Android IPC,服务未获得实例化

Cod*_*ode 4 android ipc aidl android-service

我有一个服务,它驻留在像这样的lib项目中

public abstract class MyService extends Service{
    //service body here 
}
Run Code Online (Sandbox Code Playgroud)

我将我的aidl文件设置为与远程服务进行通信,该服务也包含在lib项目中,复制aidl文件

package mypackage;

// Declare the communication interface which holds all of our exposed functions.
interface IMyService {
    //interface body here 
}
Run Code Online (Sandbox Code Playgroud)

在lib清单中,我已经声明了这样的服务

<service
    android:name="mypackage.core.MyService"
    android:enabled="true"
    android:exported="true"
    android:process=":remote" >

    <intent-filter>
        <action android:name="mypackage.IMyService" />
    </intent-filter>

</service>
Run Code Online (Sandbox Code Playgroud)

我在我的应用程序中包含了这个lib,但是当我尝试从应用程序绑定服务时,它没有被实例化.任何人都可以告诉我我做错了什么,如果是这样,那就给我一个出路.该服务正在另一个属于lib的类中开始

try{
    Intent i = new Intent(MyService.class.getName());
    i.setPackage("mypackage");
    // start the service explicitly.
    // otherwise it will only run while the IPC connection is up.       
    mAppContext.startService(i);
    boolean ret = mAppContext.bindService(i,
            mConnection, Service.BIND_AUTO_CREATE);
    if(!ret){
        MyLogger.log("Error");
    }
}catch(Exception e){
    MyLogger.log("err");
}
Run Code Online (Sandbox Code Playgroud)

服务绑定API始终返回false,这将是什么问题.这是创建RemoteService的重要方式吗?我是否需要在应用清单中添加此服务,如果是这样的话?

Com*_*are 6

会是什么问题

首先,你的Intent不符合你的<service>.

Intent i = new Intent(MyService.class.getName());
Run Code Online (Sandbox Code Playgroud)

你正在传递一个String类似的动作mypackage.core.MyService.但是,这不<action>适合您Service:

<action android:name="mypackage.IMyService" />
Run Code Online (Sandbox Code Playgroud)

因此,你Intent不匹配任何东西,你不能绑定.


其次,你Service非常不安全的.任何想要绑定它的应用程序.如果您希望其他应用程序绑定到它,那很好,但通过一些权限保护它,以便用户对哪些应用程序可以绑定它进行投票.


第三,你使用隐式的绑定Intent,使用像动作字符串这样的东西.这不适用于Android 5.0+,因为您无法再使用隐式绑定到服务Intent.使用隐式Intent发现服务很好,但是您需要将其转换为Intent包含组件名称的显式服务.以下是我在此示例应用中执行此操作的方法:

  @Override
  public void onAttach(Activity host) {
    super.onAttach(host);

    appContext=(Application)host.getApplicationContext();

    Intent implicit=new Intent(IDownload.class.getName());
    List<ResolveInfo> matches=host.getPackageManager()
                                  .queryIntentServices(implicit, 0);

    if (matches.size()==0) {
      Toast.makeText(host, "Cannot find a matching service!",
                      Toast.LENGTH_LONG).show();
    }
    else if (matches.size()>1) {
      Toast.makeText(host, "Found multiple matching services!",
                      Toast.LENGTH_LONG).show();
    }
    else {
      Intent explicit=new Intent(implicit);
      ServiceInfo svcInfo=matches.get(0).serviceInfo;
      ComponentName cn=new ComponentName(svcInfo.applicationInfo.packageName,
                                         svcInfo.name);

      explicit.setComponent(cn);
      appContext.bindService(explicit, this, Context.BIND_AUTO_CREATE);
    }
  }
Run Code Online (Sandbox Code Playgroud)

这是创建RemoteService的重要方式吗?

很少有人创建远程服务.它们很难保护,很难处理协议中的版本更改等.在您的情况下,我不知道您认为自己需要远程服务的原因,因为您明确地绑定了自己的应用程序中的服务.

  • _第三,你使用一个隐含的Intent绑定,一个使用像动作字符串这样的东西.这在Android 5.0+上不起作用,因为您不能再使用隐式Intent绑定到服务.如果设置了包名称和操作,那么"Intent"被认为是隐式的,但组件名称是否缺失? (2认同)