I'm developing an app and have a really big problem understanding or finding the cause of the errors I'm getting. Full code is available on Github: https://github.com/lordgreg/Sfen. The problematic line is ALWAYS startActivity(intent) around line 608 (https://github.com/lordgreg/Sfen/blob/master/app/src/main/java/gpapez/sfen/BackgroundService.java)
Here's how I reproduce the error:
Here Is One Example of error:
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)
Or another:
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)
When this happens, my app becomes unusable, I have to go into system settings and clear data for the app itself. After that, I can rerun, create profile again, create event which shows profile and i can trigger my shortcut actions which just run this code:
/**
* 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);
The line for which errors show
at gpapez.sfen.BackgroundService.runProfileActions(BackgroundService.java:647)
is exactly:
startActivity(intent);
If I then try to reopen app, I always get Exception above. Now here is the twist... waiting a while after crash (+1min) reopens app without a problem and I can continue opening everything until next crashes.
Please help me out on why is this happening... I'm even willing to pay to the person that finds out and solves the mistery (Illegal Argument Exception and Error Receiving Broadcast Intent that both lead to line startActivity(intent))! Its the only thing with which I could express my gratitude on helping me out!
Thank you!
I will answer my own question since I've managed to finally find a reason for crashing.
After that, you can finally save Intent object to String using Gson. It would look something like this:
{
"mAction": "android.intent.action.VIEW",
"mData": "http://www.amazon.com/",
"mExtras": {
"mParcelledData": {
"mOwnsNativeParcelObject": true,
"mNativePtr": -1197637952
},
"mHasFds": false,
"mFdsKnown": true,
"mAllowFds": true
},
"mFlags": 0
}
And after you need the string converted Intent, you would call it like:
Intent intent = new Gson().fromJson(act.getSetting(MY_INTENT_STRING, Intent.class);
Since this didn't caused any problems, Intent was created, everything better than expected, BUT, after 2 days of setting breakpoints and checking code line by line, here is actual fromGson() string we get:
{
"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
}
As you see, even if we implemented Serializer and Deserializer, some differences occur.
Suggestion?
NEVER USE GSON TO SAVE INTENT. No matter the intent, you can store it to string and receive it out nicely with:
// like this to save intent
String mySavedIntent = intent.toUri(Intent.URI_INTENT_SCHEME)
and
// like this to retrieve intent from string
intent = Intent.parseUri(mySavedIntent, Intent.URI_INTENT_SCHEME)