AIDL實例解析

AIDL:
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的調用服務端的方法了
發佈了65 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章