bindService из другого приложения, но тот же идентификатор пользователя / процесс - PullRequest
1 голос
/ 09 июля 2011

Речь идет о 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>

Это аннотация myAbstractService (myService пока ничего нового не добавляет):

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 (App2) из ​​моего MainActivity (App1):

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
ОШИБКА / AndroidRuntime (5464): java.lang.ClassCastException: com.www.shared.myBinder

Поскольку оба приложения работают в одном и том же процессе, связь с памятью должна работать (по крайней мере, я так думал). Я действительно не хочу использовать общение на основе сообщений или широковещательной рассылки, поскольку я отправлю довольно много сообщений.
Я подозреваю, что это исключение происходит из-за двух разных загрузчиков классов, используемых для одного и того же класса? Этот подход просто невозможен / неправильный, или я что-то упустил?

Обновление:
Моя цель - написать очень модульное приложение, в котором App1 используется как делегирующее и запускающее приложение для других модулей (приложений). Поскольку я не хочу поставлять App1 с каждым приложением в зависимости от него, я сделал это своим собственным приложением.

Допустим, у меня есть третье приложение (App3, проект Android). App2 и App3 оба запускаются App1 (отвечает за настройку соединений, в то время как App2 и App3 предоставляют разную логику приложения (но имеют одинаковый интерфейс).

С другой стороны, я думаю, что это можно решить и с помощью библиотеки Android (App1 & Shared объединяется в библиотеку с App2 и App3, запускающими Activity этой библиотеки и ожидающими результат)? Однако данные не подлежат передаче (сетевые подключения), и я понятия не имею, как эта библиотека могла бы распространяться независимо по рынку Android (например, App2 и App3 публикуются там, но просят также установить библиотеку). Решит ли это эту проблему вообще?

Ответы [ 3 ]

3 голосов
/ 14 июля 2011

Вы правы, вы получаете это исключение, потому что задействованы два загрузчика классов.

Я добавил следующие две строки кода:

@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 (см. Мои сообщения здесь и здесь ).
  3. В настоящее время библиотеки не поддерживают ресурсы (см. Мой пост здесь ).

План № 1 планируется исправить в ближайшее время (согласно Схема поддержки сборки ).# 2 и # 3 могут быть исправлены в следующем выпуске инструментов платформы SDK.

2 голосов
/ 15 июля 2011

Пробовал это сам некоторое время назад: подобные вопросы ранее задавались на ClassCastException, когда привязка к локальному сервису из другой Деятельности и https://stackoverflow.com/questions/3162538/2-apks-running-in-1-process-sharing-code-and-data. Конечный результат почти такой же: процесс совместного использованияНЕ то же самое, что разделение кода из-за природы иерархии загрузчиков классов (аналогично тому, как разделены загрузчики классов J2EE).

Классы происходят из разных файлов DEX, так что с технической точки зрения классы разные, даже еслиинтерфейсы одинаковы.Я не верю, что то, что вы хотите сделать, возможно: я вижу AIDL в вашем будущем.

0 голосов
/ 14 июля 2011

У вас есть класс с именем "myBinder" в пространстве имен "com.www.shared"?Потому что это то, что он ищет и говорит, что там нет.Я вижу, у вас есть класс, но в каком пространстве имён он есть?

...