我正在开发一个应用程序,并有一个非常大的问题理解或找到我得到的错误的原因。完整的代码可在Github: https://github.com/lordgreg/Sfen。有问题的行是608行(https://github.com/lordgreg/Sfen/blob/master/app/src/main/java/gpapez/sfen/BackgroundService.java)周围的ALWAYS startActivity(intent)
下面是我重现错误的方法:- 创建新的配置文件,它可以有一个"动作",创建新的快捷方式(小部件)-它实际上保存意图作为Gson字符串(我不得不使用(反)序列化,因为Uri)。
- 我可以运行这个配置文件(点击它只是运行所有的动作)很多次,我想和意图将运行没有任何问题。
- 现在,有"事件"在特殊条件下触发,除了运行特定的配置文件外不做任何其他事情(与再次点击配置文件相同)。这个作品。事件的条件得到满足,我发送广播EVENT_ENABLED,接收器得到它,它启动触发配置文件的函数,运行动作和sendActivity与它从Gson获得的意图一起工作。其完美的。 问题来了,当我关闭应用程序,重新打开它。
- 然后,接收器向我发送一个信号来重新运行事件(当我单击它时工作,如果我手动单击配置文件)。
这里有一个错误的例子:
08-04 21:27:50.065 21621-21621/gpapez.sfen E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: gpapez.sfen, PID: 21621
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.STATE_CHANGE flg=0x4000010 (has extras) } in gpapez.sfen.Receiver@44b7a678
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:791)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:212)
at android.app.ActivityThread.main(ActivityThread.java:5151)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException
at android.os.Parcel.nativeAppendFrom(Native Method)
at android.os.Parcel.appendFrom(Parcel.java:436)
at android.os.Bundle.writeToParcel(Bundle.java:1679)
at android.os.Parcel.writeBundle(Parcel.java:641)
at android.content.Intent.writeToParcel(Intent.java:7026)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2084)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.ContextImpl.startActivity(ContextImpl.java:1079)
at android.app.ContextImpl.startActivity(ContextImpl.java:1061)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:311)
at gpapez.sfen.BackgroundService.runProfileActions(BackgroundService.java:647)
at gpapez.sfen.BackgroundService.runEventActions(BackgroundService.java:749)
at gpapez.sfen.BackgroundService.EventFinder(BackgroundService.java:346)
at gpapez.sfen.Receiver.onReceive(Receiver.java:189)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:781)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:212)
at android.app.ActivityThread.main(ActivityThread.java:5151)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
或另一个:
08-04 21:38:30.950 22971-22971/gpapez.sfen E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: gpapez.sfen, PID: 22971
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.STATE_CHANGE flg=0x4000010 (has extras) } in gpapez.sfen.Receiver@451087f0
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:791)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:212)
at android.app.ActivityThread.main(ActivityThread.java:5151)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException
at android.os.Parcel.nativeAppendFrom(Native Method)
at android.os.Parcel.appendFrom(Parcel.java:436)
at android.os.Bundle.writeToParcel(Bundle.java:1679)
at android.os.Parcel.writeBundle(Parcel.java:641)
at android.content.Intent.writeToParcel(Intent.java:7026)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2084)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.ContextImpl.startActivity(ContextImpl.java:1079)
at android.app.ContextImpl.startActivity(ContextImpl.java:1061)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:311)
at gpapez.sfen.BackgroundService.runProfileActions(BackgroundService.java:647)
at gpapez.sfen.BackgroundService.runEventActions(BackgroundService.java:749)
at gpapez.sfen.BackgroundService.EventFinder(BackgroundService.java:346)
at gpapez.sfen.Receiver.onReceive(Receiver.java:189)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:781)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:212)
at android.app.ActivityThread.main(ActivityThread.java:5151)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
当这种情况发生时,我的应用程序变得不可用,我必须进入系统设置并清除应用程序本身的数据。之后,我可以重新运行,创建概要文件,创建显示概要文件的事件我可以触发我的快捷操作它只运行以下代码:
/**
* get Intent from saved setting
*
* http://stackoverflow.com/questions/22533432/create-object-from-gson-string-doesnt-work
*/
class UriDeserializer implements JsonDeserializer<Uri> {
@Override
public Uri deserialize(final JsonElement src, final Type srcType,
final JsonDeserializationContext context) throws JsonParseException {
return Uri.parse(src.getAsString());
}
}
Gson gsonIntent = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
.create();
Intent intent = gsonIntent.fromJson(act.getSetting("shortcut_intent"), Intent.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
System.out.println("*** Opening intentn" + act.getSetting("shortcut_intent"));
startActivity(intent);
显示错误的行
at gpapez.sfen.BackgroundService.runProfileActions(BackgroundService.java:647)
就是:
startActivity(intent);
如果我尝试重新打开应用程序,我总是得到上面的异常。现在问题来了……等待一段时间后崩溃(+1分钟)重新打开应用程序没有问题,我可以继续打开所有东西,直到下一次崩溃。
请告诉我为什么会发生这种情况…我甚至愿意支付给发现并解决之谜的人(非法参数异常和错误接收广播意图,两者都导致行startActivity(意图))!这是我唯一能表达对你帮助我的感激之情的东西!
谢谢!
我将回答我自己的问题,因为我终于找到了崩溃的原因。
- 如前所述,当保存配置文件操作时,在我们的案例中,我必须保存快捷方式意图。自从Gson抱怨Uri (java.lang。运行时异常:调用私有android.net.Uri()失败,没有参数),你必须创建自己的序列化器和反序列化器类,并将它们传递给Gson对象。
之后,你终于可以使用Gson将Intent对象保存为String。它看起来像这样:
{
"mAction": "android.intent.action.VIEW",
"mData": "http://www.amazon.com/",
"mExtras": {
"mParcelledData": {
"mOwnsNativeParcelObject": true,
"mNativePtr": -1197637952
},
"mHasFds": false,
"mFdsKnown": true,
"mAllowFds": true
},
"mFlags": 0
}
在你需要转换成Intent的字符串之后,你可以这样调用它:
Intent intent = new Gson().fromJson(act.getSetting(MY_INTENT_STRING, Intent.class);
因为这没有引起任何问题,Intent被创建了,一切都比预期的好,但是,经过2天的设置断点和逐行检查代码,这里是我们得到的实际fromGson()字符串:
{
"mAction": "android.intent.action.VIEW",
"mData": "http://www.amazon.com/",
"mExtras": {
"mMap": {
"com.android.browser.application_id": "-2531992419148236456"
},
"mHasFds": false,
"mFdsKnown": true,
"mAllowFds": true
},
"mFlags": 0
}
如您所见,即使我们实现了序列化器和反序列化器,也会出现一些差异。
建议吗?
永远不要使用GSON来保存意图。无论目的是什么,您都可以将其存储为string,并使用 很好地接收它。// like this to save intent
String mySavedIntent = intent.toUri(Intent.URI_INTENT_SCHEME)
和
// like this to retrieve intent from string
intent = Intent.parseUri(mySavedIntent, Intent.URI_INTENT_SCHEME)