来自其他应用程序但同一用户ID /进程的bindService

时间:2011-07-08 21:34:47

标签: android android-service ipc android-binder

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

我有两个应用(App1App2)和一个共享项目(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,在<application>中定义), App2发布com.www.app2.myService

<-- Both Apps run in the same process -->
<manifest <!-- *snip* --> android:sharedUserId="my.shareduser">
    <!--  ... -->
    <application <!-- *snip* --> android:process="my.process">
        <-- App2 exports the service -->
        <service android:name="com.www.app2.myService" android:exported="true">
            <intent-filter>
                <action android:name="com.www.app2.myService" />
            </intent-filter>
       </service>

这是摘要myAbstractServicemyService尚未添加任何新内容):

abstract public class GameClient extends Service
{   
    private static final String LOGTAG = "GameClient";

    private myBinder binder = new myBinder();

    public IBinder onBind(Intent intent)
    {
        Log.d(LOGTAG, "onBind()");

        return this.binder;
    }

    public class myBinder extends Binder
    {
        public void sendMessage()
        {
            Log.d(LOGTAG, "sendMessage()");
        }
    }
 }

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

public void onServiceConnected(ComponentName name, IBinder service) 
{
    Log.d("MS", service.getClass().toString());
    main.this.t = (myBinder) service; // Exception in this line of course
}

我得到一个例外:

  

DEBUG / MS(5464):com.www.shared.myBinder   ERROR / AndroidRuntime(5464):java.lang.ClassCastException:com.www.shared.myBinder

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

更新
我的目标是编写一个非常模块化的应用程序,其中App1用作其他模块(应用程序)的委托和启动应用程序。由于我不希望随每个应用程序发送App1,我将其作为自己的应用程序。

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

第二个想法我认为这也可以通过一个安卓库来解决(App1&amp; Shared合并为带有App2App3的库,启动此库的Activity并等待结果)?然而,数据不是可以分配的(网络连接),我不知道这个库如何在Android市场上独立分发(如App2App3在那里发布,但要求安装库太)。这会解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

你是对的,你收到这个例外,因为涉及两个类加载器。

我接下来添加了两行代码:

@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]

从日志中可以清楚地看到使用了另一个类加载器。这实际上是有道理的,因为您可以在一周之后使用不同版本的App1类(或直接或间接通过myBinder接口传递的任何其他类)安装myBinder应用程序。



<强>更新
你应该在你的场景中坚持使用Android库。请注意,Android库直接嵌入引用它们的应用程序中。它们不是单独分发的。 Here is my post解释了Android库与简单罐子和其他相关细微差别的区别。

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

Android库存在一些问题:

  1. 您需要将库AndroidManifest.xml中的所有组件声明复制到Android应用的AndroidManifest.xml
  2. 目前,图书馆不支持自定义xml属性(请参阅我的帖子herehere)。
  3. 目前图书馆不支持资源(请参阅我的帖子here)。
  4. #1计划很快修复(根据Build Support roadmap)。 #2和#3可能会在下一版SDK平台工具中修复。

答案 1 :(得分:2)

我自己一段时间地尝试过这个问题:先前在ClassCastException when binding to local service from another Activityhttps://stackoverflow.com/questions/3162538/2-apks-running-in-1-process-sharing-code-and-data提出了类似的问题。最终结果几乎相同:共享流程与共享代码不同,因为类加载器层次结构的性质(类似于J2EE类加载器的拆分方式)。

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

答案 2 :(得分:0)

你是否在命名空间“com.www.shared”中有一个名为“myBinder”的类?因为这就是它所寻求的,而且说不存在。我看到你有这个类,但是它有什么命名空间?