1

我正在开发一个应用程序并且在理解或找到我遇到的错误的原因时遇到了很大的问题。完整代码可在 Github 上找到:https ://github.com/lordgreg/Sfen 。有问题的行是 ALWAYS startActivity(intent) 围绕第 608 行(https://github.com/lordgreg/Sfen/blob/master/app/src/main/java/gpapez/sfen/BackgroundService.java

这是我重现错误的方法:

  • 创建新的配置文件,它可以有一个“动作”来创建新的快捷方式(小部件) - 它实际上将 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 intent\n" + act.getSetting("shortcut_intent"));

            startActivity(intent);

显示错误的行

 at gpapez.sfen.BackgroundService.runProfileActions(BackgroundService.java:647)

正是:

startActivity(intent);

如果我然后尝试重新打开应用程序,我总是会得到上面的异常。现在是转折点......崩溃后等待一段时间(+ 1分钟)重新打开应用程序没有问题,我可以继续打开所有内容,直到下一次崩溃。

请帮助我了解为什么会发生这种情况......我什至愿意付钱给发现并解决这个谜团的人(非法参数异常和错误接收广播意图都导致行 startActivity(intent))!这是我唯一可以表达我对帮助我的感激之情!

谢谢!

4

1 回答 1

0

我将回答我自己的问题,因为我终于找到了崩溃的原因。

  1. 如前所述,当保存配置文件操作时,在我们的例子中是快捷方式,我不得不保存快捷方式意图。由于 Gson 抱怨 Uri (java.lang.RuntimeException: Failed to invoke private android.net.Uri() with no args),你必须创建自己的 Serializer 和 Deserializer 类并将它们传递给 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
}

如您所见,即使我们实现了 Serializer 和 Deserializer,也会出现一些差异。

建议?

切勿使用 GSON 来保存意图。无论意图如何,您都可以将其存储为字符串并通过以下方式很好地接收它:

// 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)
于 2014-08-05T06:17:04.643 回答