首页 > 其他分享 >Android AIDL——实现机制浅析

Android AIDL——实现机制浅析

时间:2023-07-28 17:33:20浏览次数:37  
标签:AIDLService AIDL service aidl 浅析 Stub Android public android


1.基于前面写的aidl使用,这段时间准备研究ActivityManager框架,对aidl进行了更深入的研究,因为android框架大量使用了进程通信机制,所以,在研究android framework前认真研究一下AIDL的实现机制十分有必要的


3.aidl接口

package com.cao.android.demos.binder.aidl; 
 import com.cao.android.demos.binder.aidl.AIDLActivity;
 interface AIDLService {  
     void registerTestCall(AIDLActivity cb);  
     void invokCallBack();
 }

它编译后生成的java文件如下

总的来说,AIDLActivity.aidl编译会生成一个AIDLActivity接口,一个stub存根抽像类,一个proxy代理类,这个实现其实根axis的wsdl文件编译生成思路是一致的,
stub存根抽像类需要在服务端实现,proxy代理类被客户端使用,通过stub,proxy的封装,屏蔽了进程通信的细节,对使用者来说就只是一个AIDLActivity接口的调用

AIDLService.java详细描述了aidl接口的实现,看上面图示,AIDLActivity.aidl编译成了一个接口AIDLActivity,一个存根类Stub,一个代理类Proxy
 public interface AIDLService extends android.os.IInterface//与AIDLActivity.aidl中定义的接口对应的java接口实现
 public static abstract class Stub extends android.os.Binder implements com.cao.android.demos.binder.aidl.AIDLService
 //继承android.os.Binder,在onTransact完成对通信数据的接收,通过不同通信参数code调用AIDLService接口方法,并回写调用返回结果AIDLService接口方法需要在
 //服务端实现
 private static class Proxy implements com.cao.android.demos.binder.aidl.AIDLService
 //实现AIDLService接口方法,但是方法只是执行代理远程调用操作,具体方法操作在远端的Stub存根类中实现
