1. 程式人生 > >Service+AIDL牛刀小試,實現應用間通訊

Service+AIDL牛刀小試,實現應用間通訊

學習以及使用Android已經一年多了,卻覺得自己還是有些東西沒怎麼使用過,比如說Service,這個蠻重要的東西,之前只是隨意地使用過,也沒有好好學習。於是乎就花了大半天工作的時間學習了它的一些相關知識,在這個過程中,意外收穫了一些IPC的知識。
本文只作Service+AIDL實現程序間通訊的具體實現的步驟介紹,深入原始碼內容我還沒有仔細地學習(畢竟看C++程式碼還是有點點累,等過段時間,我把深入1第六章和深入2第二章讀透了會再來詳細補充一下Binder的知識以及原始碼的解釋)

廢話不多說了 下面就開始講講專案實現的步驟吧:
1.新建專案
2.定義AIDL介面
3.暴露服務介面
4.拷貝AIDL介面
5.呼叫服務

新建專案

既然是應用間通訊,就是說我們得新建兩個專案 專案1作為服務端server,專案2作為呼叫服務的客戶端client。

定義AIDL介面

在專案1中新建一個aidl檔案,內容如下

package com.ysdemo.testdemo;//包名

interface MyAIDLService {  
    //需要實現的方法
    int plus(int a, int b); 
    String toUpperCase(String str);  
}

需要注意的一點是 aidl介面中方法的引數限定為以下幾類:
①int,char等基礎型別
②String,List,Map,CharSequence等型別
③繼承Parcelable的型別
④其他AIDL介面型別

儲存該檔案後,會在gen目錄中自動編譯出一個java檔案,
將格式稍微調整了一下之後是這樣的:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\\workspace\\TestDemo\\src\\com\\ysdemo\\testdemo\\MyAIDLService.aidl
 */
package com.ysdemo.testdemo;

public interface MyAIDLService extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.ysdemo.testdemo.MyAIDLService { private static final java.lang.String DESCRIPTOR = "com.ysdemo.testdemo.MyAIDLService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.ysdemo.testdemo.MyAIDLService * interface, generating a proxy if needed. */ public static com.ysdemo.testdemo.MyAIDLService asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.ysdemo.testdemo.MyAIDLService))) { return ((com.ysdemo.testdemo.MyAIDLService) iin); } return new com.ysdemo.testdemo.MyAIDLService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override 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_plus: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.plus(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_toUpperCase: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); java.lang.String _result = this.toUpperCase(_arg0); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.ysdemo.testdemo.MyAIDLService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int plus(int a, int b) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(a); _data.writeInt(b); mRemote.transact(Stub.TRANSACTION_plus, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(str); mRemote.transact(Stub.TRANSACTION_toUpperCase, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_plus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_toUpperCase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public int plus(int a, int b) throws android.os.RemoteException; public java.lang.String toUpperCase(java.lang.String str) throws android.os.RemoteException; }

AIDL介面定義好了,現在要對其進行實現,在自定義的Service中覆寫onBind方法:

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return new MyAIDLService.Stub() {

            @Override
            public int plus(int a, int b) throws RemoteException {
                // TODO Auto-generated method stub
                return a + b;
            }
            @Override
            public String toUpperCase(String str) throws RemoteException {
                if (str != null) {  
                    return str.toUpperCase();  
                } 
                return null;
            }  
        };
    }

暴露服務介面

在專案1的AndroidManifest.xml中為application註冊自定義服務並將其以隱式Intent方式暴露給其他應用:

        <service android:name="com.ysdemo.testdemo.MyService"
            android:process=":remote">
            <intent-filter>
                <action 
                    android:name="com.ysdemo.testdemo.MyAIDLService"/>
            </intent-filter>
        </service>

拷貝AIDL介面

將專案1的aidl檔案拷貝到專案2,並放在相同的包下(新建一個名字相同的包亦可)。
這裡寫圖片描述
儲存後,gen目錄中也會生成相同的java檔案。

呼叫服務

在專案2中的Activity呼叫該服務:

public class MainActivity extends Activity {  

    private MyAIDLService myAIDLService;  

    private ServiceConnection connection = new ServiceConnection() {  

        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        }  

        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            myAIDLService = MyAIDLService.Stub.asInterface(service);  
            try {  
                int result = myAIDLService.plus(50, 50);  
                String upperStr = myAIDLService.toUpperCase("comes from ClientTest");  
                Log.d("TAG", "result is " + result);  
                Log.d("TAG", "upperStr is " + upperStr);  
            } catch (RemoteException e) {  
                e.printStackTrace();  
            }  
        }  
    };  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        Button bindService = (Button) findViewById(R.id.bind_service);  
        bindService.setOnClickListener(new OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                Intent intent = new Intent("com.ysdemo.testdemo.MyAIDLService");  
                bindService(intent, connection, BIND_AUTO_CREATE);  
            }  
        });  
    }  

}  

相關推薦

Service+AIDL牛刀小試實現應用通訊

學習以及使用Android已經一年多了,卻覺得自己還是有些東西沒怎麼使用過,比如說Service,這個蠻重要的東西,之前只是隨意地使用過,也沒有好好學習。於是乎就花了大半天工作的時間學習了它的一些相關知識,在這個過程中,意外收穫了一些IPC的知識。 本文只作S

Android BroadcastReceiver使用實現程序通訊

