box / box-android-preview-sdk

Box Android Preview SDK
Apache License 2.0
13 stars 10 forks source link

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.box.androidsdk.content.models.BoxSession) #13

Closed dshbq closed 6 years ago

dshbq commented 7 years ago

Hello, I am using box preview sdk 'com.box:box-android-preview-sdk:2.0.4' , I am using the following code to launch boxPreviewActivity from my Activity:

 private void launchPreview(BoxItem boxItem) {

        BoxFile file = new BoxFile(boxItem.toJsonObject());
        ///mPathToRoot = file.getPathCollection().getEntries();
        BoxFolder parentFolder = file.getParent() == null ? BoxFolder.createFromId("0") : file.getParent();
        BoxPreviewActivity.IntentBuilder builder = BoxPreviewActivity.createIntentBuilder(this, session, file).setBoxFolder(parentFolder);
        //set the box folder, so the sdk can page through other files in the directory for images, audio or video
        startActivityForResult(builder.createIntent(), PREVIEW_FILE_REQUEST_CODE);
    }

In my code, i get boxItem from API response which i further use to create boxFile, but i get following exception when trying to call above method, it looks like some serliazation exception but why for BoxSession we are getting this error

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.box.androidsdk.content.models.BoxSession)
                                                       at android.os.Parcel.writeSerializable(Parcel.java:1526)
                                                       at android.os.Parcel.writeValue(Parcel.java:1474)
                                                       at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
                                                       at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
                                                       at android.os.Bundle.writeToParcel(Bundle.java:1133)
                                                       at android.os.Parcel.writeBundle(Parcel.java:763)
                                                       at android.content.Intent.writeToParcel(Intent.java:8702)
                                                       at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3140)
                                                       at android.app.Instrumentation.execStartActivity(Instrumentation.java:1584)
                                                       at android.app.Activity.startActivityForResult(Activity.java:4228)
                                                       at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
                                                       at android.app.Activity.startActivityForResult(Activity.java:4187)
                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
                                                       at com.test.box.activity.ItemDetailActivity.launchPreview(ItemDetailActivity.java:371)
                                                       at com.test.box.activity.ItemDetailActivity.access$600(ItemDetailActivity.java:52)
                                                       at com.test.box.activity.ItemDetailActivity$4.onClick(ItemDetailActivity.java:271)
                                                       at android.view.View.performClick(View.java:5612)
                                                       at android.view.View$PerformClick.run(View.java:22285)
                                                       at android.os.Handler.handleCallback(Handler.java:751)
                                                       at android.os.Handler.dispatchMessage(Handler.java:95)
                                                       at android.os.Looper.loop(Looper.java:154)
                                                       at android.app.ActivityThread.main(ActivityThread.java:6123)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
                                                    Caused by: java.io.NotSerializableException: com.test.box.activity.ItemDetailActivity
                                                       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
                                                       at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
                                                       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
                                                       at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
                                                       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
                                                       at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
                                                       at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:454)
                                                       at com.box.androidsdk.content.models.BoxSession.writeObject(BoxSession.java:927)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:977)
                                                       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1536)
                                                       at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
                                                       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
                                                       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
                                                       at android.os.Parcel.writeSerializable(Parcel.java:1521)
                                                       at android.os.Parcel.writeValue(Parcel.java:1474) 
                                                       at android.os.Parcel.writeArrayMapInternal(Parcel.java:723) 
                                                       at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 
                                                       at android.os.Bundle.writeToParcel(Bundle.java:1133) 
                                                       at android.os.Parcel.writeBundle(Parcel.java:763) 
                                                       at android.content.Intent.writeToParcel(Intent.java:8702) 
                                                       at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3140) 
                                                       at android.app.Instrumentation.execStartActivity(Instrumentation.java:1584) 
                                                       at android.app.Activity.startActivityForResult(Activity.java:4228) 
                                                       at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50) 
                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79) 
                                                       at android.app.Activity.startActivityForResult(Activity.java:4187) 
                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859) 
                                                       at com.test.box.activity.ItemDetailActivity.launchPreview(ItemDetailActivity.java:371) 
                                                       at com.test.box.activity.ItemDetailActivity.access$600(ItemDetailActivity.java:52) 
                                                       at com.test.box.activity.ItemDetailActivity$4.onClick(ItemDetailActivity.java:271) 
                                                       at android.view.View.performClick(View.java:5612) 
                                                       at android.view.View$PerformClick.run(View.java:22285) 
                                                       at android.os.Handler.handleCallback(Handler.java:751) 
                                                       at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                       at android.os.Looper.loop(Looper.java:154) 
                                                       at android.app.ActivityThread.main(ActivityThread.java:6123) 
                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 