4.根据以上思路使用aidl再看一下AIDLService调用实现代码
 --1.在服务端实现AIDLService.Stub抽象类,在服务端onBind方法中返回该实现类
 --2.客户端绑定service时在ServiceConnection.onServiceConnected获取onBind返回的IBinder对象
         private ServiceConnection mConnection = new ServiceConnection() {
                 public void onServiceConnected(ComponentName className, IBinder service) {
                         Log("connect service");
                         mService = AIDLService.Stub.asInterface(service);
                         try {
                                 mService.registerTestCall(mCallback);
                                               }
                 }
         注意mConnection在bindservice作为调用参数:bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
 --3.AIDLService.Stub.asInterface(service);
 public static com.cao.android.demos.binder.aidl.AIDLService asInterface(android.os.IBinder obj)
 {
 if ((obj==null)) {
 return null;
 }
 android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
 //如果bindService绑定的是同一进程的service,返回的是服务端Stub对象本省,那么在客户端是直接操作Stub对象,并不进行进程通信了
 if (((iin!=null)&&(iin instanceof com.cao.android.demos.binder.aidl.AIDLService))) {
 return ((com.cao.android.demos.binder.aidl.AIDLService)iin);
 }
 //bindService绑定的不是同一进程的service,返回的是代理对象,obj==android.os.BinderProxy对象,被包装成一个AIDLService.Stub.Proxy代理对象
 //不过AIDLService.Stub.Proxy进程间通信通过android.os.BinderProxy实现
 return new com.cao.android.demos.binder.aidl.AIDLService.Stub.Proxy(obj);
 }
 --4.调用AIDLService接口方法,如果是同一进程,AIDLService就是service的Stub对象,等同直接调用Stub对象实现的AIDLService接口方法
 如果是一个proxy对象,那就是在进程间调用了,我们看一个客户端调用的例子:
                         public void onClick(View v) {
                                 Log("AIDLTestActivity.btnCallBack");
                                 try {
                                         mService.invokCallBack();
                                 } catch (RemoteException e) {
                                         // TODO Auto-generated catch block
                                         e.printStackTrace();
                                 }
         --mService.invokCallBack()等同调用Proxy.invokCallBack,这个时候是进程间调用,我们看代理方法的实现
 public void invokCallBack() throws android.os.RemoteException
 {
 //构造一个Parcel对象,该对象可在进程间传输
 android.os.Parcel _data = android.os.Parcel.obtain();
 android.os.Parcel _reply = android.os.Parcel.obtain();
 try {
 //DESCRIPTOR = "com.cao.android.demos.binder.aidl.AIDLService",描述了调用哪个Stub对象
 _data.writeInterfaceToken(DESCRIPTOR);
 //Stub.TRANSACTION_invokCallBack 标识调用Stub中哪个接口方法,mRemote在是构造Proxy对象的参数obj,也就是public void onServiceConnected(ComponentName className, IBinder service)
 //中的service参数,它是一个BinderProxy对象,负责传输进程间数据。
 mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0);
 _reply.readException();
 }
 finally {
 _reply.recycle();
 _data.recycle();
 }
 }
 --5.BinderProxy.transact 该方法本地化实现
    public native boolean transact(int code, Parcel data, Parcel reply,
             int flags) throws RemoteException;
         //对应实现的本地化代码 /frameworks/base/core/jni/android_util_Binder.cpp->static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
                                                 jint code, jobject dataObj,
                                                 jobject replyObj, jint flags)
   //具体进程通信在c代码中如何实现,以后再深入研究。
 --6.服务端进程数据接收
         --调用堆栈
         ##AIDLService.Stub.onTransact
         ##AIDLService.Stub(Binder).execTransact
         ##NativeStart.run
         --AIDLService.Stub.onTransact
         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
 {
 switch (code)
 {
 case INTERFACE_TRANSACTION:
 {
 reply.writeString(DESCRIPTOR);
 return true;
 }
 case TRANSACTION_registerTestCall:
 {
 data.enforceInterface(DESCRIPTOR);
 com.cao.android.demos.binder.aidl.AIDLActivity _arg0;
 _arg0 = com.cao.android.demos.binder.aidl.AIDLActivity.Stub.asInterface(data.readStrongBinder());
 this.registerTestCall(_arg0);
 reply.writeNoException();
 return true;
 }
 //TRANSACTION_invokCallBack由前面客户端调用的时候transact方法参数决定,code==TRANSACTION_invokCallBack,执行
 //invokCallBack方法,方法由继承Stud的服务端存根类实现。
 case TRANSACTION_invokCallBack:
 {
 data.enforceInterface(DESCRIPTOR);
 this.invokCallBack();
 reply.writeNoException();
 return true;
 }

5.里面设置本地C代码的调用,我没有深入研究,随着后面我对android框架的深入,我会发blog进一步说民底层C代码是如何实现进程通信的,关于AIDL进程通信,暂时研究到这里。








AIDL的作用



    由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
    通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
 



  AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
    AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。
   



选择AIDL的使用场合



  官方文档特别提醒我们何时使用AIDL是必要的: 只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。
 


  • Calls made from the local process are executed in the same thread that is making the call. If this is your main UI thread, that thread continues to execute in the AIDL interface. If it is another thread, that is the one that executes your code in the service. Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using AIDL at all, but should instead create the interface by implementing a Binder).
  • Calls from a remote process are dispatched from a thread pool the platform maintains inside of your own process. You must be prepared for incoming calls from unknown threads, with multiple calls happening at the same time. In other words, an implementation of an AIDL interface must be completely thread-safe.
  • The oneway keyword modifies the behavior of remote calls. When used, a remote call does not block; it simply sends the transaction data and immediately returns. The implementation of the interface eventually receives this as a regular call from the Binder thread pool as a normal remote call. If oneway is used with a local call, there is no impact and the call is still synchronous.



定义AIDL接口



  AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。保存在src目录下。 如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。service必须适当地实现这个IBinder接口。那么客户端程序就能绑定这个service并在IPC时从IBinder调用方法。




1.创建.aidl文件
       

  而如果需要在AIDL中使用其他AIDL接口类型,需要import,即使是在相同包结构下。AIDL允许传递实现Parcelable接口的类,需要import.
    需要特别注意的是, 对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。


package com.demo;
    

import com.demo.Person;
    

interface IMyService {
    
  
     
     
     
     
     
     
     
    void savePersonInfo(in Person person);
    
  
     
     
     
     
     
     
     
    List getAllPerson();
    
 }



2.实现接口



public 
    class RemoteService 
    extends Service {
    

  
     
     
     
     
     
     
     
    private LinkedList personList = 
    new LinkedList();
    
  
     
     
     
     
     
     
     
    
  
     
     
     
     
     
     
     
    @Override
    
  
     
     
     
     
     
     
     
    public IBinder onBind(Intent intent) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return mBinder;
    
  
     
     
     
     
     
     
     
    }
    

       private final IMyService.Stub mBinder = new{
    

  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    @Override
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    public 
    void savePersonInfo(Person person) 
    throws RemoteException {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    if (person != 
    null){
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    personList.add(person);
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    }
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    @Override
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    public List getAllPerson() 
    throws RemoteException {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return personList;
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    }
    
  
     
     
     
     
     
     
     
    };
    
 }
    
 

 
 
  
  
 
 
 
    
public 
    static 
    abstract 
    class Stub 
    extends android.os.Binder 
    implements



    Parcelable需要实现三个函数:
    1) void writeToParcel(Parcel dest, int flags) 将需要序列化存储的数据写入外部提供的Parcel对象dest。而看了网上的代码例子,个人猜测,读取Parcel数据的次序要和这里的write次序一致,否则可能会读错数据。具体情况我没试验过!
      2) describeContents() 没搞懂有什么用,反正直接返回0也可以
      3) static final Parcelable.Creator对象CREATOR   这个CREATOR命名是固定的,而它对应的接口有两个方法:
      createFromParcel(Parcel source) 实现从source创建出JavaBean实例的功能

    newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。
   



