4

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

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

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

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

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

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

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

{act=foo.testapp.IScript }:未找到

我认为这个猜测与我的误解有关,即。包名左右)

这是我的测试活动应用程序中的实现

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>

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

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

提前致谢!

4

2 回答 2

3

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

我的安卓生活

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

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

我没有足够的声誉来发布多个链接,因此您可以从页面顶部获取来源。

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

于 2011-01-18T11:52:44.517 回答
1

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

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

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

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

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

链接文本

于 2011-01-11T12:34:18.480 回答