1、新建一個服務端項目,app目錄右鍵New->AIDL->AIDL file,重命名aidl文件名
2、在aidl文件的接口裏聲明方法
//接口和方法聲明都不用public,方法加入public會提示錯誤
String teleplay();
3、編譯工程,在app/build/generated/source/aidl/debug會生成一個同名的java文件
4、新建一個客戶端項目,將服務端的整個aidl文件夾拷貝過來
如果你按服務端的方法新建aidl文件,然後只拷貝客戶端的包名和aidl文件過來覆蓋,或者直接修改aidl文件和包名會出現以下錯誤:
Error:Execution failed for task ':app:compileDebugAidl'.
> java.io.IOException: com.android.ide.common.process.ProcessException: Error while executing process C:\Users\Administrator\AppData\Local\Android\sdk\build-tools\26.0.2\aidl.exe with arguments {-pC:\Users\Administrator\AppData\Local\Android\sdk\platforms\android-26\framework.aidl
-oE:\ASWorkspace\AIDLTest\app\build\generated\source\aidl\debug -IE:\ASWorkspace\AIDLTest\app\src\main\aidl
-IE:\ASWorkspace\AIDLTest\app\src\debug\aidl
-IC:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\support-media-compat-26.1.0.aar\0ab74ae4163edf0259282212ea294d65\aidl
-IC:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\support-compat-26.1.0.aar\8120fcf75fb68b2bb03ddc6e108c3eba\aidl
-dC:\Users\ADMINI~1\AppData\Local\Temp\aidl2759574706819238886.d E:\ASWorkspace\AIDLTest\app\src\main\aidl\com.example.ndkjni\IMyAidlInterface.aidl}
解決辦法就是:刪掉客戶端整個aidl文件夾,直接把服務端的整個dial文件夾拷貝過來放在相應的位置即可
5、服務端新建一個Service類,並實現aidl文件裏面聲明的方法,將實現aidl文件裏方法的類的對象作爲IBinder返回給客戶端使用
package com.example.ndkjni;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return new TeleService();
}
class TeleService extends IMyAidlInterface.Stub{
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String teleplay() throws RemoteException {
return "if we meet at the beginning of our life--人生若如初相見";
}
}
}
在AndroidManifest.xml文件裏聲明:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
6、客戶端實現:
package com.example.aidltest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.ndkjni.IMyAidlInterface;
public class MainActivity extends AppCompatActivity {
private static TextView contentTv;
private ServerConnection serverConnection;
public static class ServerConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("wanlijun","onServiceConnected");
IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
try {
contentTv.setText(iMyAidlInterface.teleplay());
}catch (Exception e){
e.printStackTrace();
Log.i("wanlijun",e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i("wanlijun","onServiceDisconnected");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentTv = (TextView)findViewById(R.id.contentTv);
serverConnection = new ServerConnection();
}
@Override
protected void onResume() {
super.onResume();
//顯示調用遠程服務
Intent aidlIntent = new Intent();
aidlIntent.setComponent(new ComponentName("com.example.ndkjni","com.example.ndkjni.MyService"));
bindService(aidlIntent,serverConnection,BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
//解綁服務
unbindService(serverConnection);
}
}
7、客戶端異常報錯:
java.lang.RuntimeException: Unable to resume activity {com.example.aidltest/com.example.aidltest.MainActivity}:
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.ndkjni.MyService }
解決辦法:
Context.bindService() 方法現在需要顯式 Intent,如果提供隱式 intent,將引發異常
原先我是這麼寫的:
Intent aidlIntent = new Intent("com.example.ndkjni.MyService");
bindService(aidlIntent,serverConnection,BIND_AUTO_CREATE);
後來改爲:
Intent aidlIntent = new Intent();
aidlIntent.setComponent(new ComponentName("com.example.ndkjni","com.example.ndkjni.MyService"));
bindService(aidlIntent,serverConnection,BIND_AUTO_CREATE);
就解決了
8、先運行服務端,再運行客戶端,客戶端就可以happy的調用服務端的方法了