仔细观察Person类的代码和上面所说的内容:

public 
    class Person 
    implements Parcelable {
    

  
     
     
     
     
     
     
     
    private String name;
    
  
     
     
     
     
     
     
     
    private String telNumber;
    
  
     
     
     
     
     
     
     
    private 
    int age;
    

  
     
     
     
     
     
     
     
    public Person() {}
    

       public Person(Parcel pl){
                 name = pl.readString();
                 telNumber = pl.readString();
                 age = pl.readInt();
         }

  
     
     
     
     
     
     
     
    public String getName() {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return name;
    
  
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    public 
    void setName(String name) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    this.name = name;
    
  
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    public String getTelNumber() {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return telNumber;
    
  
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    public 
    void setTelNumber(String telNumber) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    this.telNumber = telNumber;
    
  
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    public 
    int getAge() {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return age;
    
  
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    public 
    void setAge(
    int age) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    this.age = age;
    
  
     
     
     
     
     
     
     
    }
    

       @Override
         public int describeContents() {
                 return 0;
         }

 
           @Override
         public void writeToParcel(Parcel dest, int flags) {
                 dest.writeString(name);
                 dest.writeString(telNumber);
                 dest.writeInt(age);
         }

    
       public static final Parcelable.Creator CREATOR = new {
    

  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    @Override
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    public Person createFromParcel(Parcel source) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return new Person(source);
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    @Override
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    public Person[] newArray(
    int size) {
    
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    return new Person[size];
  
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    }
    

  
     
     
     
     
     
     
     
    };
    
 }



然后创建Person.aidl文件,注意这里的parcelable和原来实现的Parcelable 接口,开头的字母p一个小写一个大写:



package com.demo;
    

 parcelable Person;


   



    2. IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。
      3. 抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)。
 
3. 客户端获取接口


private IMyService mRemoteService;
      

private ServiceConnection mRemoteConnection = 
      new ServiceConnection() { 
       
       
       
      
  
       
       
       
       
       
       
       
      public 
      void onServiceConnected(ComponentName className, IBinder service) { 
       
       
       
      
  
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      mRemoteService = IMyService.Stub.asInterface(service); 
       
       
       
      
  
       
       
       
       
       
       
       
      } 
       
       
       
      

  
       
       
       
       
       
       
       
      public 
      void onServiceDisconnected(ComponentName className) { 
       
       
       
      
  
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      mRemoteService = 
      null; 
       
       
       
      
  
       
       
       
       
       
       
       
      } 
       
       
       
      
 };


在生成的IMyService.java里面会找到这样的代码:



public 
        static


而service的绑定没有什么不同:



if (mIsRemoteBound) {
      
  
       
       
       
       
       
       
       
      unbindService(mRemoteConnection);
      
 }
      else{
      
  
       
       
       
       
       
       
       
      bindService(
      new Intent(
      "com.demo.IMyService"),
      
  
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      mRemoteConnection, Context.BIND_AUTO_CREATE);
      
 }
      

 mIsRemoteBound = !mIsRemoteBound;


通过IPC调用/传递数据



    客户端绑定service后就能通过IPC来调用/传递数据了,直接调用service对象的接口方法:

addPersonButton.setOnClickListener(
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     new View.OnClickListener(){
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     private 
     int index = 0;
     

  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     @Override
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     public 
     void onClick(View view) {
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     Person person = 
     new Person();
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     index = index + 1;
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     person.setName(
     "Person" + index);
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     person.setAge(20);
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     person.setTelNumber(
     "123456"); 
     
                               try {
                                         mRemoteService.savePersonInfo(person);
                                 } catch (RemoteException e) {
                                         e.printStackTrace();
                                 } 
 
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     }
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     });
     

 listPersonButton.setOnClickListener(
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     new View.OnClickListener(){
     

  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     @Override
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     public 
     void onClick(View view) {
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     List list = 
     null; 
     

                               try {
                                         list = mRemoteService.getAllPerson();
                                 } catch (RemoteException e) {
                                         e.printStackTrace();
                                 } 

     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     if (list != 
     null){
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     StringBuilder text = 
     new StringBuilder();
     

  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     for(Person person : list){
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(
     "\nPerson name:");
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(person.getName());
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(
     "\n            );
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(person.getAge());
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(
     "\n tel number:");
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     text.append(person.getTelNumber());
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     }
     

  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     inputPersonEdit.setText(text);
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     }
     else {
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     Toast.makeText(ServiceActivity.
     this, 
     "get data error",
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     Toast.LENGTH_SHORT).show();
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     }
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     }
     
  
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
     });


  Permission权限
    如果Service在AndroidManifest.xml中声明了全局的强制的访问权限,其他引用必须声明权限才能来start,stop或bind这个service.        



  AndroidManifest.xml的Service元素


<</span>service android:name=".RemoteService" android:process=":remote">
         <</span>intent-filter>
                 <</span>action android:name="com.demo.IMyService" />
         </</span>intent-filter>
</</span>service>

    这里的android:process=":remote",一开始我没有添加的,在同一个程序里使用IPC,即同一个程序作为客户端/服务器端,结果运行mRemoteService = IMyService.Stub.asInterface(service);时提示空指针异常。观察了人家的在不同程序里进行IPC的代码,也是没有这个android:process=":remote"的。后来在官方文档 http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html里了解到(留意第二段文字):


android:process
The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.


If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.

 

也就是说android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

标签:AIDLService,AIDL,service,aidl,浅析,Stub,Android,public,android
From: https://blog.51cto.com/u_548275/6885701

相关文章

  • Android NFC简介
    目录:AndroidNFC1 简介1.1 什么是 NFC1.2Android 上的 NFC1.3Android 中的 NFC 通讯机制2 用法2.1 读取 tag2.2 发送消息2.2.1 发送过程2.2.2NDEF 消息格式1 简介1.1 什么是 NFC近场通讯 (NearFiledCommunication) 技术是一种近距离的高频无线......
  • UPS设备在物流机房中的应用浅析
    1UPS简介UPS即不间断电源(UninterruptiblePowerSupply),是一种含有储能装置的不间断电源。主要用于给部分对电源稳定性要求较高的设备,提供不间断的电源。当市电输入正常时,UPS将市电稳压后供应给负载使用,此时的UPS就是一台交流式电稳压器,同时它还向机内电池充电;当市电中......
  • Android-组件属性
    ImageView:app:tint=“”(tint:染色)作用:将非透明像素点染成指定颜色 EditText:android:selectAllOnFocus="true"作用:输入框获取焦点后,获取到所有文本内容 ......
  • AndroidAnnotations 自定义控件 ant编译 找不到类
    问题:今天使用jenkins+ant编译android项目,一直编译不通过,报错内容就是,自定义控件找不到类。确认了几次svn提交,项目代码完全提交,所以想到是不是代码的问题。故回头查询代码。在代码中使用了下划线类。这个类是在AA中自动生成的,而报错的地方,正是编译生成的地方,觉得可能和编......
  • Android从相册、照相机选择图片(支持4.4+,KIKAT以上)
    开发都会遇到从手机的相册和照相机选择图片的功能,下面是一段通用的代码,用来选择手机中的图片,以后用的时候,直接调用就可以了。使用到的类属性publicfinalstaticintCONSULT_DOC_PICTURE=1000;publicfinalstaticintCONSULT_DOC_CAMERA=1001;privateintSELECT_PICTURE......
  • AndroidAnnotations 使用在library项目中出现无法找到R文件下资源索引的错误
    AndroidAnnotations使用在library项目中出现无法找到R文件下资源索引的错误使用AndroidAnnotations(以下简称AA)已经有一段时间了,挺好用的,基本上完全可以满足Android开发需要,可以简化代码,所以现在在岗编写的所有的项目都是基于AA实现的。AA现在最新版本为3.2官方地址:http://android......
  • Kotlin 踩坑日记(六)Android studio 3.0.0 Canary 4 Instant Run
    前言宁夏的特色假日,开斋节放了5天,今天回来上班。放假前,Androidstudio3.0发布了Canary4的升级,因为即将放假,所以就没有升级,节后上班第一天,就安排升级并且试用一下。DebugApk找不到Application类没有别的问题,只是在InstantRun环境下,找不到App的Application类,应用安装成功后,......
  • Android 人脸识别 MTCNN Kotlin实现
    前言看见网上有一个MTCNN的Java实现,闲来无事,把Java实现用Koltin重写了一下,主要是针对使用MTCNN来识别人脸。不想罗嗦看的,可以直接去我的github上下载已经写好的demo。https://github.com/ChineseLincoln/AndroidFaceNet文章目录前言人脸识别tensorflowAndroid依赖配置MTCNN......
  • Android-定义和获取字符串资源
    resource->values->strings.xml里定义字符串定义单字符串:<stringname="app_name">abc123</string>定义字符串数组:<string-arrayname="map_style_array"><item>MAPBOX_STREETS</item><item>OUTDO......
  • 17 位谷歌 Android 开发专家是如何看待 Kotlin 的?
    译者简介:ASCE1885,《Android高级进阶》作者。*微信公众号:asce1885*小密圈:Android高级进阶,详情见这篇文章。*Github,简书,微博,原文链接:https://antonioleiva.com/google-kotlin/,由于Markdown对图片的排版存在限制,因此为了保证排版的美观,本文对作者介绍部分进行截图,不做另......