Интерфейс AIDL между двумя приложениями

Я воткнул тотальную стену с интерфейсом AIDL. У меня есть приложение, которым нужно управлять через стороннее приложение (у меня достаточно контроля над этим, поэтому я могу попросить их реализовать то, что мне нужно, в их деятельности)

Первоначально мое приложение также было активностью с интерфейсом и всем остальным, но я изменил его на фоновую службу, и для тестирования я создал фиктивное приложение, которому удается запустить приложение службы в фоновом режиме.

Теперь мне нужен способ запрашивать вызовы методов из службы (в основном, start, stop, sendData). Я создал файлы .aidl для обоих приложений. Файл помощи реализует только один метод (это любезно предоставлено другим вопросом здесь.)

package foo.testapp;
interface IScript 
{
     String executeScript(String script); 
}

в то время как другой помощник такой же, за исключением того, что пакет «foo.otherapp». Реализации, которые я нашел в Интернете, имели один и тот же пакет для обоих файлов помощи, но для меня это вызывает ошибку (думаю, это просто проблема с моей стороны, так как я ненавижу пространства имен и пакеты, поэтому я часто просто неправильно называю их, если это важно меняй, я умею)

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

Во всяком случае ... Я не могу подключиться к помощи, я получаю сообщение об ошибке «Невозможно запустить службу

{act=foo.testapp.IScript}: не найдено

Я хотел бы, чтобы это предположение имело какое-то отношение к моим недоразумениям, т.е. имена пакетов или около того)

это реализация в моем тестовом приложении activity

private final IScript.Stub mBinder = new IScript.Stub()
{
    @Override
    public String executeScript(String script) throws RemoteException
    {
        // TODO Auto-generated method stub
    }
};
IScript mService = null;
private ServiceConnection mConnection = new ServiceConnection() 
{
     public void onServiceConnected(ComponentName className, IBinder service) 
     {
         mService = IScript.Stub.asInterface(service);
     }
     public void onServiceDisconnected(ComponentName className) 
     {
         mService = null;
     }
 };

Затем в методе OnCreate() я сделаю следующее:

bindService(new Intent(IScript.class.getName()),
            mConnection, Context.BIND_AUTO_CREATE);

В классе обслуживания у меня есть это;

@Override
public IBinder onBind(Intent intent) 
{
    // Select the interface to return.  If your service only implements
    // a single interface, you can just return it here without checking
    // the Intent.
    if (IScript.class.getName().equals(intent.getAction())) 
    {
        return mBinder;
    }
    return null;
}

/**
 * The IRemoteInterface is defined through IDL
 */
private final IScript.Stub mBinder = new IScript.Stub() 
{
    @Override
    public String executeScript(String script) throws RemoteException 
    {
        if (script == "test")
        {
            return "foo";
        }
        return "fail";
    }
};

И, наконец, файлы манифеста;

ну на самом деле, я понятия не имею, нужно ли мне что-то добавлять в файлы манифеста при работе с helpl. В одном примере я видел это;

    <intent-filter>
        <action android:name="foo.otherapp.IScript" />
    </intent-filter>

а также

    <intent-filter>
        <action android:name="foo.testapp.IScript" />
    </intent-filter>

Я предполагаю, что ошибки могут быть где угодно. Я пытался устроить это с помощью жевательной резинки и лейкопластырей. Думаю, я просто неправильно понял некоторые основные концепции этого.

В любом случае, любая помощь приветствуется.

Заранее спасибо!


person Marko Järvenpää    schedule 11.01.2011    source источник


Ответы (2)


Я решил ответить на свой вопрос, так как нашел точное решение.

Моя жизнь с Android

Все работало, просто скопировав исходный код и правильно изменив имена пакетов и имена функций (при условии, что вы реализуете это в своем собственном проекте)

Источник из папки клиента переходит к активности клиента, а serviceimpl переходит к сервису. Мне не нужна «Сервисная активность», поэтому я ее исключил (и, похоже, она все равно не вызывается).

У меня недостаточно репутации, чтобы публиковать несколько ссылок, поэтому вы можете получить источник в верхней части страницы.

«Обновление: ознакомьтесь с обновленным примером программы для Android SDK 1.5».

person Marko Järvenpää    schedule 18.01.2011

Я тоже боролся с этим. Вы правы в своем предположении, что RemoteInterface.aidl должен иметь одно и то же имя пакета как в сервисе, так и в тестовом приложении — так куда вы его помещаете!?

Если вы разрабатываете в Eclipse, то хитрость заключается в том, чтобы иметь общую исходную папку (общую для обоих проектов). Сделайте эту папку вне обоих проектов и в свойствах/источнике сборки, нажмите «связать источник» и перейдите к местоположению общего источник. (Вы можете назвать его как хотите) Сделайте это в обоих проектах и ​​поместите туда interface.aidl. Он появится в обозревателе пакетов обоих проектов, и когда вы измените его в одном проекте, другой тоже будет обновлен.

В общую исходную папку я положил interface.aidl в пакете с тем же именем, что и сервис.

Если вы используете Ant для сборки, это становится немного сложнее, так как ant_rules.xml по умолчанию не поддерживает две папки helpl, и вам придется немного изменить свой build.xml, добавив новую цель и все ее зависимости. .

Я начал свой проект, адаптировав образцы из главы 17 из «источника загрузки» здесь:

текст ссылки

person NickT    schedule 11.01.2011
comment
Спасибо за предложение. Я попробовал это быстро вчера и еще не мог понять это. Затем я попытался просто реорганизовать имена пакетов, чтобы они были идентичны уникальными .service и .client в конце. Итак, foo.projectname.client и foo.projectname.service. Затем это привело меня к неприятной ошибке, которая теперь вызывает много седых волос, некоторые приложения не устанавливаются на эмуляторе... 70-80% времени с ошибкой Class not found, а иногда просто устанавливается плавно и начинается. Поэтому я думаю, что перепишу привязки на основе опубликованного вами источника. Вернемся с результатами, надеюсь, сегодня. - person Marko Järvenpää; 12.01.2011
comment
Вчера был немного занят, и я вообще не мог над этим работать. В любом случае... Теперь я создал папку в своей рабочей области с именем AIDL, в которой я создал папки foo.service и поместил туда файл interface.aidl, а имя пакета в файле helpl - foo.service. проблема в том, что я не могу импортировать это сейчас. Я также попытался иметь файл .aidl в корне папки AIDL. Я использую затмение. - person Marko Järvenpää; 13.01.2011
comment
Я немного поиграл с этим и в конце концов решил попробовать создать учебный проект из источников, на которые вы ссылаетесь. По крайней мере, учебник не сразу заработал (я действительно не пытался выяснить, является ли это учебником, который решен в книге, связанной с ним). Это выдавало ошибку «Намерение не найдено»... в основном довел его до того же состояния, что и мой текущий проект. Я немного погуглил тему и наткнулся на золотую жилу. Чрезвычайно упрощенный и небольшой учебник по взаимодействию с помощью отдельных приложений. mylifewithandroid.blogspot.com/2008/01/invoking-services.html - person Marko Järvenpää; 18.01.2011