两个应用程序之间的 AIDL 接口

Posted

技术标签:

【中文标题】两个应用程序之间的 AIDL 接口【英文标题】:AIDL interface between two applications 【发布时间】:2011-01-11 10:37:04 【问题描述】:

我用 AIDL 接口卡住了一堵墙。我有一个必须通过 3rd 方应用程序控制的应用程序(我对此有足够的控制权,所以我可以要求他们在他们的活动中实现我需要的任何东西)

最初我的应用程序也是一个带有界面和所有内容的活动,但我已将其更改为后台服务,为了进行测试,我创建了一个虚拟应用程序,它设法将服务应用程序启动到后台。

现在我想要一种从服务请求方法调用的方法(主要是:启动、停止、sendData)。我已经为这两个应用程序创建了 .aidl 文件。 aidl 文件只实现了一种方法(这是由其他一些问题提供的。)

package foo.testapp;
interface IScript 

     String executeScript(String script); 

除了包是“foo.otherapp”之外,其他aidl是相同的。我在网上找到的实现对于两个aidl文件都有相同的包,但是对我来说这会导致一个错误(我猜这只是我的一个问题,因为我讨厌命名空间和包,所以我经常把它们命名得很糟糕,如果重要的话换他们,我能行)

计划是使用此方法向服务发送字符串,然后切换预定义的字符串以调用正确的方法(如果提高使用率,也可以实现三种不同的方法)。

无论如何...我无法让助手连接,我收到错误“无法启动服务意图

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";
    
;

最后是清单文件;

实际上,我不知道在处理aidl 时是否必须在清单文件中添加一些内容。在我看到的一个例子中;

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

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

我猜错误可能在任何地方。我一直在尝试用口香糖和创可贴来解决这个问题。我想我只是误解了这个的一些基本概念。

无论如何,欢迎任何帮助。

提前致谢!

【问题讨论】:

【参考方案1】:

我决定回答我自己的问题,因为我找到了一个确切的解决方案。

My Life With Android

只需复制粘贴源代码并正确更改包名称和函数名称即可一切正常(假设您将其实现到自己的项目中)

来自客户端文件夹的源进入客户端活动,而 serviceimpl 进入服务。我不需要“服务活动”,所以我把它排除在外(而且它似乎并没有真正被调用)。

我没有足够的声望发布多个链接,所以你可以从页面顶部获取来源。

“更新:请查看 Android SDK 1.5 的更新示例程序。”

【讨论】:

【参考方案2】:

我也为此苦苦挣扎。您猜对了,RemoteInterface.aidl 需要在服务和测试应用程序中具有相同的包名称 - 那么您将它放在哪里!?

如果您在 Eclipse 中开发,那么诀窍是拥有一个公共源文件夹(两个项目共用)将此文件夹置于两个项目之外并在构建属性/源中,单击“链接源”并浏览到该位置的共同来源。 (你可以给它起任何你想要的名字)在两个项目中都这样做,然后把 interface.aidl 放在那里。它会出现在两个项目的包资源管理器中,当您在一个项目中更改它时,另一个项目也会更新。

在公共源文件夹中,我将 interface.aidl 放在与服务同名的包中。

如果你使用 Ant 来构建,它会变得有点棘手,因为默认的 ant_rules.xml 不支持两个aidl 文件夹,你必须修改你的 build.xml 添加一个新的目标和它的所有依赖项。

我通过从此处的“下载源”改编第 17 章中的示例来启动我的项目:

link text

【讨论】:

感谢您的建议。我昨天很快尝试了这个,但还没有弄清楚。然后我尝试将包名称重构为最后与唯一的 .service 和 .client 相同。所以 foo.projectname.client & foo.projectname.service。然后这导致我陷入了一个令人讨厌的错误,现在导致很多白发,应用程序无法在模拟器上安装一些...... 70-80%的时间没有找到错误类,有时它只是顺利安装并且开始。所以我想我会根据你发布的来源重写绑定。带着结果回来,希望今天。 昨天有点忙,我根本无法工作。无论如何...我现在在我的工作空间中创建了一个名为 AIDL 的文件夹,在该文件夹下我创建了文件夹 foo.service,并将 interface.aidl 文件放在那里,aidl 文件中的包名称是 foo.service问题是,我现在无法导入它。我还尝试在 AIDL 文件夹根目录中放置 .aidl 文件。我正在使用日食。 我玩了很多次,最终决定尝试从您链接的源代码构建教程项目。该教程至少没有立即起作用(我并没有真正尝试找出它是否是在与其链接的书中解决的那种教程)。它给出了错误 Intent not found .... 基本上得到了与我当前项目相同的状态。我用谷歌搜索了更多的主题并找到了一个金矿。关于通过单独应用程序进行辅助通信的极其简化和小型教程。 mylifewithandroid.blogspot.com/2008/01/invoking-services.html

以上是关于两个应用程序之间的 AIDL 接口的主要内容,如果未能解决你的问题,请参考以下文章

入门篇:10.Android中AIDL(安卓接口定义语言)跨应用操作Service

AIDL(Android Interface Definition LanguageAndroid接口定义语言)

多个 AIDL 版本

Android之AIDL知识总结

Android AIDL浅析及异步使用

浅析AIDL的使用和工作原理