由于Crashlytics没有开箱即用的可穿戴应用程序,我正在寻找一种拦截和报告运行时抛出的任何潜在异常的最佳方法。我想知道为什么他们没有自动报告给Google Play开发者控制台?
谷歌已宣布未来的Android Wear更新将内置Wi-Fi支持,但即便如此,并非所有设备都配备足够的硬件。在这种情况下,我最初的想法是创建Application
的子类并实现Thread.UncaughtExceptionHandler
。然后,必须使用MessageApi
对每个例外进行编组并发送到手机。手机上WearableListenerService
的扩展名会收到一条消息,解组该异常并将其传递给Crashlytics。
然而,这又提出了一些问题。存在可穿戴设备和手机之间的蓝牙连接中断的风险,因此所有错误都应排队并存储在可穿戴设备的文件系统中。
对于简单的崩溃报告来说,这似乎有些过分。有更简单的方法吗?
答案 0 :(得分:4)
请勿MessageApi
用于此目的,DataApi
。那你就不必担心失去蓝牙连接。
它的工作方式:
发生崩溃时,在可穿戴设备上设置DataItem
崩溃;
最终会将其发送到移动设备。
从移动设备发送有关崩溃的信息并删除DataItem
。
此处提供更多信息:http://developer.android.com/training/wearables/data-layer/index.html
答案 1 :(得分:4)
这是我的解决方案的草稿。作为@gruszczy suggested,我使用DataApi
。
可穿戴应用程序:
public class WApplication extends Application
implements Thread.UncaughtExceptionHandler {
private static final String LOG_TAG = WApplication.class.getSimpleName();
private Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler;
...
@Override
public void onCreate() {
super.onCreate();
mDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, final Throwable throwable) {
Log.e(LOG_TAG, "Uncaught exception thrown.");
WearableService.launchService(throwable, WApplication.this);
mDefaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
}
可穿戴服务:
public class WearableService extends Service {
...
public static void launchService(Throwable throwable, Context context) {
Intent startServiceIntent = new Intent(context, WearableService.class);
startService.putExtra(EXTRA_KEY_EXCEPTION, throwable);
context.startService(startServiceIntent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Throwable throwable = (Throwable) intent.getSerializableExtra(KEY_EXCEPTION);
sendExceptionToMobile(throwable);
return super.onStartCommand(intent, Service.START_REDELIVER_INTENT, startId);
}
private void sendExceptionToMobile(final Throwable throwable) {
if (throwable == null) {
return;
}
Log.d(LOG_TAG, "Sending exception to mobile...");
PutDataMapRequest putDataMapReq = PutDataMapRequest
.create(WearCommunicationConstants.PATH_EXCEPTION);
DataMap dataMap = putDataMapReq.getDataMap();
StringWriter sw = new StringWriter();
throwable.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
dataMap.putString(WearCommunicationConstants.KEY_STACK_TRACE, stackTrace);
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult =
Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
@Override
public void onResult(final DataApi.DataItemResult result) {
if (result.getStatus().isSuccess()) {
Log.d(LOG_TAG,
"DataItem synced: " + result.getDataItem().getUri());
} else {
Log.e(LOG_TAG,
"Failed to sync DataItem: " + result.getStatus().getStatusCode() + ", "
+ result.getStatus().getStatusMessage());
}
}
});
}
}
移动服务:
public class MobileService extends WearableListenerService {
...
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
Log.d(LOG_TAG, "Data changed, data event(s) received.");
for (DataEvent event : dataEvents) {
Log.d(LOG_TAG, "Data event type: " + event.getType());
switch (event.getType()) {
case DataEvent.TYPE_CHANGED:
DataItem item = event.getDataItem();
DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
switch (item.getUri().getPath()) {
case WearCommunicationConstants.PATH_EXCEPTION:
Log.e(LOG_TAG, "Received exception from a wearable device.");
String stackTrace = dataMap
.getString(WearCommunicationConstants.KEY_STACK_TRACE);
Utils.logWithCrashlytics(stackTrace);
break;
// ...
}
break;
case DataEvent.TYPE_DELETED:
// ...
}
}
}
}
答案 2 :(得分:2)
现有解决方案要求手机目前在范围内。使用Wear 2.0提供手表自主权,我们需要能够存储崩溃并在连接后将其发送出去。 WearCrashReporter就是这样做的。
我们在监视虚拟机上安装崩溃处理程序。捕获崩溃时,其跟踪和类型将序列化为json,保存到FileSystem,然后在手机可用时将其作为MessageApi消息与服务一起发送。在手机应用程序中通过WearableListenerService接收后,它将被反序列化并传递给已安装的Phone Virtual Machine的崩溃记者。
答案 3 :(得分:0)
我通过以下方式解决了这个问题:
将this lib集成到您的项目中。此lib将把所有异常从磨损应用程序传输到移动应用程序。
如果您不使用proguard - 您可以简单地使用ExceptionWear lib并将移动应用程序端的异常记录到崩溃物中。
否则
当您在移动应用程序端收到throwable时 - 您可以将其记录到crashlytics中,但是有一个问题:
如果我们使用android plugin feature构建移动+磨损应用程序,我们将会这样:
dependencies {
compile 'com.google.android.gms:play-services:5.0.+@aar'
...lots of cool libs...
wearApp project(':wear')
}
并在两个应用程序(移动和磨损)上应用crashlytics插件,然后在构建磨损应用程序期间,您可以看到在proguard任务和dex任务(gradle任务)后,crashlytics插件不会存储和上传Deobs,因此 - 在crashlytics仪表板上堆栈跟踪不会重新映射(回溯):
<强>:穿:crashlyticsCleanupResourcesRelease // EXPECTED
:磨损:crashlyticsUploadStoredDeobsRelease //预期
:磨损:crashlyticsGenerateResourcesRelease //预期强>
:wear:generateReleaseResValues UP-TO-DATE
:磨损:generateReleaseResources
:磨损:mergeReleaseResources
:磨损:processReleaseResources
:磨损:generateReleaseSources
:磨损:compileReleaseJava
:磨损:proguardRelease
:wear:dexRelease //没有crashlytics存储和上传Deobs任务
:穿:processReleaseJavaRes UP-TO-DATE
:磨损:shrinkReleaseResources 强>
但是当磨损应用程序被构建时(磨损ap就像对移动应用程序的依赖),移动应用程序构建开始,并且在移动构建过程中,crashlytics插件运行良好:
<强>:移动:crashlyticsCleanupResourcesRelease // EXPECTED
:手机:crashlyticsUploadStoredDeobsRelease //预期
:移动:crashlyticsGenerateResourcesRelease //预期强>
:mobile:generateReleaseResValues UP-TO-DATE
:手机:generateReleaseResources
:手机:mergeReleaseResourcesknown
:手机:processReleaseResources
:手机:generateReleaseSources
:手机:compileReleaseJava
:手机:proguardRelease
:手机:dexRelease
的:移动:crashlyticsStoreDeobsRelease // EXPECTED
:手机:crashlyticsUploadDeobsRelease //预期
:移动:crashlyticsCleanupResourcesAfterUploadRelease //预期强>
:手机:lintVitalRelease
:mobile:compileReleaseNdk UP-TO-DATE
:mobile:processReleaseJavaRes UP-TO-DATE
:移动:shrinkReleaseResources
因此,在标准构建过程中磨损模块deobs不会上传,但有解决方法:
如果开始构建单独使用app,然后在移动模块资源中使用manualy package wear apk,
然后成功上传了deobs,你可以在仪表板上观察到被追踪的崩溃。
但我个人不喜欢建造apk的manual way,所以我尝试做以下事项:
首先只建立穿着应用程序。 deobs将上传到crashlytics。然后使用&#39; wearApp项目运行完整版本(&#39;:穿&#39;)&#39;功能,看起来很有效。
无论如何,我正在等待崩解剂开箱即用的android-wear支持。
答案 4 :(得分:0)
可以在构建过程中上传移动设备并佩戴。
概念:
1.确保移动和磨损具有独特的映射
2.在上传之前将磨损映射合并到移动映射中
1.配置proquard(通常是proguard-rules.pro)
换穿:
-useuniqueclassmembernames
for mobile add:
-useuniqueclassmembernames
-applymapping ../wear/build/outputs/mapping/release/mapping.txt
此更改通过将磨损构建的映射应用于移动构建,确保您在移动设备上具有唯一的名称并佩戴。
2.配置构建以合并mapping.txt
添加到build.gradle of mobile:
// allows to use Crashlytics also for wear by merging the mappings of wear into the
// mappings of mobile
//noinspection GroovyAssignabilityCheck
task mergeMappings(dependsOn: "transformClassesAndResourcesWithProguardForRelease") << {
File wearMappingFile = new File("wear/build/outputs/mapping/release/mapping.txt");
File mobileMappingFile = new File("mobile/build/outputs/mapping/release/mapping.txt");
if (wearMappingFile.exists() && mobileMappingFile.exists()) {
println("merge mapping.txt")
java.nio.file.Files.copy(wearMappingFile.toPath(),
new FileOutputStream(mobileMappingFile, true))
} // else we are on the wear build and the mobile build was not yet executed
}
afterEvaluate {
project.("crashlyticsStoreDeobsRelease").dependsOn(mergeMappings);
}
在crashlyticsStoreDeobsRelease之前将磨损映射附加到移动映射。