Android bindService来自其他应用程序,但用户ID/进程相同

Android bindService来自其他应用程序,但用户ID/进程相同,android,android-service,ipc,android-binder,Android,Android Service,Ipc,Android Binder,这是关于基于内存的IPC的示例,但对于在同一进程中运行的两个应用程序: 我有两个应用程序App1、App2和一个共享项目shared,它为这两个应用程序定义了一些接口和抽象类: Shared (regular Java project, references android.jar) - abstract myAbstractService - Binder myBinder App1 (Android Project, references Shared) - Main

这是关于基于内存的IPC的示例,但对于在同一进程中运行的两个应用程序:

我有两个应用程序App1、App2和一个共享项目shared,它为这两个应用程序定义了一些接口和抽象类:

Shared (regular Java project, references android.jar)
    - abstract myAbstractService
    - Binder myBinder
App1 (Android Project, references Shared)
    - MainActivity
App2 (Android Project, references Shared)
    - myService extends myAbstractService
这两个应用程序在同一进程my.process中运行,在中定义, App2发布com.www.App2.myService:

当我尝试从MainActivity App1绑定到myService App2时:

我得到一个例外:

DEBUG/MS5464:class com.www.shared.myBinder 错误/AndroidRuntime5464:java.lang.ClassCastException:com.www.shared.myBinder

由于两个应用程序在同一进程中运行,至少我认为内存耦合通信应该可以工作。我真的不想使用基于消息或基于广播的通信,因为我会向周围发送相当多的消息。 我怀疑发生这种异常是因为同一个类使用了两个不同的类加载器?这种方法是不可能的/错误的还是我遗漏了什么

更新: 我的目标是编写一个非常模块化的应用程序,其中App1用作其他模块应用程序的委托和启动应用程序。因为我不想随每个应用程序一起发布App1,所以我把它做成了自己的应用程序

假设我有第三个应用程序App3,Android项目。App2和App3均由负责设置连接的App1启动,而App2和App3提供不同的应用程序逻辑,但具有相同的接口


再想一想,我认为这可以通过android库以及App1和App2与App3合并的库来解决,启动该库的活动并等待结果?然而,数据不是可打包的网络连接,我不知道该库如何在android市场上独立分发,比如App2和App3在那里发布,但要求也安装该库。这能解决这个问题吗?

在名称空间com.www.shared中有一个名为myBinder的类吗?因为这就是它所寻找的,而它所说的并不存在。我看到您有这个类,但它在哪个名称空间中?

在名称空间com.www.shared中有一个名为myBinder的类吗?因为这就是它所寻找的,而它所说的并不存在。我看到您有这个类,但它在什么名称空间中?

您是正确的,您收到这个异常,因为涉及到两个类加载器

我添加了下面两行代码:

@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
    ...
    Log.e(TAG, "Expected class loader: "+myBinder.class.getClass().getClassLoader());
    Log.e(TAG, "Class loader: "+service.getClass().getClassLoader());
    ...
}
并收到以下日志:

Expected class loader: java.lang.BootClassLoader@4001bdb0
Class loader: dalvik.system.PathClassLoader[/data/app/com.inazaruk.shared.service-2.apk]
从日志中可以清楚地看到使用了另一个类加载器。这实际上是有道理的,因为您可以在一周后使用不同版本的myBinder类或通过myBinder接口直接或间接传递的任何其他类安装App1应用程序

更新: 在您的场景中,您应该坚持使用Android库。请注意,Android库直接嵌入到引用它们的应用程序中。它们不是单独分发的。解释Android库与简单JAR的区别,以及其他相关的细微差别

您在Android库中仍然具有高度的模块化,因为最终的Android应用程序只包含它使用的模块。但这是编译时模块化,而不是运行时模块化

不过,Android库存在一些问题:

您需要将库的AndroidManifest.xml中的所有组件声明复制到Android应用程序的AndroidManifest.xml中。 当前库不支持自定义xml属性,请参阅我的文章和。 当前库不支持资源,请参阅我的文章。
1计划很快按照计划进行修复。2和3可能会在下一版本的SDK平台工具中得到修复。

您是正确的,您会收到此异常,因为涉及到两个类加载器

我添加了下面两行代码:

@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
    ...
    Log.e(TAG, "Expected class loader: "+myBinder.class.getClass().getClassLoader());
    Log.e(TAG, "Class loader: "+service.getClass().getClassLoader());
    ...
}
并收到以下日志:

Expected class loader: java.lang.BootClassLoader@4001bdb0
Class loader: dalvik.system.PathClassLoader[/data/app/com.inazaruk.shared.service-2.apk]
从日志中可以清楚地看到使用了另一个类加载器。这实际上是有道理的,因为您可以在一周后使用不同版本的myBinder类或通过myBinder接口直接或间接传递的任何其他类安装App1应用程序

更新: 在您的场景中,您应该坚持使用Android库。请注意,Android库直接嵌入到引用它们的应用程序中。它们不是单独分发的。解释Android库与简单JAR的区别,以及其他相关的细微差别

您在Android库中仍然具有高度的模块化,因为最终的Android应用程序只包含它使用的模块。但这是编译时模块化,而不是运行时模块化

