I have an app that crashes at random times when I don't have a computer nearby to view logcat. Therefore I want to write the reason for a fatal error / every error to a file on my phone that I can read later to debug. I tried using try catch, but I am looking for a complete solution, like a command I enter once and it captures every crash and saves it, like an observer above the code respectively a kind of virtual box.
Which command helps me here?
Using a file for this is a bad idea - Not only do you possible have to worry about extra permissions but you also have to write a fair amount of code.
There are many libraries out there to catch Exceptions and log them for you.
Furthermore in a live environment this won't work at catching bugs since you can't ask users to send them a log file.
I use Fabric (Firebase)
https://firebase.google.com/docs/crashlytics/get-started
You're probably looking for Thread.UncaughtExceptionHandler or even better, Firebase Crashlytics.
I to wanted something similar, the solution that I came up with that works a bit was a Debug Log activity in the app that reads the logcat output in to a TextView.
I then Start this activity from a Menu Item or Button to show previous crashes.
Normally Android Studio Logcat window is just opening a remote shell on to the device with ADB and running the logcat command on the Android Device.
This method runs the logcat command on the Device itself without the need of a remote shell, but you need some Java code in your app to do this.
(This Extra Activity has to be in the Same App as you only have permission to see you own App's logcat)
(This does not always seem to pick up always all Log output but it does pickup crashes)
NOTE
The try and catch in this example code has nothing to do with trying to catch the errors Alex is Hunting as some people thought but to catch a possible error in the logcat display code. The logcat text shown by this Activity will show stack traces of those errors Alex is hunting.
This could then be run after restarting the app.
Code to do this is (Note you need to replace the "YOUR_APPS_TAG" with the Log TAG used by your app) See https://developer.android.com/studio/command-line/logcat for the filter specs
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class DebugLogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug_log);
try {
Process process = Runtime.getRuntime().exec("logcat -d -D -v long " + "YOUR_APPS_TAG" + ":V *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line );
log.append(System.getProperty("line.separator"));
}
TextView tv = (TextView)findViewById(R.id.debugLog);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setTextIsSelectable(true);
tv.setText(log.toString());
} catch (IOException e) {
if (BuildConfig.LOG) {
Log.e("YOUR_APPS_TAG", "DebugLogActivity:onCreate:" + e.toString() + Arrays.toString(e.getStackTrace()));
}
}
}
}
The xml (actvitiy_debug_log.xml) for this extra activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".debuglogActivity">
<TextView
android:id="#+id/debugLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars = "vertical"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
Example ScreenShot of running Activity after a crash
You can then copy and paste the text out and send it to yourself or just read it in the app.
Related
I am new to Android Studio. I successfully created a Hello World app from the example in Android website. Now, I want to play around by using some statement to print in the logcat but it doesn't works. Below is my ApplicationTest.java code:
package com.example.abc.myloggingapplication;
import android.app.Application;
import android.test.ApplicationTestCase;
import android.util.Log;
/**
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
Log.d("MyTest", "Here goes the output!"); // THIS IS THE NEW STATEMENT INSERTED BUT PRINTS NOTHING IN CONSOLE LOG IN ANDROID STUDIO SDK.
}
}
Other files are same as provided by the Hello World example in Android website. In Android Studio sdk, I entered the logcat to debug but still no luck. Can anybody point me out where I am going wrong.
Check your logcat:
Check View -> Tool windows -> Android Monitor.
Or Alt + 6
If that doesnt help, make sure you have an instance of your class. Otherwise the constructor is never called and therefor the log.d is never called.
Edit:
As other's have stated: Check if you are running the Test Application, if you want to do so. Otherwise make sure you code in your actual application and not your test application.
I'm developing a multi-tab application. In one of the tab I want to show the logcat but I have a lot of problem running it correctly.
Right now I'm using the following command but I don't get anything in my TextView. :
Process process = Runtime.getRuntime().exec("/system/bin/logcat -s com.vittorio:I");
But when I run the same command into Terminal it works flawlessy.
I've also tryed this other command :
Process process = Runtime.getRuntime().exec("/system/bin/logcat *:I");
but for some reason it prints also Debug level messages ...
EDIT (1):
I've by-passed the problem by adding an high-level filter (java) to the whole log.. so I only print in my textview what I need. It's a very dirty solution but for now is the only one I managed to come with.
I would like to point out that I'me experiencing different behaviours on my phones :
Galaxy S Plus (rooted) : I can see the log.
Galaxy Y (rooted) : No log
Nexus One (not-rooted) : No log
EDIT (2) - SOLVED (NEED ROOTED PHONE):
After some struggling I managed to solve my problem. Actually navigating through the init.rc system file I saw that the permissions for /dev/log/main and /dev/log/system where setted to 620.. that's why I couldn't open the log on some of my phones. So I rooted also my Nexus One and added this commands into my activity before calling the logcat command :
Process process_su = Runtime.getRuntime().exec("su");
Process process_ch = Runtime.getRuntime().exec("chmod 777 /dev/log/main");
Done! :D
Hope this info will help anyone who will face my same issue.
You have to use this permission :
<uses-permission android:name="android.permission.READ_LOGS" />
and then you can use that snippet i found
try {
Process process = Runtime.getRuntime().exec("logcat -v");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder logString=new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
logString.append(line);
}
TextView tv = (TextView)findViewById(R.id.logTextView);
tv.setText(logString.toString());
} catch (IOException e) {
}
I didn't try it but it seems correct
Is it possible to capture MMI result in Android?
I need to do things like put on hold, merge calls, etc. and as the only telephony events in android are NEW_OUTGOING_CALL, RINGING, OFFHOOK and IDLE, I need to get the result when i dial any MMI code like Held Code.
Is it possible?
The best solution for me would be to find some way to discover when an outgoing call gets actually connected. Maybe has somebody find any workaround for that?
I made some progress in that question reading system logs (LogCat) and searching for determinate strings, but it seems that logs differs between models and SO versions so this is not a consistent aproach.
Thanks for your help!
Maybe you can get it using RIL(Radio Interface Layer)
try something like:
1) adb device shell
2) logcat -b radio
// Navigate to the page that you have dial *#06# in dialpad then execute jar below to get the IMEI result
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import android.util.Log;
public class SIM_Info_Reader_png extends UiAutomatorTestCase{
public void getPromptedIMEI() throws UiObjectNotFoundException {
UiObject list = new UiObject(new UiSelector().resourceId("android:id/text1"));
int i = 0;
System.out.println("IMEI=" + list.getText());
}
}
I'm trying to use Jsoup 1.6.0 in my Android application, but for some reason it crashes. I simplified my code to:
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class JsoupTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Document d = Jsoup.connect("http://www.google.com").get();
} catch (Exception e) {
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG);
t.show();
}
}
}
But whenever I run the above on my phone (in USB debugging mode) or on the emulator, I get the message that my program has unexpectedly crashed--an error wasn't even caught. If I replace the contents of the try block with
Jsoup.connect("http://www.google.com");
the program works fine, so it seems like the get() method is causing the problems...
FYI, in my AndroidManifest.xml I did include
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
in the correct place, and R.layout.main is the default layout that the ADT generates when you create a new project. I'm using Android API level 7 for this project. How do I get this to work?
Try to download new version of Jsoup and paste jsoup-1.6.x.jar in libs folder from your project.
you can't do Network operations from the UI thread, so you should take the JSoup.connect() out of your onCreate() and use an ASyncTask
I am completely new to android, and pretty much a Java newb.
I have a simple app that I am building to get the hang of android's development environment - and things like click events, etc..
The app loads, and I am able to change the text in a textfield using a button handler. However, when I import the location class, and try to do a simple GPS call, the application crashes.
The problem is, everything looks good in Eclipse (error console) - and I'm not seeing any exceptions in the android emulator (DevTools). I have the logcat window open, but I haven't done anything in eclipse/code to send logcat anything (do I need to?)
Can anyone see something wrong with this? Is there a better way to troubleshoot?
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
import android.location.*;
public class locationDisplay extends Activity {
private EditText text;
private Location GPSLocation;
double dblLat;
double dblong;
String strLat;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // bind the layout to the activity
text = (EditText) findViewById(R.id.EditText01);
text.setText("No button pressed");
}
// Handler for each button -- Button01 is when it crashes
public void myClickHandler(View view) {
switch (view.getId()) {
case R.id.Button01:
dblLat = GPSLocation.getLatitude();
strLat = Double.toString(dblLat);
text.setText(strLat);
break;
case R.id.Button02:
text.setText("Button 2 was clicked");
break;
case R.id.Button03:
text.setText("Button 3 was clicked");
break;
}
}
You shouldn't need to write anything to get the default messages in LogCat; uncaught exception reports should appear automatically when your program crashes. However, sometimes LogCat and your emulator get disconnected from each other and the messages simply all disappear. Simply close Eclipse and the emulator, restart them both, and the messages should reappear. An easy way to tell whether the link has been re-established is during the boot-up of the emulator. Just as the flashing "ANDROID" text in the fancy font disappears bringing you to the lockscreen, you should see about a hundred lines of text flash by on LogCat. If that doesn't happen, then LogCat isn't getting its messages.
The way to display debugging messages in Android is to use the Log.d("some name for your log statements so you can filter the LogCat messages", "The actual debug statement here");. You'll often find people using things like a static final String LOG_TAG in their application so that they can make sure their logs always have the same tag, and hence, the filter never misses a message.
As for your actual code here, Rpond is right, you never initialised your GPSLocation object.
You GPSLocation object is null. You need to access the LocationService to get a current location. And with the emulator you will need to manually send locations.
Location Services
Sometimes LogCat 'forgets' you have a device/emulator connected and running. It seems like this happens after you have a device and an emulator online at the same time and then you disconnect one of them. If you are getting nothing from LogCat, go to Window>Show View>Other>Devices and then click the device that you want to log.