带有 Parcelable 的 Intent 如何在两个 App 之间传递?

Posted

技术标签:

【中文标题】带有 Parcelable 的 Intent 如何在两个 App 之间传递?【英文标题】:How does the Intent with Parcelable pass between two App? 【发布时间】:2019-07-21 05:37:56 【问题描述】:

我在 android app2 中有服务。我想从 app1 启动 Service,并将 Intent 中的 Album 对象传递给 app2 中的 Service。

在 app1 中

var alb: Album = Album()
alb.name="album name"
alb.numOfSongs=1
alb.thumbnail=2

var serviceIntent: Intent = Intent();
var componentName: ComponentName = ComponentName("com.eusecom.demoad","com.eusecom.demoad.view.EkasaService")
serviceIntent.setComponent(componentName)
serviceIntent.putExtra("albumpar", alb)
context.startService(serviceIntent)

在服务类的 app2 中

@Override
public int onStartCommand(Intent intent, int flags, int startId) 

    Album alb = intent.getParcelableExtra("albumpar");


我可以在 Intent 中传递字符串。如果我将 Parcelable 放入 Intent 中,则会出错。

02-27 14:12:18.438 22198-22198/com.eusecom.demoad E/Parcel:解组时找不到类:com.eusecom.samshopersung.models.Album java.lang.ClassNotFoundException: com.eusecom.samshopersung.models.Album 在 java.lang.Class.classForName(本机方法) 在 java.lang.Class.forName(Class.java:400) 在 android.os.Parcel.readParcelableCreator(Parcel.java:2517) 在 android.os.Parcel.readParcelable(Parcel.java:2471) 在 android.os.Parcel.readValue(Parcel.java:2374) 在 android.os.Parcel.readArrayMapInternal(Parcel.java:2727) 在 android.os.BaseBundle.unparcel(BaseBundle.java:269) 在 android.os.BaseBundle.getString(BaseBundle.java:992) 在 android.content.Intent.getStringExtra(Intent.java:6743) 在 com.eusecom.demoad.view.EkasaService.onStartCommand(EkasaService.java:29) 在 android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3685) 在 android.app.ActivityThread.-wrap23(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1740) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 引起:java.lang.ClassNotFoundException:在路径上找不到类“com.eusecom.samshopersung.models.Album”:DexPathList [[zip file“/data/app/com.eusecom.demoad-1/base.apk "],nativeLibraryDirectories=[/data/app/com.eusecom.demoad-1/lib/arm64, /system/lib64, /vendor/lib64]] 在 dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:380) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:312) 在 java.lang.Class.classForName(本机方法) 在 java.lang.Class.forName(Class.java:400) 在 android.os.Parcel.readParcelableCreator(Parcel.java:2517) 在 android.os.Parcel.readParcelable(Parcel.java:2471) 在 android.os.Parcel.readValue(Parcel.java:2374) 在 android.os.Parcel.readArrayMapInternal(Parcel.java:2727) 在 android.os.BaseBundle.unparcel(BaseBundle.java:269) 在 android.os.BaseBundle.getString(BaseBundle.java:992) 在 android.content.Intent.getStringExtra(Intent.java:6743) 在 com.eusecom.demoad.view.EkasaService.onStartCommand(EkasaService.java:29) 在 android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3685) 在 android.app.ActivityThread.-wrap23(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1740) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 02-27 14:12:18.439 22198-22198/com.eusecom.demoad D/AndroidRuntime: 关闭虚拟机 02-27 14:12:18.440 22198-22198/com.eusecom.demoad E/AndroidRuntime: 致命异常: main 进程:com.eusecom.demoad,PID:22198 java.lang.RuntimeException: Unable to start service com.eusecom.demoad.view.EkasaService@fe9af21 with Intent cmp=com.eusecom.demoad/.view.EkasaService launchParam=MultiScreenLaunchParams mDisplayId=0 mFlags=0 (有附加功能) : android.os.BadParcelableException: 解组时 ClassNotFoundException: com.eusecom.samshopersung.models.Album 在 android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3702) 在 android.app.ActivityThread.-wrap23(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1740) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 引起:android.os.BadParcelableException:解组时ClassNotFoundException:com.eusecom.samshopersung.models.Album 在 android.os.Parcel.readParcelableCreator(Parcel.java:2545) 在 android.os.Parcel.readParcelable(Parcel.java:2471) 在 android.os.Parcel.readValue(Parcel.java:2374) 在 android.os.Parcel.readArrayMapInternal(Parcel.java:2727) 在 android.os.BaseBundle.unparcel(BaseBundle.java:269) 在 android.os.BaseBundle.getString(BaseBundle.java:992) 在 android.content.Intent.getStringExtra(Intent.java:6743) 在 com.eusecom.demoad.view.EkasaService.onStartCommand(EkasaService.java:29) 在 android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3685) 在 android.app.ActivityThread.-wrap23(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1740) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(Native Method)

【问题讨论】:

相册是否实现了 Parcelable? @Antonis Radz 当然。我已经在相册类的两个应用程序中实现了 parcelable 不,在我看来,您不能直接将对象从一个应用程序打包和共享到另一个应用程序。您需要在一个应用程序中创建 Content Provider 并在另一个应用程序中使用 Content Resolver 访问它。 (在第二个应用程序中解组时的主要问题是特定类名com.eusecom.samshopersung.models.Album 在第二个应用程序中不存在,显然.. 包名称不同) Album 类在两个应用程序中是否具有完全相同的完全限定类名? @David Wasser 类名是同一个专辑,但当然包不同。 【参考方案1】:

最好将对象序列化为字符串,将字符串传递到Intent,然后将字符串反序列化为目标应用程序中的对象。

【讨论】:

Intent 中字符串的最大大小是多少? 大约 1MB,可能会少一点。如果您的对象非常大,最好将其存储在数据库或文件中,而不是将其放入Intent

以上是关于带有 Parcelable 的 Intent 如何在两个 App 之间传递?的主要内容,如果未能解决你的问题,请参考以下文章

Android中Intent传递对象的两种方法(Serializable,Parcelable)

——Parcelable接口的使用(跨进程,Intent传输)

Intent使用Parcelable传递对象

Intent传递对象——Serializable和Parcelable差别

无法从 onActivityReenter 中的 Intent 读取 Parcelable

Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!