0

This is my Interface class

interface InstallerInterface {
     fun onInstallation(context: Context)
}

I implements the interface in this class

class FirstActivity : InstallerInterface{
    override fun onInstallation(context: Context) {
         *MyCode*
    }
}

I have tried to pass this context using intent to

 val intent=Intent(context,SecondActivity::class.java)
        intent.putExtra("NAME",name)
        intent.putExtra("Callback",Interface)
        context.startActivity(intent)    

But intent.putExtra was causing error Cannot resolve method 'putExtra() . So I implements Serializable in FirstActivity() class. But that was causing error

06-11 12:28:57.323  4042  4042 E AndroidRuntime: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = FirstAcitvity)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Parcel.writeSerializable(Parcel.java:1535)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Parcel.writeValue(Parcel.java:1483)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Parcel.writeArrayMapInternal(Parcel.java:732)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1417)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Bundle.writeToParcel(Bundle.java:1157)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Parcel.writeBundle(Parcel.java:772)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.content.Intent.writeToParcel(Intent.java:8703)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3082)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1520)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.Activity.startActivityForResult(Activity.java:4229)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:676)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.Activity.startActivityForResult(Activity.java:4187)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:663)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.Activity.startActivity(Activity.java:4526)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.Activity.startActivity(Activity.java:4494)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at foundation.e.apps.XAPK.LaunchUtils.startInstallSplitApksActivity(LaunchUtils.kt:15)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at foundation.e.apps.XAPK.ViewUtils$installXApk$1.onCompedApks(ViewUtils.kt:57)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at foundation.e.apps.XAPK.XApkInstallUtils$installSplitApks$2.run(XApkInstallUtils.kt:191)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Handler.handleCallback(Handler.java:751)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:95)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:154)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:6186)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
06-11 12:28:57.323  4042  4042 E AndroidRuntime: Caused by: java.io.NotSerializableException: ThirdAcivity()
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
06-11 12:28:57.323  4042  4042 E AndroidRuntime:        at android.os.Parcel.writeSerializable(Parcel.java:1530)
06-11 12:28:57.323  4042

I believe ThirdActivity() implements the FirstActivity() and I was not implementing Serializable in ThirdAcivity. So I implement Serializable in ThirdAcitivity . And I was getting error on every Activity which uses FirstAcivity. This is a large project and I can't implement Serializable on every Acitivity. So I implement Parcelable instead. My code is

@Parcelize
class FirstActivity : InstallerInterface, Parcelable{
    override fun onInstallation(context: Context) {
         *MyCode*
    }
}

And I was getting error like java.lang.RuntimeException: Parcel: unable to marshal value How can I fix this code. If not, What could be better alternative. Thank you in advance

  • 1
    Why you want pass an Interface to another class? Can you please add more details? – Alpha 1 Jun 11 '20 at 07:50
  • I think you want to listen to an event using the interface implemented in FirstActivity from SecondActivity? If that is the case try using startActivityForResult method. You can chain this to get results even from 3rd activity to 1st activity https://developer.android.com/training/basics/intents/result – Jude Osbert K Jun 11 '20 at 08:10
  • If you want to use context in non-activity class then you can try this answer https://stackoverflow.com/questions/17917968/get-context-in-non-activity-class – Amit Tiwary Jun 11 '20 at 09:17
  • I want to call the interface function`onInstallation()` of `FirstActivity()` from `SecondActivity` . Like `callback.onInstallation`. I was not able to pass the interface using `intent.putExtra` to `SecondActivity`. The main idea is to get the context of the interface class – Dayona Joseph Jun 11 '20 at 09:23
  • https://gitlab.e.foundation/DayonaJ/apps/-/commit/685cbb5952e7374b7925f0ff8712f4bdf1c60606. Here is what Iam doing. I want to call `onInstalationComplete()` of class `Application.kt` (which is `InstallerInterface.kt` method) from `InstallSplitApksActivity.kt` – Dayona Joseph Jun 11 '20 at 09:55

2 Answers2

0

Yours' activities should't implement Parcelable/Serializable. Also passing activity references may cause memory leaks and app crushes (https://proandroiddev.com/everything-you-need-to-know-about-memory-leaks-in-android-d7a59faaf46a, https://techbeacon.com/app-dev-testing/what-you-need-know-about-android-app-memory-leaks)

If you want to do something in another activity and return result to the first activity you could use startActivityForResult or new Activity Result APIs. More information https://developer.android.com/training/basics/intents/result

ZSergei
  • 807
  • 10
  • 18
  • I don't want return result from activity. I just want to know when activity ends. I have tried `startActivityForResult` . But `onActivityResult` is not called. – Dayona Joseph Jun 12 '20 at 05:49
  • Here is my code. ``` fun startInstallSplitApksActivity(context: Activity, apksBean: ApksBean, callback:InstallerInterface) { val intent =installSplitApksActivity.newInstanceIntent(context, apksBean, callback) context.startActivityForResult(intent, 1) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode==1) { if (resultCode == Activity.RESULT_OK) { myCode() } } } ``` – Dayona Joseph Jun 12 '20 at 05:49
  • `I just want to know when activity ends` - I think event that activity ends is some kind of result. Yours code with `startActivityForResult` looks good, but don't you forget to call `setResult()` at InstallActivity before calling `finish()`? – ZSergei Jun 12 '20 at 07:52
  • Yes, added `setResult()`.But override `nextStep()` is from another class-BaseActivity().Is that the issue? `override fun nextStep() { super.nextStep() apksBean = intent.getParcelableExtra(KEY_PARAM) if (apksBean == null || apksBean!!.splitApkPaths.isNullOrEmpty()){ val intent = Intent() setResult(Activity.RESULT_OK) finish() }` `abstract class BaseActivity : RxAppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) nextStep() }` – Dayona Joseph Jun 15 '20 at 09:21
0

You cannot "pass an interface". An "interface" is an abstract thing. What you want to pass is a concrete implementation of that interface, ie: an object (that happens to implement your interface). When you instantiate your "interface" (in your example, like this:

intent.putExtra("testInterface", new ITest() {
    @Override 
    void onSuccess(String text) {
    }
}

However, even if you did that, it would not solve your problem. What you need to understand is that you can't pass objects (instances) by putting them as "extras" in an Intent. When you do that, Android actually serializes and then deserializes the object so that you end up with 2 objects, one is a serialized/deserialized copy of the original.

For more Details:->

Diksha Pruthi
  • 276
  • 2
  • 5