Hier ist die vollständige Lösung (fast: Ich habe das Layout der Benutzeroberfläche und die Handhabung der Schaltflächen weggelassen) - abgeleitet aus vielen Experimenten und verschiedenen Beiträgen von anderen, die sich auf Probleme bezogen, die auf dem Weg auftauchten.
Es gibt eine Reihe von Dingen, die Sie tun müssen:
- Behandeln Sie uncaughtException in Ihrer Application-Unterklasse.
- Starten Sie nach dem Abfangen einer Ausnahme eine neue Aktivität, um den Benutzer zum Senden eines Protokolls aufzufordern.
- Extrahieren Sie die Protokollinformationen aus den logcat-Dateien und schreiben Sie in Ihre eigene Datei.
- Starten Sie eine E-Mail-App und stellen Sie Ihre Datei als Anhang bereit.
- Manifest: Filtern Sie Ihre Aktivität, um von Ihrem Ausnahmebehandler erkannt zu werden.
- Richten Sie Proguard optional so ein, dass Log.d () und Log.v () entfernt werden.
Hier sind die Details:
(1 & 2) Behandeln Sie uncaughtException und starten Sie das Senden der Protokollaktivität:
public class MyApplication extends Application
{
public void onCreate ()
{
// Setup handler for uncaught exceptions.
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
@Override
public void uncaughtException (Thread thread, Throwable e)
{
handleUncaughtException (thread, e);
}
});
}
public void handleUncaughtException (Thread thread, Throwable e)
{
e.printStackTrace(); // not all Android versions will print the stack trace automatically
Intent intent = new Intent ();
intent.setAction ("com.mydomain.SEND_LOG"); // see step 5.
intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application
startActivity (intent);
System.exit(1); // kill off the crashed app
}
}
(3) Protokoll extrahieren (ich habe dies in meine SendLog-Aktivität eingefügt):
private String extractLogToFile()
{
PackageManager manager = this.getPackageManager();
PackageInfo info = null;
try {
info = manager.getPackageInfo (this.getPackageName(), 0);
} catch (NameNotFoundException e2) {
}
String model = Build.MODEL;
if (!model.startsWith(Build.MANUFACTURER))
model = Build.MANUFACTURER + " " + model;
// Make file name - file must be saved to external storage or it wont be readable by
// the email app.
String path = Environment.getExternalStorageDirectory() + "/" + "MyApp/";
String fullName = path + <some name>;
// Extract to file.
File file = new File (fullName);
InputStreamReader reader = null;
FileWriter writer = null;
try
{
// For Android 4.0 and earlier, you will get all app's log output, so filter it to
// mostly limit it to your app's output. In later versions, the filtering isn't needed.
String cmd = (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) ?
"logcat -d -v time MyApp:v dalvikvm:v System.err:v *:s" :
"logcat -d -v time";
// get input stream
Process process = Runtime.getRuntime().exec(cmd);
reader = new InputStreamReader (process.getInputStream());
// write output stream
writer = new FileWriter (file);
writer.write ("Android version: " + Build.VERSION.SDK_INT + "\n");
writer.write ("Device: " + model + "\n");
writer.write ("App version: " + (info == null ? "(null)" : info.versionCode) + "\n");
char[] buffer = new char[10000];
do
{
int n = reader.read (buffer, 0, buffer.length);
if (n == -1)
break;
writer.write (buffer, 0, n);
} while (true);
reader.close();
writer.close();
}
catch (IOException e)
{
if (writer != null)
try {
writer.close();
} catch (IOException e1) {
}
if (reader != null)
try {
reader.close();
} catch (IOException e1) {
}
// You might want to write a failure message to the log here.
return null;
}
return fullName;
}
(4) Starten Sie eine E-Mail-App (auch in meiner SendLog-Aktivität):
private void sendLogFile ()
{
String fullName = extractLogToFile();
if (fullName == null)
return;
Intent intent = new Intent (Intent.ACTION_SEND);
intent.setType ("plain/text");
intent.putExtra (Intent.EXTRA_EMAIL, new String[] {"log@mydomain.com"});
intent.putExtra (Intent.EXTRA_SUBJECT, "MyApp log file");
intent.putExtra (Intent.EXTRA_STREAM, Uri.parse ("file://" + fullName));
intent.putExtra (Intent.EXTRA_TEXT, "Log file attached."); // do this so some email clients don't complain about empty body.
startActivity (intent);
}
(3 & 4) So sieht SendLog aus (Sie müssen jedoch die Benutzeroberfläche hinzufügen):
public class SendLog extends Activity implements OnClickListener
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature (Window.FEATURE_NO_TITLE); // make a dialog without a titlebar
setFinishOnTouchOutside (false); // prevent users from dismissing the dialog by tapping outside
setContentView (R.layout.send_log);
}
@Override
public void onClick (View v)
{
// respond to button clicks in your UI
}
private void sendLogFile ()
{
// method as shown above
}
private String extractLogToFile()
{
// method as shown above
}
}
(5) Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
<!-- needed for Android 4.0.x and eariler -->
<uses-permission android:name="android.permission.READ_LOGS" />
<application ... >
<activity
android:name="com.mydomain.SendLog"
android:theme="@android:style/Theme.Dialog"
android:textAppearance="@android:style/TextAppearance.Large"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="com.mydomain.SEND_LOG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
(6) Setup Proguard:
Ändern Sie in project.properties die Konfigurationszeile. Sie müssen angeben , „optimieren“ oder Proguard wird nicht entfernen Log.v () und Log.d () Anrufe.
proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt
Fügen Sie in proguard-project.txt Folgendes hinzu. Dies weist Proguard an, anzunehmen, dass Log.v und Log.d keine Nebenwirkungen haben (obwohl dies der Fall ist, da sie in die Protokolle schreiben) und daher während der Optimierung entfernt werden können:
-assumenosideeffects class android.util.Log {
public static int v(...);
public static int d(...);
}
Das ist es! Wenn Sie Verbesserungsvorschläge haben, lassen Sie es mich bitte wissen und ich kann dies aktualisieren.