My activity 'used' the put a custom (serializable) class in the bundle when starting a Service
. But couple version back I had remove it (and delete the class) and directly put primitives in the bundle.
And now... my ACRA log is getting completely hammered by this error of a crash in the onStartCommand
when on the line the bundle is read.
java.lang.RuntimeException: Unable to start service com.xxx.MyService@db4c909 with Intent { act=ACTION_START flg=0x4 cmp=com.xxx/.MyService (has extras) }: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.xxx.MyBundle)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3045)
at android.app.ActivityThread.access$2200(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1454)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5551)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.xxx.MyBundle)
at android.os.Parcel.readSerializable(Parcel.java:2491)
at android.os.Parcel.readValue(Parcel.java:2294)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2592)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.get(BaseBundle.java:281)
at com.xxx.MyService.onStartCommand(MyService.java:190)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3028)
....
... 14 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.xxx.MyBundle" on path: DexPathList[[zip file "/data/app/com.xxx-2/base.apk"],nativeLibraryDirectories=[/data/app/com.xxx-2/lib/arm, /data/app/com.xxx-2/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
I don't get what I'm getting error knowing that the com.xxx.MyBundle
doesn't even exist anymore in the project!
Note that Im seeing this error in my crash logs. I cannot reproduce this locally probably because I have uninstalled and reinstall the app many times and this it probably fixes the problem.
The issue here is that there thousands of people which the app is probably crashing and cannot just tell to everyone "uninstall- reinstall". I'd like to find the cause of this and possibily fix it with a new update without the user having to manually uninstall the app and reinstall..
EDIT
This is the history of event
v1: I was putting a Serializable class in the bundle when starting the service (I had forgotten to set the serialVersionUID) and I was seeing a lot of serialization error when starting the service like version mismatch when desializing.. typical error when forgetting the serialVersionUID
v2: I have added serialVersionUID=-1 in my Serializable class (No dice, in the log I was still seeing these serialization is now saying found version={random number} but was -1....
v3: I gave up and deleted com.xx.MyBundle and created a com.xx.MyBundle2 (no Dice.. and this is when I started to see in the log that ClassNotFoundException)
v4: I Delete com.xx.MyBundle2 and instead of putting the serializable class in the bundle I put directly my primitives
So you see.. it is not a question of service running or not.. Even when my users update from v3 to v4 I would have expect this error to be gone but no... I still see the ClassNotFoundExcpetionn in v4
As I guess from your question, you might have started a Service
with a previous version of your application which was removed lately along with the classes used. Its causing the ClassNotFoundException
.
So, in this specific case, you might consider detecting the application update and on application update you need to check if the Service
is running in background which needs to be stopped.
To check for your newer version of application is installed you'll receive a broadcast event called ACTION_MY_PACKAGE_REPLACED and then you stop the running Service
.
To check if your desired Service
is already running, you might consider having a checker like this.
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
And then call it using
if(isMyServiceRunning(MyService.class))
stopMyService();
Update
I think I've understood your problem correctly and thought of a solution above already. I guess, the Service
you started already in your v1 or v2 is running and expecting the bundle of serialized class there. So you need to stop the service and start it again to make it follow the current behaviour which you're expecting.