1

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

我有两个应用程序 ( 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定义在 中<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()");
        }
    }
 }

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

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

我得到一个例外:

调试/MS(5464):com.www.shared.myBinder 类
错误/AndroidRuntime(5464):java.lang.ClassCastException:com.www.shared.myBinder

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

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

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

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

4

3 回答 3

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 库直接嵌入在引用它们的应用程序中。它们不单独分发。这是我的帖子,解释了 Android 库与简单 jar 的不同之处,以及其他相关的细微差别。

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

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

  1. 您需要将库中所有组件的声明复制AndroidManifest.xml到 Android 应用程序的AndroidManifest.xml.
  2. 当前库不支持自定义 xml 属性(请参阅我的帖子herehere)。
  3. 目前图书馆不支持资产(见我的帖子在这里)。

#1 计划很快修复(根据构建支持路线图)。#2 和 #3 可能会在下一版本的 SDK 平台工具中得到修复。

于 2011-07-14T19:41:28.630 回答
2

不久前我自己尝试过:以前在 ClassCastException 中提出了类似的问题,当从另一个 Activity和https://stackoverflow.com/questions/3162538/2-apks-running-in-1-process-sharing-code绑定到本地服务时-和-数据。最终结果几乎相同:由于类加载器层次结构的性质(类似于 J2EE 类加载器的拆分方式),共享过程与共享代码不同。

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

于 2011-07-14T20:01:31.060 回答
0

您在命名空间“com.www.shared”中有一个名为“myBinder”的类吗?因为那是它正在寻找的东西,并且说不存在。我看到你有这个类,但它在什么命名空间中?

于 2011-07-14T14:25:32.990 回答