項目須要,將作好的項目做爲一個服務提供給另外一個公司。咱們須要提供一個apk,因此設計到進程間交互,不得不瞭解一下AIDL了。java
以前準備面試的時候,或多或少的瞭解了一點AIDL,不過如今忘記得差很少了。android
因此網上隨便找了幾篇不錯的文章。git
1.進程通訊之AIDL的使用。github
本身搞了一個簡單的demo。服務器
實現了進程間通訊,能夠傳輸普通類型和實體類型。app
首先是服務端。dom
1.第一個aidl接口。ide
// IMyAidlInterface.aidl package com.xf.test1; import com.xf.test1.IAidlCallBack; import com.xf.test1.Entity; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String getStr(String str); int getPid(); Entity getEntity(); Entity setEntity(in Entity entity); void registerCallBack(IAidlCallBack callback); void unregisterCallBack(IAidlCallBack callback); }
2.第二個aidl接口。佈局
// IAidlCallBack.aidl package com.xf.test1; import com.xf.test1.Entity; // Declare any non-default types here with import statements interface IAidlCallBack { void callBack(String name); void callBackEntity(in Entity entity); }
3.第三個aidl接口。
// Person.aidl package com.xf.test1; parcelable Entity;
4.封裝的一個IBinder。
package com.xf.test1; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; public class AIDLService extends Service { private AIDLImp mBinder; @Override public void onCreate() { super.onCreate(); mBinder = new AIDLImp(this); } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onDestroy() { super.onDestroy(); mBinder.KillAll(); } }
5.AIDL服務。
package com.xf.test1; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; public class AIDLService extends Service { private AIDLImp mBinder; @Override public void onCreate() { super.onCreate(); mBinder = new AIDLImp(this); } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onDestroy() { super.onDestroy(); mBinder.KillAll(); } }
6.實體類型。
package com.xf.test1; import android.os.Parcel; import android.os.Parcelable; /** * Description: 簡單實體類 * * @version V1.0.0 * Createdate: 2018/6/22 * @author: wja 1211241203@qq.com */ public class Entity implements Parcelable { private String name; private int parameter1; private double parameter2; public Entity(String name){ this.name=name; } public Entity(String name, int parameter1, double parameter2) { this.name = name; this.parameter1 = parameter1; this.parameter2 = parameter2; } public int getParameter1() { return parameter1; } public void setParameter1(int parameter1) { this.parameter1 = parameter1; } public double getParameter2() { return parameter2; } public void setParameter2(double parameter2) { this.parameter2 = parameter2; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.name); dest.writeInt(this.parameter1); dest.writeDouble(this.parameter2); } protected Entity(Parcel in) { this.name = in.readString(); this.parameter1 = in.readInt(); this.parameter2 = in.readDouble(); } public static final Creator<Entity> CREATOR = new Creator<Entity>() { @Override public Entity createFromParcel(Parcel source) { return new Entity(source); } @Override public Entity[] newArray(int size) { return new Entity[size]; } }; @Override public String toString() { return "Entity{" + "name='" + name + '\'' + ", parameter1=" + parameter1 + ", parameter2=" + parameter2 + '}'; } }
7.清單文件。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xf.test1"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <!--<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> <data android:scheme="com.xf.aidl.test" /> </intent-filter>--> </activity> <service android:name=".AIDLService"> <intent-filter> <action android:name="com.xf.aidl" /> <category android:name="android.intent.category.DEFAULT" /> <!--<action android:name="android.intent.action.MAIN" />--> <!--<category android:name="android.intent.category.LAUNCHER" />--> </intent-filter> </service> </application> </manifest>
8.服務端如何運行(不使用啓動圖標的方式)
而後點擊進去
9.最後點擊運行,服務就安裝在手機啦。
其次,是客戶端。
1.客戶端的aidl文件和服務端的徹底同樣。(固然路徑能夠不同,爲了方便我直接copy的,路徑不同也是能夠的,測試過的)
2.而後注意實體類型所在的包必定要和服務端的一致,負責找不到這個實體的。
3.最後是客戶端的主頁面。
package com.xf.test2; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import com.xf.test1.Entity; import com.xf.test1.IAidlCallBack; import com.xf.test1.IMyAidlInterface; import java.util.Random; public class MainActivity extends AppCompatActivity { private IMyAidlInterface mIMyAidlInterfaceService; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterfaceService = IMyAidlInterface.Stub.asInterface(service); try { mIMyAidlInterfaceService.registerCallBack(mIAidlCallBack); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { try { mIMyAidlInterfaceService.unregisterCallBack(mIAidlCallBack); } catch (RemoteException e) { e.printStackTrace(); } mIMyAidlInterfaceService = null; } }; private IAidlCallBack mIAidlCallBack = new IAidlCallBack.Stub() { @Override public void callBack(String name) throws RemoteException { Log.e("info---->","服務端給我發消息啦:"+name); ToastUtil.showShort(MainActivity.this,"服務端給我發消息啦:"+name); } @Override public void callBackEntity(Entity entity) { Log.e("info---->","服務端給我發實體消息啦:"+entity.toString()); ToastUtil.showShort(MainActivity.this,"服務端給我發實體消息啦:"+entity.toString()); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onDestroy() { super.onDestroy(); if (mServiceConnection != null) unbindService(mServiceConnection); } /** * 綁定服務 * @param view */ public void doClick(View view) { Intent intent = new Intent(); intent.setAction("com.xf.aidl"); intent.setPackage("com.xf.test1"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } /** * 獲取服務器發送過來的消息 * @param v */ public void doAction(View v) { if (mIMyAidlInterfaceService != null) { try { String newstr = mIMyAidlInterfaceService.getStr("Hello world"); int pid = mIMyAidlInterfaceService.getPid(); Log.e("info---->", newstr + " pid:" + pid); } catch (RemoteException e) { e.printStackTrace(); } } } /** * 客戶端本身設置實體,發送給服務端 * 經過隨機數設置實體參數 * @param v */ public void doActionSetEntity(View v){ if (mIMyAidlInterfaceService != null) { try { Random random=new Random(); mIMyAidlInterfaceService.setEntity(new Entity("客戶端",random.nextInt(100),random.nextDouble())); } catch (RemoteException e) { e.printStackTrace(); } } } }
下面是佈局文件。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <RelativeLayout android:layout_marginTop="100dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="300dp" android:layout_height="wrap_content" android:onClick="doClick" android:text="綁定服務" android:layout_centerInParent="true" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="300dp" android:layout_height="wrap_content" android:onClick="doAction" android:text="獲取消息" android:layout_centerInParent="true" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:layout_width="300dp" android:layout_height="wrap_content" android:onClick="doActionSetEntity" android:text="客戶端設置實體" android:layout_centerInParent="true" /> </RelativeLayout> </LinearLayout>
運行效果是這樣的:
這裏客戶端首先須要綁定服務
點擊了獲取消息:直接獲取服務端建立好的實體類。
點擊了客戶端設置實體:經過產生隨機數,客戶端調用aidl接口設置實體。
若是再次點擊獲取消息:在服務端進行判斷,若是客戶端設置過實體,就把該實體發送回客戶端。
demo地址:https://github.com/JasonToJan/AIDLDemo
1.首先要理解aidl是幹什麼的:進程間交互。不一樣apk實現通訊。
2.爲何能夠作到進程間通訊了,誰給兩個進程之間搭起了一座橋樑呢?AIDL,其實就是一個接口,實現進程之間對接的功能。
3.兩個進程要作到通訊,aidl必定要保證一致,否則就是牛頭不對馬嘴了。
4.aidl如何實現數據傳輸了,binder。因此demo就把binder直接封裝起來,基本全部邏輯都在這個封裝類中進行便可。
5.再深刻底層,binder是如何實現數據傳輸的呢?這就涉及到操做系統的知識了,binder處於一個內存共享區域,能夠實現進程間通訊。