使用AIDL進行應用間通信

使用AIDL進行程序間通信

1.先編寫一個提供服務的service應用

應用代碼結構如下:
這裏寫圖片描述
IBook.aidl爲接口文件,但與一般的接口不同,注意比較,上代碼:

package com.aidl.myservice;
interface IBook{
  void setName(String name);
  String getName();
}

可以看到裏面的接口不用public,protected,private等修飾。
Book.java繼承並實現了IBook的存根方法:

public class Book extends IBook.Stub {
    private String name;
    @Override
    public void setName(String name) throws RemoteException {
        // TODO 自動生成的方法存根
        this.name=name;
    }

    @Override
    public String getName() throws RemoteException {
        // TODO 自動生成的方法存根
        return this.name;
    }

}

AIDLServiceServer.java繼承Service,重寫onBind()方法,放回存根類接口iBook:

public class AIDLServiceServer extends Service{

    private IBook.Stub iBook=new Book();
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO 自動生成的方法存根
        return iBook;
    }

}

MainActivity.java如下:

public class MainActivity extends Activity {

    private Button bn1;
    private Button bn2;
    private ServiceConnection conn;
    private IBook iBook;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
        bn1.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View arg0) {
                Intent intent=new Intent(MainActivity.this,AIDLServiceServer.class);
                bindService(intent,conn,Service.BIND_AUTO_CREATE);
            }

        });
        bn2.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View arg0) {
                unbindService(conn);
            }

        });
    }
    private void init(){
        setContentView(R.layout.activity_main);
        bn1=(Button)findViewById(R.id.button1);
        bn2=(Button)findViewById(R.id.button2);
        conn=new ServiceConnection(){

            @Override
            public void onServiceConnected(ComponentName arg0, IBinder arg1) {
                iBook=IBook.Stub.asInterface(arg1);
                if(iBook!=null){
                    try{
                        iBook.setName("AIDL Test");
                        Toast.makeText(MainActivity.this,iBook.getName()+"賦值成功!",Toast.LENGTH_LONG).show();
                    }
                    catch(RemoteException e){
                        e.printStackTrace();
                        Toast.makeText(MainActivity.this, "賦值失敗!", Toast.LENGTH_LONG).show();
                    }

                }

            }

            @Override
            public void onServiceDisconnected(ComponentName arg0) {

            }

        };
    }
}

由於我們創建了service,得在AndroidManifest.xml中隊service進行聲明:

<service android:name="AIDLServiceServer">
            <intent-filter >
                <action android:name="com.aidl.myservice.server"/>
            </intent-filter>
        </service>

注意:在這裏配置intent-filter時android:name:=“”裏面的內容可以是任意的,這裏建議爲了更好地進行隱式匹配,建議使用service所在包的包名加創建service的類的類名構成,即com.aidl.myservice.AIDLServiceServer;上面代碼因爲偷懶寫得不是這樣,切勿模仿。
至此,服務端創建好了,打開應用,點擊連接service,彈出我們放入的AIDLTest這個測試值說明成功了。如圖:
這裏寫圖片描述

2.編寫另一個應用來調用服務端的service

應用代碼結構如下:
這裏寫圖片描述
這裏要注意的是,aidl文件除了要求接口名和類名一模一樣外(當然不用帶上後綴.aidl),客戶端調用的aidl文件必須得存放在和服務端存放aidl文件的名字相同的包裏,即把IBook.aidl存放到com.aidl.myservice包裏。
IBook.java代碼如下:

package com.aidl.myservice;
interface IBook{
  void setName(String name);
  String getName();
}

MainActivity.java的代碼如下:

public class MainActivity extends Activity {

    private Button bn1;
    private ServiceConnection conn;
    private IBook iBook;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
        bn1.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View arg0) {
                // TODO 自動生成的方法存根
                Intent intent=new Intent();
                intent.setAction("com.aidl.myservice.server");
                bindService(intent,conn,Context.BIND_AUTO_CREATE);
            }

        });
    }
    public void init(){
        setContentView(R.layout.activity_main);
        bn1=(Button)findViewById(R.id.button1);
        conn=new ServiceConnection(){

            @Override
            public void onServiceConnected(ComponentName arg0, IBinder arg1) {
                // TODO 自動生成的方法存根
                iBook=IBook.Stub.asInterface(arg1);
                if(iBook!=null){
                    try{
                        String name=iBook.getName();
                        Toast.makeText(MainActivity.this,"獲得的值爲:"+name, Toast.LENGTH_LONG).show();
                    }
                    catch(RemoteException e){
                        e.printStackTrace();
                        Toast.makeText(MainActivity.this,"獲取失敗!!", Toast.LENGTH_LONG).show();
                    }
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName arg0) {
                // TODO 自動生成的方法存根

            }

        };
    }


}

注意:在這裏有個坑,要小心一點,服務端爲了測試連接服務,使用

bindService(intent,conn,Service.BIND_AUTO_CREATE);

而客戶端測試連接服務時,使用

bindService(intent,conn,Context.BIND_AUTO_CREATE);

最後,還有測試是需要注意的地方:(因爲我們這個service的啓動方式是bind,不是start,更多請查閱service生命週期的相關文章)
啓用服務端連接,賦值後,不要按返回鍵,按home,再找到客戶端,點擊測試即可看到如下圖,表示通信成功:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章