不过,Android库存在一些问题:

您需要将库的AndroidManifest.xml中的所有组件声明复制到Android应用程序的AndroidManifest.xml中。 当前库不支持自定义xml属性,请参阅我的文章和。 当前库不支持资源,请参阅我的文章。 1计划很快修复
我要去。2和3可能会在下一版本的SDK平台工具中得到修复。

不久前我自己也尝试过这一点:之前在和上也曾问过类似的问题。最终结果基本相同:共享过程与共享代码不同,因为类加载器层次结构的性质类似于J2EE类加载器的拆分方式


这些类来自不同的DEX文件,所以从技术上讲,这些类是不同的,即使接口是相同的。我不相信你想做什么是可能的:我看到了你未来的AIDL。

不久前我自己也尝试过这个:以前在和上也问过类似的问题。最终结果基本相同:共享过程与共享代码不同,因为类加载器层次结构的性质类似于J2EE类加载器的拆分方式



这些类来自不同的DEX文件,所以从技术上讲,这些类是不同的,即使接口是相同的。我不相信你想做的是可能的:我看到你未来的AIDL。

当然位于共享项目中。否则项目将无法编译。编辑以反映我的意思。。。抱歉。myBinder和myAbstractService都位于com.www.shared中,它由位于共享项目中的my MainActivity App1命名空间com.www.App1和myService App2命名空间com.www.app2Sure导入。否则项目将无法编译。编辑以反映我的意思。。。抱歉。myBinder和myAbstractService都位于com.www.shared中,它由我的MainActivity App1、命名空间com.www.App1和myService App2导入,namespace com.www.app2A早在一天的时候就开始写了,基本上抓住了相同的论点。感谢你的文献:已经知道你评论中的链接给了我使用sharedProcess的提示。有关可能的解决方法,请参见我的评论@inazaruk-answer:早在那一天,一篇较长的文章就在,基本上抓住了相同的论点。感谢你的文献:已经知道你评论中的链接给了我使用共享流程的提示。有关可能的解决方法,请参见我的评论@inazaruk-answer:谢谢你的澄清。我已经添加了更多的细节,可能是解决方法。另一个想法是在运行时从另一个包DexClassLoader加载类。但我想这也行不通。谢谢:这意味着我不能再使用以前的App1作为启动应用了,我想除了App2启动App1之外,它可以启动App3,而不是在完成后再次启动App1返回App3,我以前的App1将与每个应用或模块一起部署,可能导致它的两个不同版本?您将不再拥有App1、App2和App3。您将拥有Lib1和Lib2,并将创建使用Lib1和Lib2的AppX。因此,您将发布实际上是Lib1+Lib2+AppX的应用程序。若您决定创建使用Lib2的AppY,那个么您将得到实际上是Lib2+AppY的应用程序。希望我正确理解了你的问题。我想要的是另一种方式:比如App1是必备组件,App2/App3是可选的,以后可以在App1的扩展上安装。在我的例子中,App1初始化一些网络连接,并将它们交给根据安装的应用程序(如App2、App3)选择的用户。App2,3使用这些连接做一些奇特但不同的事情。但是,这取决于用户需要安装相应的应用程序来决定哪些功能。因此,在编译时,我不知道在终端系统中哪些是可用的,所以基本上需要动态时间模块化,比如插件。除了远程绑定服务、内容提供商、活动和广播之外,Android目前不支持此功能。换句话说,您需要序列化和反序列化要在来自不同软件包和应用程序的组件之间交换的数据。感谢您的澄清。我已经添加了更多的细节,可能是解决方法。另一个想法是在运行时从另一个包DexClassLoader加载类。但我想这也行不通。谢谢:这意味着我不能再使用以前的App1作为启动应用了,我想除了App2启动App1之外,它可以启动App3,而不是在完成后再次启动App1返回App3,我以前的App1将与每个应用或模块一起部署,可能导致它的两个不同版本?您将不再拥有App1、App2和App3。您将拥有Lib1和Lib2,并将创建使用Lib1和Lib2的AppX。因此,您将发布实际上是Lib1+Lib2+AppX的应用程序。若您决定创建使用Lib2的AppY,那个么您将得到实际上是Lib2+AppY的应用程序。希望我正确理解了你的问题。我想要的是另一种方式:比如App1是必备组件,App2/App3是可选的,以后可以在App1的扩展上安装。在我的例子中,App1初始化一些网络连接并将它们交给根据中的应用选择的用户
像App2、App3这样的应用程序被暂停。App2,3使用这些连接做一些奇特但不同的事情。但是,这取决于用户需要安装相应的应用程序来决定哪些功能。因此,在编译时,我不知道在终端系统中哪些是可用的,所以基本上需要动态时间模块化,比如插件。除了远程绑定服务、内容提供商、活动和广播之外,Android目前不支持此功能。换句话说,您需要序列化和反序列化要在来自不同软件包和应用程序的组件之间交换的数据。
Expected class loader: java.lang.BootClassLoader@4001bdb0
Class loader: dalvik.system.PathClassLoader[/data/app/com.inazaruk.shared.service-2.apk]