1、建立廣播接收器: /** * 作者:created by meixi * 郵箱:[email protected] * 日期:2018/11/1 09 */ public class MyBroadcastReceiver extends BroadcastReceiver

利用委託 實現窗體通訊非原創

copy自:https://www.cnblogs.com/hugoNB/p/7130562.html,這個作者寫的淺顯易懂,就複製下來自己看 實現過程:     這裡主要是用到委託實現,所以主要描述一下委託在這裡的應用。     我們要在主窗體(這裡的子父窗體都是自己假想)中獲取子窗體中的元素,所以首

Android AIDL實現程序通訊

        今天犯二了, 犯了個超級低階的錯誤, 真的是丟人丟大發了.         剛好順道反思下, 也對工作這幾年做一些簡單的總結. 不知道你們是不是和我一樣也總遇到各

android Aidl 實現程序通訊

1​,android 新建aidl 檔案 刪除void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);這個方法沒用到 還需要實

第18天Service-Messager實現程序通訊

第18天Service-Messager實現程序間通訊 Messager 一.Messager介紹 二.Messager的原理 特點: 三 .使用步驟 服務端moudle:messager

Android Studio使用AIDL 實現程序通訊例項

參考:部落格:http://www.cnblogs.com/BeyondAnyTime/p/3204119.html, http://www.cnblogs.com/linlf03/p/3192025.html     視訊教程:http://www.imooc.com/l

android使用aidl實現程序通訊的例項

//這一步啟動服務         this.bindService(new Intent("com.wyj.aidlservice"), this.serviceConnection, BIND_AUTO_CREATE);                  btn = (Button)findViewByI

android studio使用CMake和NDK實現應用自身被卸載時打開某一網址

licensed 項目 右鍵 ava 開發工具 not per 2.0 idt 實現應用自身被卸載時打開某一網址的c代碼 MyActivity: public class MyActivity extends Activity { /** * Calle

思科單臂路由實驗配置實現跨vlan通訊

單臂路由 思科單臂路由 配置參數如圖:PC1 vlan 20 20.1.1.1 網關20.1.1.254PC2 vlan 30 20.1.1.1 網關30.1.1.254PC3 vlan 40 40.1.1.1 網關40.1.1.254R1配置以下3個子接口地址:g0/0.1 20.1.1.254g0

iOS--CFMessagePort實現程序通訊

CFMessagePort屬於CoreFoundation框架中的類。因此可以在http://opensource.apple.com/tarballs/CF/CF-855.17.tar.gz中在原始碼,如果感興趣可以去看看。 下面說下CFMessagePortRef的具體使用。 首先建立一

C#使用SendMessage實現程序通訊的方法

本文例項講述了C#使用SendMessage實現程序間通訊的方法。分享給大家供大家參考。具體分析如下: 為了深入理解訊息機制,先來做一個測試專案 在新建專案的Form1的程式碼中,加入方法: ?

Linux 通過共享記憶體機制實現程序通訊

問題背景 編寫程式 sender ,它建立一個共享記憶體,然後等待使用者通過終端輸入一串字元,並將這串字元通過共享記憶體傳送給 receiver;最後,它等待 receiver 的應答,收到應答訊息後,將接收到的應答資訊顯示在終端螢幕上,刪除共享記憶體,結束程式的執行。 編寫 receiver 程

說說在 Vue.js 中如何實現元件通訊

1 用法 假設父元件的模板包含子元件,我們可以通過 props 來正向地把資料從父元件傳遞給子元件。props 可以是字串陣列,也可以是物件。 html: <div id="app"> <deniro-component message=""嫦娥四號"成功發射

linux 用命名管道實現程序通訊

什麼是命名管道 命名管道和匿名管道一樣適用於程序之間的通訊linux匿名管道詳解,但是使用範圍不同,匿名管道要求必須是親緣程序,而命名管道卻沒有這個限制,它可以用於同一臺機器主機上的任意程序間通訊。

說說在 Vue.js 中如何實現元件通訊(高階篇)

之前說過,可以使用 props 將資料從父元件傳遞給子元件。其實還有其它種的通訊方式,下面我們一一娓娓道來。 1 自定義事件 通過自定義事件,我們可以把資料從子元件傳輸回父元件。子元件通過 $emit() 來觸發事件,而父元件通過 $on() 來監聽事件,這是典型的觀察者模式。 htm

PipedInputStreamPipedOutputStream例項執行緒通訊

Java.io.PipedOutputStream and java.io.PipedInputStream has been introduced in JDK 1.0. PipedOutputStream and PipedInputStream both are con

ArcGIS中實現兩點連線

轉載:ArcGIS中,一個點集裡的點兩兩連線,比如有4個點,就連3+2+1=6條線 一、目標   一個點集裡的點兩兩連線,比如有4個點,則連3+2+1=6條線;有38個點,則連37+36+35+···+3+2+1=703條線,其原始座標資料及最終樣式類似於以下這種:  →

使用三層交換機實現VLAN通訊

實現PC0能與PC1、PC2、PC3通訊 1.先配置使得vlan內通訊,vlan間通訊隔離 對switch0 Switch>ena Switch#conf t Enter configuration commands, one per line. End with CNTL/Z

應用通訊方式HTTP和RPC

一、HTTP和RPC 1、Dobbo  RPC框架 2、Sping Cloud 微服務架構下的一站式解決方案。 微服務直接使用的是 Http restful方式   二、SpringCloud中服務間兩種restful RestTemplate Feign &nbs