Androidアプリケーションからクラッシュデータ(少なくともスタックトレース)を取得するにはどうすればよいですか。少なくともケーブルで検索されている自分のデバイスで作業しているとき、しかし理想的には私がそれを改良しそしてよりしっかりしたものにすることができるように野生で走っている私のアプリケーションのインスタンスから。
ACRA(Android用アプリケーションクラッシュレポート) ライブラリを試してみてください。
ACRAは、AndroidアプリケーションがクラッシュレポートをGoogleDocフォームに自動的に投稿できるようにするライブラリです。 Androidアプリケーションの開発者を対象に、クラッシュしたり誤って動作したりしたときにアプリケーションからデータを取得できるようにします。
あなたのアプリにインストールするのは簡単で、高度な設定が可能で、どこにでもサーバースクリプトをホストする必要はありません。レポートはGoogle Docスプレッドシートに送信されます。
サンプルアプリケーションとデバッグの目的で、デバイスのsdカードにスタックトレースを書き込んだり、サーバーにアップロードしたりできる簡単な解決策を使用します。この解決法は、Project Android-remote-stacktrace (具体的には、デバイスへの保存とサーバーへのアップロードの部分)に触発されており、Soonilが言及した問題を解決すると思います。これは最適ではありませんが、機能するので、本番アプリケーションで使用する場合は改善することができます。スタックトレースをサーバーにアップロードする場合は、phpスクリプト(index.php
)を使用してそれらを表示できます。あなたが興味を持っているなら、あなたはあなたのアプリケーションのための1つのJavaクラスとアップロードされたスタックトレースをホストするサーバのための2つのオプションのphpスクリプトの下にあるすべてのソースを見つけることができます。
コンテキスト(メインアクティビティなど)では、次のように呼び出します。
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
"/sdcard/<desired_local_path>", "http://<desired_url>/upload.php"));
}
CustomExceptionHandler
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
private String localPath;
private String url;
/*
* if any of the parameters is null, the respective functionality
* will not be used
*/
public CustomExceptionHandler(String localPath, String url) {
this.localPath = localPath;
this.url = url;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
String timestamp = TimestampFormatter.getInstance().getTimestamp();
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = timestamp + ".stacktrace";
if (localPath != null) {
writeToFile(stacktrace, filename);
}
if (url != null) {
sendToServer(stacktrace, filename);
}
defaultUEH.uncaughtException(t, e);
}
private void writeToFile(String stacktrace, String filename) {
try {
BufferedWriter bos = new BufferedWriter(new FileWriter(
localPath + "/" + filename));
bos.write(stacktrace);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendToServer(String stacktrace, String filename) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("filename", filename));
nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
try {
httpPost.setEntity(
new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
}
}
upload.php
<?php
$filename = isset($_POST['filename']) ? $_POST['filename'] : "";
$message = isset($_POST['stacktrace']) ? $_POST['stacktrace'] : "";
if (!ereg('^[-a-zA-Z0-9_. ]+$', $filename) || $message == ""){
die("This script is used to log debug data. Please send the "
. "logging message and a filename as POST variables.");
}
file_put_contents($filename, $message . "\n", FILE_APPEND);
?>
index.php
<?php
$myDirectory = opendir(".");
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
closedir($myDirectory);
$indexCount = count($dirArray);
sort($dirArray);
print("<TABLE border=1 cellpadding=5 cellspacing=0 \n");
print("<TR><TH>Filename</TH><TH>Filetype</th><th>Filesize</TH></TR>\n");
for($index=0; $index < $indexCount; $index++) {
if ((substr("$dirArray[$index]", 0, 1) != ".")
&& (strrpos("$dirArray[$index]", ".stacktrace") != false)){
print("<TR><TD>");
print("<a href=\"$dirArray[$index]\">$dirArray[$index]</a>");
print("</TD><TD>");
print(filetype($dirArray[$index]));
print("</TD><TD>");
print(filesize($dirArray[$index]));
print("</TD></TR>\n");
}
}
print("</TABLE>\n");
?>
BugSense を試すこともできます。 BugSenseはすべてのクラッシュレポートを収集して分析し、意味のある視覚的なレポートを提供します。無料で、統合するためのコードは1行だけです。
免責事項:私は共同創設者です
Android 2.2では、Android Market Applicationsからクラッシュレポートを自動的に取得することが可能になりました。
Androidマーケットアプリの新しいバグ報告機能により、開発者はユーザーからクラッシュレポートとフリーズレポートを受け取ることができます。レポートは、発行者アカウントにログインしたときに利用可能になります。
http://developer.Android.com/sdk/Android-2.2-highlights.html
Thread.setDefaultUncaughtExceptionHandler()
でこれらの例外を処理することは可能ですが、これはAndroidの例外処理方法を台無しにするようです。私はこの性質のハンドラを使おうとしました:
private class ExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex){
Log.e(Constants.TAG, "uncaught_exception_handler: uncaught exception in thread " + thread.getName(), ex);
//hack to rethrow unchecked exceptions
if(ex instanceof RuntimeException)
throw (RuntimeException)ex;
if(ex instanceof Error)
throw (Error)ex;
//this should really never happen
Log.e(Constants.TAG, "uncaught_exception handler: unable to rethrow checked exception");
}
}
しかし、例外を再スローしても、Androidがそれが発生したコンポーネントをシャットダウンできるようにしながら例外をログに記録するなど、希望する動作を取得できなかったため、しばらくしてあきらめました。
私は質問が古すぎると思います、そして私の答えが同じ問題を抱えている他の人のために役立つことを願っています...
Crashlytics を試してみてください。それはあなたのアプリケーションを持っているすべてのデバイス上のすべてのクラッシュへの詳細な洞察力を与え、電子メールを通してあなたに通知を送るでしょう。
さて、私はrrainnとSoonilから提供されたサンプルをよく見ました、そしてエラー処理を台無しにしない解決策を見つけました。
CustomExceptionHandlerを変更して、新しいものを関連付けるThreadの元のUncaughtExceptionHandlerを格納するようにしました。新しい "uncaughtException"の終わりに - メソッド私が保存したUncaughtExceptionHandlerを使って古い関数を呼び出すだけです。
DefaultExceptionHandlerクラスにはsthが必要です。このような:
public class DefaultExceptionHandler implements UncaughtExceptionHandler{
private UncaughtExceptionHandler mDefaultExceptionHandler;
//constructor
public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler)
{
mDefaultExceptionHandler= pDefaultExceptionHandler;
}
public void uncaughtException(Thread t, Throwable e) {
//do some action like writing to file or upload somewhere
//call original handler
mStandardEH.uncaughtException(t, e);
// cleanup, don't know if really required
t.getThreadGroup().destroy();
}
}
http://code.google.com/p/Android-remote-stacktrace のコードにその修正を加えると、あなたはあなたのWebサーバまたはSDカードにその分野でログインするための優れた実用的な基盤を持つことになります。
私は Crittercism 私のAndroidおよびiOSアプリ - を使っています - それらについてtechcrunchで聞きました。これまでのところ彼らとかなり幸せです!
Google Play Developers Consoleでは、クラッシュしてレポートを送信したアプリのスタックトレースが実際に表示されます。また、情報を確認するのに役立つ優れたチャートもあります。以下の例を参照してください。
私はここで私自身のバージョンを作りました: http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html
基本的には同じことですが、レポートの送信にhttp接続ではなくメールを使用しています。さらに重要なことに、アプリケーションのバージョン、OSのバージョン、電話モデル、使用可能なメモリなどの情報をレポートに追加しました。 。
これを使用して例外の詳細を把握します。
String stackTrace = Log.getStackTraceString(exception);
これをデータベースに保存してログを管理します。
ライブラリだけでなく、全体の(単純な)サービスを使用することもできます。私達の会社はちょうどそのためのサービスをリリースしました: http://apphance.com 。
それはあなたが追加して5分で統合する簡単な.jarライブラリ(Android用)を持ち、それからライブラリはクラッシュ情報だけでなく実行中のアプリケーションからのログも収集します。全体のコンテキスト(デバイスの回転、それがWiFiに接続されているかどうかなど)。あなたはあなたのアプリケーションとのセッション、クラッシュ、ログ、統計などを追跡することができるとても素敵で便利なウェブパネルを使ってログを見ることができます。このサービスは現在クローズドベータテスト段階にありますが、あなたはアクセスを要求することができます、そして、我々はあなたにそれを非常に速く与えます。
免責事項:私はPolideaのCTOであり、サービスの共同作成者です。
私がこの答えを見つける手助けをしてくれたおかげでStackoverflow
に参考資料がありました。
あなたは あなたのEメールにあなたのリモートAndroidクラッシュレポートを直接見つけることができます 。 CustomExceptionHandlerクラスの中にあなたのメールアドレスを入れる必要があることを忘れないでください 。
public static String sendErrorLogsTo = "[email protected]" ;
必要な手順:
1)あなたの活動のonCreateであなたのコードのこのセクションを使用してください。
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
}
私のphpscriptによると、2nd)(rrainn)のCustomExceptionHandlerクラスのこのオーバーライドされたバージョンを使用してください。
package com.vxmobilecomm.activity;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.io.PrintWriter;
import Java.io.StringWriter;
import Java.io.Writer;
import Java.lang.Thread.UncaughtExceptionHandler;
import Java.util.ArrayList;
import Java.util.List;
import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.NameValuePair;
import org.Apache.http.client.ClientProtocolException;
import org.Apache.http.client.HttpClient;
import org.Apache.http.client.entity.UrlEncodedFormEntity;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.entity.BufferedHttpEntity;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.Apache.http.message.BasicNameValuePair;
import Android.app.Activity;
import Android.content.Context;
import Android.content.pm.ApplicationInfo;
import Android.content.pm.PackageManager;
import Android.content.pm.PackageManager.NameNotFoundException;
import Android.os.AsyncTask;
import Android.util.Log;
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
public static String sendErrorLogsTo = "[email protected]" ;
Activity activity;
public CustomExceptionHandler(Activity activity) {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
this.activity = activity;
}
public void uncaughtException(Thread t, Throwable e) {
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = "error" + System.nanoTime() + ".stacktrace";
Log.e("Hi", "url != null");
sendToServer(stacktrace, filename);
StackTraceElement[] arr = e.getStackTrace();
String report = e.toString() + "\n\n";
report += "--------- Stack trace ---------\n\n";
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
report += "-------------------------------\n\n";
report += "--------- Cause ---------\n\n";
Throwable cause = e.getCause();
if (cause != null) {
report += cause.toString() + "\n\n";
arr = cause.getStackTrace();
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
}
report += "-------------------------------\n\n";
defaultUEH.uncaughtException(t, e);
}
private void sendToServer(String stacktrace, String filename) {
AsyncTaskClass async = new AsyncTaskClass(stacktrace, filename,
getAppLable(activity));
async.execute("");
}
public String getAppLable(Context pContext) {
PackageManager lPackageManager = pContext.getPackageManager();
ApplicationInfo lApplicationInfo = null;
try {
lApplicationInfo = lPackageManager.getApplicationInfo(
pContext.getApplicationInfo().packageName, 0);
} catch (final NameNotFoundException e) {
}
return (String) (lApplicationInfo != null ? lPackageManager
.getApplicationLabel(lApplicationInfo) : "Unknown");
}
public class AsyncTaskClass extends AsyncTask<String, String, InputStream> {
InputStream is = null;
String stacktrace;
final String filename;
String applicationName;
AsyncTaskClass(final String stacktrace, final String filename,
String applicationName) {
this.applicationName = applicationName;
this.stacktrace = stacktrace;
this.filename = filename;
}
@Override
protected InputStream doInBackground(String... params)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(
"http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php?");
Log.i("Error", stacktrace);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
6);
nameValuePairs.add(new BasicNameValuePair("data", stacktrace));
nameValuePairs.add(new BasicNameValuePair("to",sendErrorLogsTo));
nameValuePairs.add(new BasicNameValuePair("subject",applicationName));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity1 = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(
entity1);
is = bufHttpEntity.getContent();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
@Override
protected void onPostExecute(InputStream result) {
super.onPostExecute(result);
Log.e("Stream Data", getStringFromInputStream(is));
}
}
// convert InputStream to String
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
これは非常に野蛮ですが、どこでもlogcatを実行することが可能であるため、迅速で汚いハックはどんなキャッチブロックに追加することですgetRuntime().exec("logcat >> /sdcard/logcat.log");
Fabricというツールがあります。これはクラッシュ分析ツールです。これを使用すると、アプリケーションのライブデプロイ時および開発中にクラッシュレポートを取得できます。あなたのアプリケーションにこのツールを追加することも同様に簡単でした。あなたのアプリケーションがクラッシュしたとき、クラッシュのそのレポートはあなたのfabric.ioダッシュボードから見ることができます。レポートは自動的に取得されました。ユーザーに許可を求めません。彼/彼女がバグ/クラッシュレポートを送りたいかどうか。そしてこれは完全に無料です... https://get.fabric.io/ /
Google Firebase は、お使いの携帯電話にクラッシュ/エラーデータを提供するためのGoogleの最新の(2016)方法です。あなたのbuild.gradleファイルにそれを含めます。
compile 'com.google.firebase:firebase-crash:9.0.0'
致命的なクラッシュはユーザーの入力を必要とせずに自動的に記録されます。また、致命的でないクラッシュやその他のイベントを記録することもできます。
try
{
}
catch(Exception ex)
{
FirebaseCrash.report(new Exception(ex.toString()));
}
このページの回答の多くは役に立ちますが、古くなるのは簡単です。 AppBrainのWebサイトでは、現在最も人気のあるクラッシュ報告ソリューションを見つけることができるように統計が集計されています。
この写真を投稿した時点では、Crashlyticsはアプリの5.24%、インストールの12.38%で使用されています。
Sherlock というこのAndroidライブラリがあります。それはあなたにデバイスとアプリケーション情報と一緒にクラッシュの完全なレポートを与えます。クラッシュが発生するたびに、通知バーに通知が表示され、通知をクリックするとクラッシュの詳細が表示されます。電子メールやその他の共有オプションを使ってクラッシュの詳細を他の人と共有することもできます。
インストール
Android {
dataBinding {
enabled = true
}
}
compile('com.github.ajitsing:sherlock:1.0.0@aar') {
transitive = true
}
デモ
私たちは自社製のシステムを社内で使用していますが、これは非常に役立ちます。クラッシュレポートをサーバーに送信するAndroidライブラリと、レポートを受信して分析を行うサーバーです。サーバーは、例外名、スタックトレース、メッセージによって例外をグループ化します。修正が必要な最も重要な問題を特定するのに役立ちます。私たちのサービスは現在パブリックベータ版ですので、誰でも試すことができます。あなたは http://watchcat.co でアカウントを作成することができます - あるいはあなたはそれがデモアクセスを使ってどのように動くかを見ることができます http://watchcat.co/reports/index.php?demo 。
今ではFirebase Crashレポートは非常に人気があり、使いやすくなっています。詳細については、次のリンクを参照してください。 Firebase Crash Reporting
お役に立てば幸いです。
すぐに答えが欲しいなら、 logcat を使うことができます。
$adb Shell logcat -f /sdcard/logoutput.txt *:E
今ログにジャンクが多すぎる場合は、まずそれをクリアしてみてください。
$adb Shell logcat -c
それからあなたのアプリを実行してから、もう一度logcatしてみてください。
エラーレポートを追跡するためのもう1つ優れたWebアプリケーションが見つかりました。
構成する手順の数が少ない。
Mint.initAndStartSession(YourActivity.this, "api_key");
Android { ... repositories { maven { url "https://mint.splunk.com/gradle/"} } ... } dependencies { ... compile "com.splunk.mint:mint:4.4.0" ... }
Mint.initAndStartSession(YourActivity.this、 "api_key");
それでおしまい。あなたがログインしてあなたのアプリケーションダッシュボードに行くと、あなたはすべてのエラーレポートを得るでしょう。
誰かに役立つことを願っています。
代替のクラッシュ報告/例外追跡サービスのチェックアウトのために Raygun.io - それはあなたのアプリにプラグインするときのまともなユーザーエクスペリエンスを含むAndroidクラッシュを扱うためのたくさんのNiceロジックを持っています(メインの2行のコードAndroidManifestに貼り付けられたアクティビティと数行のXML。
アプリがクラッシュすると、スタックトレース、ハード/ソフトウェアの環境データ、ユーザー追跡情報、指定したカスタムデータなどが自動的に取得されます。これは非同期でAPIに送信されるため、UIスレッドはブロックされずにキャッシュされます。利用可能なネットワークがない場合はディスクに。
免責事項:私はAndroidプロバイダを構築しました:)
ACRAを使い始めました https://github.com/ACRA/acra バックエンドとしてGoogleフォームを使用していて、設定と使用が非常に簡単です。これがデフォルトです。
しかし、Googleフォームへのレポートの送信は廃止予定(その後削除)される予定です。 https://plus.google.com/118444843928759726538/posts/GTTgsrEQdN6https://github.com/ACRA/acra/wiki/Googleフォームスプレッドシート使用上の注意
とにかくあなた自身の送信者を定義することは可能です https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender 例えば送信者にEメールを送信することを試みることができます。
最小限の労力でbugsenseにレポートを送信することが可能です: http://www.bugsense.com/docs/Android#acra
_ nb _ bugsenseの無料アカウントは毎月500レポートまでです。
私は Bugsnag の創設者の一人です。 Bugsnagは自動的にAndroidアプリの未処理の例外をキャプチャし、それを私たちのダッシュボードに送ります。
クラッシュ報告システムを選択または構築する際に考慮すべきいくつかの重要な事項と、いくつかのコードスニペットがあります。
Androidでのクラッシュ処理/報告に関するベストプラクティスを見たい場合は、Bugsnagの クラッシュ報告ライブラリ の完全なソースコードをチェックしてください。アプリケーション!
パーティーに遅れて、私はACRAがすべての中で最良の選択肢であることを支持し、信じています。セットアップと設定が簡単です。私はACRAを使用してクラッシュレポートを取得し、MandrillApを使用して自分の電子メールアドレスに同じメールを送信するために、世界中からの入力を含む詳細なガイドを作成しました。
Githubのサンプルプロジェクトへのリンク: https://github.com/ayushhgoyal/AcraSample
Android Studioで直接これを行うことができます。お使いの携帯電話を接続してアプリを実行し、クラッシュさせるだけでAndroid Studioで直接スタックトレースを表示できます。
グーグルはあなたが実際に得るクラッシュレポートの量を変更しました。以前は手動で報告されたバグレポートしかありませんでした。
前回の開発者カンファレンスおよび Android Vitals の導入以来、診断データを共有することができるようになったユーザーからクラッシュレポートを受け取ることもできます。
ユーザーが使用状況と診断データを自動的に共有することを選択したAndroidデバイスから収集されたすべてのクラッシュが表示されます。過去2ヶ月間のデータが入手可能です。
Flurry analytics クラッシュ情報、ハードウェアモデル、Androidのバージョン、およびライブアプリの使用状況の統計を表示します。新しいSDKでは、より詳細なクラッシュ情報を提供しているようです http://www.flurry.com/flurry-crash-analytics.html 。
あなたのアプリが他の人によってダウンロードされていてリモートデバイスでクラッシュしている場合は、Androidのエラー報告ライブラリ( this SO post で参照)を調べてください。それがあなた自身のローカルデバイス上にある場合は、LogCatを使うことができます。クラッシュが発生したときにデバイスがホストマシンに接続されていなかったとしても、デバイスを接続してadb logcatコマンドを発行すると、logcatの履歴全体がダウンロードされます無限ではありません。どちらかの方法であなたの質問に答えますか?そうでなければ、あなたはもう少し探しているものを明確にしようとすることができますか?