1

I have interface Callback class as shown below,

public interface Callback extends Serializable {
     void onResponse(int responseCode);
}

I use the above interface to parse as params callback object, like below

private Callback callback = new Callback() {
    @Override
    public void onResponse(int responseCode) {
        switch (responseCode) {
            case ResponseCode.FACE_NOT_DETECT: {
                notifyText.setText("Face not detected");
                break;
            }
            case ResponseCode.FACE_TOO_FAR: {
                notifyText.setText("Face too far, Please get closer to the camera");
                break;
            }
            case ResponseCode.FACE_BLINK_TO_CAPTURE: {
                notifyText.setText("Blink once to capture your face image");
                break;
            }
        }
    }
};

Then I use the above callback object to send to my library

FaceDetectFragment.newInstance(callback, mode);

In this FaceDetectFragment class, I manipulate the param as below,

 public static FaceDetectFragment newInstance(Callback callback, int mode) {
    if (faceInstance != null) {
        return faceInstance;
    }
    faceInstance = new FaceDetectFragment();
    Bundle bundle = new Bundle();
    bundle.putSerializable(KEY_USER_CALLBACK, callback);
    bundle.putInt(KEY_BIOMETRIC_MODE, mode);
    faceInstance.setArguments(bundle);

    return faceInstance;
}

Then I use above setted arguments in at onCreate method as shown below,

if (getArguments() != null) {
        clientCallback = (Callback) getArguments().getSerializable(KEY_USER_CALLBACK);
        biometricMode = getArguments().getInt(KEY_BIOMETRIC_MODE);
    }

Then in here I'll use callback object several times as below,

clientCallback.onResponse(ResponseCode.FACE_NOT_DETECT);

All the functionlaties are working fine, but when I paused the app, will throw an RuntimeException, the exception is shown as below,

 Process: com.ej.face_demo_android, PID: 29679
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.ej.face_demo_android.FaceDetectActivity$2)
    at android.os.Parcel.writeSerializable(Parcel.java:1536)
    at android.os.Parcel.writeValue(Parcel.java:1484)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:733)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
    at android.os.Bundle.writeToParcel(Bundle.java:1133)
    at android.os.Parcel.writeBundle(Parcel.java:773)
    at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
    at android.os.Parcel.writeTypedArray(Parcel.java:1316)
    at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
    at android.os.Parcel.writeParcelable(Parcel.java:1505)
    at android.os.Parcel.writeValue(Parcel.java:1411)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:733)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
    at android.os.Bundle.writeToParcel(Bundle.java:1133)
    at android.os.Parcel.writeBundle(Parcel.java:773)
    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:4146)
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4148)
    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:6682)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
 Caused by: java.io.NotSerializableException: com.ej.face_demo_android.FaceDetectActivity
    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.writeObject(ObjectOutputStream.java:346)
    at android.os.Parcel.writeSerializable(Parcel.java:1531)
    at android.os.Parcel.writeValue(Parcel.java:1484) 
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:733) 
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 
    at android.os.Bundle.writeToParcel(Bundle.java:1133) 
    at android.os.Parcel.writeBundle(Parcel.java:773) 
    at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124) 
    at android.os.Parcel.writeTypedArray(Parcel.java:1316) 
    at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639) 
    at android.os.Parcel.writeParcelable(Parcel.java:1505) 
    at android.os.Parcel.writeValue(Parcel.java:1411) 
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:733) 
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408) 
    at android.os.Bundle.writeToParcel(Bundle.java:1133) 
    at android.os.Parcel.writeBundle(Parcel.java:773) 
    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:4146) 
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4148) 
    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:6682) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410) 

As my knowledge when I am pausing the app, the app trying to save the current state of the app, while saving the state, couldn't identify serialized call back to save in current state. What should I do to handle this exception?

UPDATE: When we consider about the fragment life cycle, when onPause state is triggered, the current state wi saving in the stack, Then my serialize object will wrap into to the bundle again by main thread. This is the time error occurs as I analyzed

Thanks in advance for your valuable time!

E J Chathuranga
  • 927
  • 12
  • 27
  • I don't think you should serialize the callback. It doesn't make sense to me – Vladyslav Matviienko Mar 04 '19 at 09:39
  • Please provide us HOW and WHERE you call *FaceDetectFragment.newInstance()* showing us real parameters. – emandt Mar 04 '19 at 09:57
  • @VladyslavMatviienko without serializing object how can we send a value activity to fragment? I think you probably know fragment constructor must have empty param. – E J Chathuranga Mar 04 '19 at 23:20
  • 1
    you can use a setter for example. Or make your activity implement an interface, and then in fragment do `((YourInterface)getActivity()).yourMethod();` – Vladyslav Matviienko Mar 05 '19 at 06:30
  • Yeah, it's a good solution, Cause of above issue I moved to setter already, But I need to know what was the real issue. – E J Chathuranga Mar 05 '19 at 07:24
  • You cannot serialize an interface. You can only serialize data. Why are you trying to put this `Callback` object in a `Bundle`? This makes no sense. – David Wasser Mar 05 '19 at 12:20
  • @DavidWasser, objects can serialize in java, so my interface callback object extended using serializable API. That's how we serialize the interface objects. No, we can serialize an object also. Why I put my callback function in Bundle, is when I getting new instance from my fragment I can initialze my callback when fragment object is creating. – E J Chathuranga Mar 05 '19 at 12:46
  • You do understand that if you serialize and deserialize an object, you end up with 2 different instances. They aren't the same instance. Also, since your `Callback` doesn't have any data, what is it you are trying to achieve by serializing and deserializing this? It still makes no sense what you are trying to do – David Wasser Mar 05 '19 at 12:50
  • @DavidWasser, please look closely, I've initialized the callback object. When we write an HTTP request using retrofit(as example), we can parse a callback object, that telling what will happen when a response comes. Something like that I am trying to do here mate. – E J Chathuranga Mar 05 '19 at 12:57

1 Answers1

1

To answer your question, the "real problem" is that you are trying to serialize an instance of a class, not an interface. Your class is an anonymous inner class called com.ej.face_demo_android.FaceDetectActivity$2 which you created here:

private Callback callback = new Callback() {
    @Override
    public void onResponse(int responseCode) {
      switch (responseCode) {
        case ResponseCode.FACE_NOT_DETECT: {
            notifyText.setText("Face not detected");
            break;
        }
        case ResponseCode.FACE_TOO_FAR: {
            notifyText.setText("Face too far, Please get closer to the camera");
            break;
        }
        case ResponseCode.FACE_BLINK_TO_CAPTURE: {
            notifyText.setText("Blink once to capture your face image");
            break;
        }
      }
    }
};

It isn't possible to serialize this anonymous inner class. See NotSerializableException on anonymous class for more gory details.

If you really need to do this, create a real standalone class instead of an anonymous inner class. You might have more luck with that.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Does that mean interfaces are implementing as an inner class when we creating interface instance inside of a class? – E J Chathuranga Mar 06 '19 at 05:31
  • 1
    If you create an anonymous class, then the anonymous class is implemented as an inner class, and contains a reference to the surrounding class. Also, there is no such thing as an **instance of an interface**. You can only create an **instance of a class**. In the code snippet above, you are creating an instance of an anonymous inner class that implements the interface `Callback`. – David Wasser Mar 06 '19 at 13:57
  • pretty good so far, Inner classes are encapsulated along with the main class. What if the anonymous class implements as static? – E J Chathuranga Mar 07 '19 at 04:03