Android 位置跟踪器在很长时间后崩溃
Android location tracker crashes after a long time
我创建了一个位置跟踪应用程序,每次位置更改时都会写入本地 SQLite 数据库。
不幸的是,该应用程序在跟踪时大约 7-8 小时后崩溃,不幸的是,当我将设备连接到调试器时,这种情况不会发生,因此没有我可以附加的日志。
更多可能有用的信息:
- 应用程序在从后台唤醒之前崩溃(在跟踪数据中可以清楚地看到),因此我可以从其他应用程序中排除此错误
- 尝试写入文本文件而不是数据库但没有成功(崩溃前 运行 大约 3 小时)
- 更改跟踪间隔(5s 正常 1s 最快间隔):同样的结果应用程序也在 7-8 小时后崩溃
以下是一些代码片段:
位置更改事件
@Override
public void onLocationChanged(Location location) {
if(location == null){
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(location == null) {
return;
}
}
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
ActivitylogRepo activityRepo = new ActivitylogRepo(this);
Activitylog activity = new Activitylog();
activity.activity = "Position";
activity.timestamp = getDateTime();
activity.value2 = String.valueOf(currentLatitude);
activity.value3 = String.valueOf(currentLongitude);
activityRepo.insert(activity);
}
数据库插入命令
public int insert(Activitylog activitylog) {
//Open connection to write data
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Activitylog.KEY_activity, activitylog.activity);
values.put(Activitylog.KEY_timestamp, activitylog.timestamp);
values.put(Activitylog.KEY_value1, activitylog.value1);
values.put(Activitylog.KEY_value2, activitylog.value2);
values.put(Activitylog.KEY_value3, activitylog.value3);
values.put(Activitylog.KEY_value4, activitylog.value4);
// Inserting Row
long activitylog_id = db.insert(Activitylog.TABLE, null, values);
db.close(); // Closing database connection
return (int) activitylog_id;
}
正在初始化服务
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(20 * 1000) // 20s in ms
.setFastestInterval(5 * 1000); // 5s in ms
我有一些东西可以帮助您捕获崩溃报告,即使您没有连接到调试器 - 从而帮助您找到问题的根源!我已将此作为答案发布,因此我可以很好地格式化它。
下面的 class 将处理未捕获的异常,将它们打包到电子邮件中并在您的 phone 上放置通知(您可以根据需要进行调整)
public class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private Context mContext;
private java.lang.Thread.UncaughtExceptionHandler mDefaultUEH;
public UncaughtExceptionHandler(Context context, java.lang.Thread.UncaughtExceptionHandler defaultUEH) {
mContext = context;
mDefaultUEH = defaultUEH;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Make error into something more readable
String timestamp = android.text.format.DateFormat.getLongDateFormat(mContext).format(
new Date(System.currentTimeMillis()));
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
ex.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
// Create email intent for error
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/html");
emailIntent.putExtra(Intent.EXTRA_EMAIL, "email address");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Crash Report " + timestamp);
emailIntent.putExtra(Intent.EXTRA_TEXT, stacktrace);
// Make into pending intent for notifcation
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
Intent.createChooser(emailIntent, "Send report with.."),
Intent.FLAG_ACTIVITY_NEW_TASK);
// here create a notification for the user
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
builder.setContentTitle("Crash Caught");
builder.setContentText("Send to Developer");
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_notification);
// Finally display the notification!
NotificationManager mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1337, builder.build());
// re-throw critical exception further to the os (important)
mDefaultUEH.uncaughtException(thread, ex);
}
}
在您的应用程序 class 中这样设置:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
/*
* Set up uncaught exception handler
*/
java.lang.Thread.UncaughtExceptionHandler defaultUEH =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new
UncaughtExceptionHandler(this, defaultUEH));
}
}
我不建议在您的发布版本中包含此代码!届时,您可以使用 Developer Console 获取崩溃报告。
我创建了一个位置跟踪应用程序,每次位置更改时都会写入本地 SQLite 数据库。 不幸的是,该应用程序在跟踪时大约 7-8 小时后崩溃,不幸的是,当我将设备连接到调试器时,这种情况不会发生,因此没有我可以附加的日志。 更多可能有用的信息:
- 应用程序在从后台唤醒之前崩溃(在跟踪数据中可以清楚地看到),因此我可以从其他应用程序中排除此错误
- 尝试写入文本文件而不是数据库但没有成功(崩溃前 运行 大约 3 小时)
- 更改跟踪间隔(5s 正常 1s 最快间隔):同样的结果应用程序也在 7-8 小时后崩溃
以下是一些代码片段:
位置更改事件
@Override
public void onLocationChanged(Location location) {
if(location == null){
location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(location == null) {
return;
}
}
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
ActivitylogRepo activityRepo = new ActivitylogRepo(this);
Activitylog activity = new Activitylog();
activity.activity = "Position";
activity.timestamp = getDateTime();
activity.value2 = String.valueOf(currentLatitude);
activity.value3 = String.valueOf(currentLongitude);
activityRepo.insert(activity);
}
数据库插入命令
public int insert(Activitylog activitylog) {
//Open connection to write data
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Activitylog.KEY_activity, activitylog.activity);
values.put(Activitylog.KEY_timestamp, activitylog.timestamp);
values.put(Activitylog.KEY_value1, activitylog.value1);
values.put(Activitylog.KEY_value2, activitylog.value2);
values.put(Activitylog.KEY_value3, activitylog.value3);
values.put(Activitylog.KEY_value4, activitylog.value4);
// Inserting Row
long activitylog_id = db.insert(Activitylog.TABLE, null, values);
db.close(); // Closing database connection
return (int) activitylog_id;
}
正在初始化服务
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(20 * 1000) // 20s in ms
.setFastestInterval(5 * 1000); // 5s in ms
我有一些东西可以帮助您捕获崩溃报告,即使您没有连接到调试器 - 从而帮助您找到问题的根源!我已将此作为答案发布,因此我可以很好地格式化它。
下面的 class 将处理未捕获的异常,将它们打包到电子邮件中并在您的 phone 上放置通知(您可以根据需要进行调整)
public class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private Context mContext;
private java.lang.Thread.UncaughtExceptionHandler mDefaultUEH;
public UncaughtExceptionHandler(Context context, java.lang.Thread.UncaughtExceptionHandler defaultUEH) {
mContext = context;
mDefaultUEH = defaultUEH;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Make error into something more readable
String timestamp = android.text.format.DateFormat.getLongDateFormat(mContext).format(
new Date(System.currentTimeMillis()));
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
ex.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
// Create email intent for error
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/html");
emailIntent.putExtra(Intent.EXTRA_EMAIL, "email address");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Crash Report " + timestamp);
emailIntent.putExtra(Intent.EXTRA_TEXT, stacktrace);
// Make into pending intent for notifcation
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
Intent.createChooser(emailIntent, "Send report with.."),
Intent.FLAG_ACTIVITY_NEW_TASK);
// here create a notification for the user
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
builder.setContentTitle("Crash Caught");
builder.setContentText("Send to Developer");
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_notification);
// Finally display the notification!
NotificationManager mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1337, builder.build());
// re-throw critical exception further to the os (important)
mDefaultUEH.uncaughtException(thread, ex);
}
}
在您的应用程序 class 中这样设置:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
/*
* Set up uncaught exception handler
*/
java.lang.Thread.UncaughtExceptionHandler defaultUEH =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new
UncaughtExceptionHandler(this, defaultUEH));
}
}
我不建议在您的发布版本中包含此代码!届时,您可以使用 Developer Console 获取崩溃报告。