1. 程式人生 > >AIDL實現跨APP通訊(雙向通訊)

AIDL實現跨APP通訊(雙向通訊)

某天,接到了一人任務要在兩個app互相傳遞一些訊息,上網查了以後發現有幾種方式。第一是廣播、第二是AIDL,由於初出茅廬全不會就選擇了AIDL。。。下面簡單粗暴的開始貼程式碼好了。也是得到了網上的一些借鑑,若有雷同,嗯你懂的。

1.我們需要先建立AIDL檔案。值得一提的是,我們要在main下建立一個專門用來放AIDL檔案的包。非常重要!


其中,AIDLClient.aidl是客戶端使用的介面,AIDLService是伺服器所用的介面,Info是我們要傳的自定義實體類。客戶端就是想要主動給另一個app傳送資訊的一端,伺服器就是接收資訊並可以返回資訊的一端。下面來看看最簡單的AIDL裡面該怎麼寫。

(1)AIDLClient.aidl

<pre style="font-family: 宋體; font-size: 9pt; background-color: rgb(255, 255, 255);"><pre name="code" class="java">// AIDLClient.aidl
package AIDL;

// Declare any non-default types here with import statements

interface AIDLClient {
    /**
     * 接收來自另一個app返回的資訊
     */
     void receiveByServer(String message);
}

(2)AIDLClient.aidl

package AIDL;

// Declare any non-default types here with import statements
import AIDL.AIDLClient;
import AIDL.AIDLService;

interface AIDLService {
    /**
     * 接收來自客戶端發來的資訊
     * @param info 實體類
     */
    Info getServerdanceInfo(in Info info);
}

在客戶端給伺服器傳送請求後,伺服器會返回一個Info型別的實體。

(3)Info.aidl

// Info.aidl
package AIDL;

parcelable Info;

在Info中我們要使用我們自己寫的實體類型別,而不是用基本型別。

(4)Info

public class Info implements Parcelable {
    private String message;
我們實體類中其實只有一個String型別,當然也可以有多個自己設定的型別,但是一定要使用AIDL中支援的幾個基本型別。剩下的就自動生成出get/set等就可以了,記得多寫一個預設建構函式。

2.在客戶端app中我們要實現點選按鈕,傳送訊息並將伺服器返回的訊息顯示著Textview中。

<pre name="code" class="java">public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity";
    private static final String BIND_ACTION = "AIDL.service";
    private Button button;
    private TextView textView;
    private AIDLService aidlServce;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init(){
        button = (Button)findViewById(R.id.sendAIDL);
        textView = (TextView)findViewById(R.id.receive);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //繫結服務
                getServiceConnect();
            }
        });
    }

    private void getServiceConnect(){
        Intent it = new Intent();
        it.setAction(BIND_ACTION);
        it.setPackage("com.example.zjl.aidlservice_demo");
        startService(it);
        bindService(it, serviceConnection,BIND_AUTO_CREATE);
    }

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG,"onServiceDisconnected");

        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG,"onServiceConnected");
            //獲取服務端傳過來的IBinder物件,通過該物件呼叫服務端的方法
            aidlServce = AIDLService.Stub.asInterface(service);
            if (aidlServce != null){
                handlerInfo();
            }
        }

    };

    private void handlerInfo(){
        Info mInfo = new Info();
        mInfo.setMessage("腫麼可以次兔兔");

        try {
            Info serverInfo = new Info();
            //呼叫服務端的方法
            serverInfo = aidlServce.getServerInfo(mInfo,mClient);
            unbindService(serviceConnection);
        }catch (RemoteException e){
            e.printStackTrace();
        }
    }

    AIDLClient.Stub mClient = new AIDLClient.Stub()
    {
        //客戶端回撥方法的具體實現
        @Override
        public void receiveByServer(String param) throws RemoteException {
            textView.setText(param);
        }
    };
}



這裡需要注意的是,在用Intent繫結服務的時候在5.0以後需要對package進行設定,否則會報錯。setPackage裡的引數為伺服器端的包名。XML就倆控制元件,一個button一個Textview就不寫了。

3.在伺服器中需要把AIDL連同包一起復制到main下同客戶端一樣。build後會自動生成java檔案,否則使用不了。


4.在服務端寫一個service用於接收來自客戶端的請求。

public class service extends Service {
    public static final String TAG = "DanceAIDLService";
    private AIDLClient aidlClient;
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    /**
     * 建立服務
     */
    @Override
    public void onCreate()
    {
        super.onCreate();
    }

    /**
     * 銷燬服務
     */
    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }

    /**
     * 啟動服務
     */
    @Override
    public void onStart(Intent intent, int startId)
    {
        super.onStart(intent, startId);
    }

    /**
     * 解綁服務
     */
    @Override
    public boolean onUnbind(Intent intent)
    {
        aidlClient = null;
        return super.onUnbind(intent);
    }

    //處理來自客戶端的訊息

    AIDLService.Stub mBinder = new AIDLService.Stub() {

        @Override
        public Info getServerInfo(Info info, AIDLClient client) throws RemoteException {

            aidlClient = client;
            aidlClient.receiveByServer("收到來自客戶端的訊息:"+info.getMessage());
            Log.d(TAG,info.getMessage()+"       ");

            Info newInfo = new Info();
            newInfo.setMessage(info.getMessage());

            return newInfo;

        }
    };
}

我們這把從客戶端發過來的資訊加了幾個字又返了回去。並且配置service。
<service
            android:name=".service"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="AIDL.service"></action>
            </intent-filter>
</service>

5.最後,還需要在build.gradle中新增用於區分aidl和java的命令。解除安裝Android括號內就可以。
 sourceSets{
        main{
            java.srcDirs = ['src/main/java', 'src/main/aidl']
        }
    }

怎麼樣是不是好簡單,但是AIDL那些檔案真的很容易出錯誤哦,所以在第一次寫的時候可能會總也調不好,有點耐心慢慢調吧~~