1.aidl service端
1)創建aidl文件
New--->AIDL--->AIDL file
就會生成一個IPerson.aidl文件
// IPerson.aidl
package com.example.aidlserverdemo;
// Declare any non-default types here with import statements
interface IPerson {
void setAge(int age);
void setName(String name);
String display();
}
2)aidl文件編寫完畢之後,需要Build--->Make Module 'aidlserverdemo',生成相應的java文件。
IPerson.java文件目錄如下:
3)aidl接口的實現類(IPersonImpl)
package com.example.aidlserverdemo;
import android.os.RemoteException;
public class IPersonImpl extends IPerson.Stub {
// 聲明兩個變量
private int age;
private String name;
@Override
public void setAge(int age) throws RemoteException {
this.age = age;
}
@Override
public void setName(String name) throws RemoteException {
this.name = name;
}
@Override
public String display() throws RemoteException {
return "name:zzz;age=18";
}
}
4)MyRemoteService
package com.example.aidlserverdemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyRemoteService extends Service {
// 聲明IPerson接口
private Binder iPerson;
@Override
public void onCreate() {
super.onCreate();
if (iPerson == null) {
iPerson = new IPersonImpl();
}
}
@Override
public IBinder onBind(Intent intent) {
return iPerson;
}
}
5)AndroidManifest.xml
<service
android:name=".MyRemoteService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.aidlserverdemo.MyRemoteService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
6)開啓服務
注意這裏有兩個坑,第一個就是Intent的action一定要寫AndroidManifest.xml裏面service的action;
package com.example.aidlserverdemo;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
// 設置Intent的Action 屬性
intent.setAction("com.example.aidlserverdemo.MyRemoteService");
Intent finalIntent = IntentUtils.createExplicitFromImplicitIntent(this, intent);
// 綁定服務
startService(finalIntent);
}
}
第二個坑就是需要將隱式的intent轉變爲顯示的intent
package com.example.aidlserverdemo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import java.util.List;
public class IntentUtils {
/***
* Android L (lollipop, API 21) introduced a new problem when trying to invoke implicit intent,
* "java.lang.IllegalArgumentException: Service Intent must be explicit"
*
* If you are using an implicit intent, and know only 1 target would answer this intent,
* This method will help you turn the implicit intent into the explicit form.
*
* Inspired from SO answer: http://stackoverflow.com/a/26318757/1446466
* @param context
* @param implicitIntent - The original implicit intent
* @return Explicit Intent created from the implicit original intent
*/
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
}
然後將service端運行開啓,因爲client是基於service的,一定要開啓。
2.aidl client端
1.IPerson.aidl
把服務端的IPerson.aidl拷貝過來,並執行Build--->Make Module 'aidlserverdemo'
1)創建ServiceConnection對象
// 實例化ServiceConnection
private ServiceConnection conn = new ServiceConnection() {
@Override
synchronized public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("MainActivity","onServiceConnected()---------->");
// 獲得IPerson接口
iPerson = IPerson.Stub.asInterface(service);
Log.d("MainActivity","iperson----------:" + iPerson);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("MainActivity","onServiceDisconnected()---------->");
iPerson = null;
}
};
2)綁定
注意這裏也有坑,必須加上package和action,package是服務端的包名,action是上面service的action。
Intent intent = new Intent();
//在5.0及以上版本必須要加上這個
intent.setPackage("com.example.aidlserverdemo");
intent.setAction("com.example.aidlserverdemo.MyRemoteService");//這個是上面service的action
bindService(intent, conn, Service.BIND_AUTO_CREATE);
3)調用
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String msg = iPerson.display();
// 顯示方法調用返回值
Log.d("MainActivity", "msg====>" + msg);
} catch (Exception e) {
Log.d("MainActivity", "e====>" + e);
e.printStackTrace();
}
}
});
4)解綁
@Override
protected void onDestroy() {
if (conn != null) {
unbindService(conn);
}
super.onDestroy();
}
5)運行結果:
2020-07-02 09:56:20.461 9151-9151/com.example.aidlclientdemo D/MainActivity: msg====>name:zzz;age=18