Skip to content

ProGuard configuration breaks serialization #122

Open
pimlott opened this Issue Mar 23, 2012 · 4 comments

3 participants

@pimlott
pimlott commented Mar 23, 2012

The default ProGuard configuration in src/main/scala/AndroidInstall.scala is missing many of the suggested configurations in the ProGuard documentation (http://proguard.sourceforge.net/index.html#manual/examples.html), including those for serializable classes. For example, if my class relies on a readResolve method for deserialization, that method is stripped ProGuard and so deserialization breaks.

I suggest putting a more complete and conservative ProGuard configuration in sbt-android-plugin by default. I'm still learning, so I don't have a full proposal, but I would include at least:

-keepclassmembers class * implements java.io.Serializable {
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

It may be worth centrally maintaining a ProGuard configuration that works reliably for the Scala library.

@rst
rst commented May 18, 2012

FWIW, this can be worked around by adding the text suggested above to the
build settings in a project's build.scala. roughly like so:

lazy val fullAndroidSettings =
General.settings ++
AndroidProject.androidSettings ++
TypedResources.settings ++
AndroidMarketPublish.settings ++ Seq (
keyalias in Android := "change-me",
libraryDependencies += "org.scalatest" %% "scalatest" % "1.6.1" % "test",
proguardOption in Android := """
-keepclassmembers class * implements java.io.Serializable {
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
"""
)

It can be useful to do so, as storing serializable objects in a Bundle is one of the more
straightforward ways of handling saveInstanceState/restoreInstanceState in an Activity.

@rst
rst commented May 18, 2012

Candidate fix submitted as pull request #131.

@pimlott
pimlott commented May 28, 2012

I agree about your use case (storing serializable objects in a Bundle), and this is exactly what I was trying to do. I did soon realize that since so many of the standard Scala classes are polymorphic, the lack of full type checking on deserialize (even with manifests as currently available) can bite. So now I usually use my own non-polymorphic classes instead.

That said, serialization and deserialization of standard Scala classes ought to work reliably. It took me a long time to figure out what was going wrong.

@ezh
ezh commented May 29, 2012

I tried to use serialization in my projects DigiControl/DigiSSHD, but there was an errors when I passed serialized object between different apk (transport level not significant) that shared in single library with serialized object.

I have something like client-server model that based on common code (DigiLib). Inside single apk all works well (intents and so on). So I am afraid that you find that your serialized data broken if you upgrade you application someday or try to send it to other application.

Of course ,I tried to set serial number by hand and I read proguard serialization manuals. So now I use only parcelable, even for persistent storage (Google prohibit this, but I read android source code and daresay, that parcelable chunk writen relatively well for my needs)

PS I think that scala bytecode generation maybe affected, so class in pure java will be consistent. But I don't want to use java code in my project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.