Could you please check and it let me know the issue here.

Thanks!!

doncung commented 7 years ago

Part of our logic serializes and deserializes sessions now instead of trying to recreate the session based on the user. This is to better handle shared links and device pinning as well as other custom types of sessions. I was trying out your logic with 2.04 using a shared link and a BoxSharedLinkSession with some slight modification, and was unable to reproduce. Can you share the json you are using in that boxItem in your test? (You can call toJson() as well as modify it replacing any sensitive info with stars I will need the file extension) Also how are you authenticating/using the session? Are you subclassing BoxSession? (Right before passing it to the builder print session.getAuthInfo().toJson() are all fields populated?) Are you doing anything in your build.gradle file (i.e. using other libraries including ours, support libraries, targetting a certain version)?

Hopefully I will be able to reproduce your issue, which will allow me to debug further.

dshbq commented 7 years ago

@doncung Thanks for the reply!! i am using boxSession as a static object in my base class, and in each class check for null for boxSession, and if it is null i initialise it again. Regarding other json, i m using that line to create boxFile since from server response i get BoxItem when trying to fetch files but launch method takes BoxFile as parameter.

Hope it helps you to understand the issue.

doncung commented 7 years ago

Are you ever extending the BoxSession anonymously? The preview sdk does work with static sessions (it will essentially clone it) however because it uses serialization it does not work with anonymous classes. I can reproduce your issue if that is the case. One thing that can be done is you can create a new class that extends BoxSession or a static class (Depending on what you are doing you might need to implement the readObject/writeObject methods) You can also clone your session into a normal BoxSession before passing into the builder in which case it should no longer be anonymous.

dshbq commented 7 years ago

@doncung I checked my session creation logic, i am using below code in my base class from :


  protected void initSession(){
        BoxAuthentication.BoxAuthenticationInfo info = new BoxAuthentication.BoxAuthenticationInfo();
        info.setAccessToken(PreferenceManager.getInstance().getAppUserToken(this));

        MyAuthenticationRefreshProvider refreshProvider = new MyAuthenticationRefreshProvider();
        BoxAuthentication.getInstance().setRefreshProvider(refreshProvider);
        session = new BoxSession(this, info, refreshProvider);

        session.authenticate();
        addSessionAuthListener();
    }

    public class MyAuthenticationRefreshProvider implements Serializable, BoxAuthentication.AuthenticationRefreshProvider {
        @Override
        public BoxAuthentication.BoxAuthenticationInfo refreshAuthenticationInfo(BoxAuthentication.BoxAuthenticationInfo info) throws BoxException {
            BoxAuthentication.BoxAuthenticationInfo newInfo = new BoxAuthentication.BoxAuthenticationInfo();
            newInfo.setAccessToken(PreferenceManager.getInstance().getAppUserToken(BaseActivity.this));
            return newInfo;
        }

        @Override
        public boolean launchAuthUi(String userId, BoxSession session) {
            return true;
        }
    }

The above sets a refresh provider in boxSession object. So in the above code if i change the line
session = new BoxSession(this, info, refreshProvider);

to session = new BoxSession(this, info, null);

Preview has started working but setting the refresh provider during the boxSession creation was to add refresh provider for box session token. Please let me know if any change is required for session creation logic along with Refresh provider.

Thanks!!

doncung commented 7 years ago

Since you are calling BoxAuthentication.getInstance().setRefreshProvider(refreshProvider);

It should be unnecessary to set the provider into the individual sessions as this does it globally. The intent of the session constructor was to handle multiple sessions with potentially different providers.

doncung commented 7 years ago

I also tried this with your logic, and you can still use the refresh provider in the sdk if you make the "MyAuthenticationRefreshProvider" class static or by creating a separate java file for it. The sdk seems to have trouble serializing/deserializing it as just an inner public class.