Androidは2つのアプリ間の通信と相互メッセージコールバックにAIDLを使用します(1)

序文:

AIDL:Android Interface Definition Languageに翻訳されたAndroid Interface Definition Language。これは、サーバーとクライアント間の通信インターフェースを定義するために使用される記述言語であり、IPCのコードを生成するために使用できます。したがって、AIDLを使用するにはサーバーとクライアントの
役割が必要です。別のプロセスのデータを取得し、1つのプロセスで公開されているメソッドを呼び出して、プロセス間通信のニーズを満たすことができます。

1. AIDLがサポートする基本的なデータ型

  1. 8つの基本的なデータ型:バイト、char、short、int、long、float、double、boolean
  2. 文字列、CharSequence
  3. Parcelableインターフェースのデータ型を実装します
  4. リストのタイプ。リストによって運ばれるデータは、AIDL、または他の宣言されたAIDLオブジェクトによってサポートされるタイプである必要があります
  5. マップタイプ。マップによって運ばれるデータは、AIDLまたは他の宣言されたAIDLオブジェクトでサポートされているタイプである必要があります

2.サーバーの実装

   必要なプロジェクトとAIDLファイルを作成します

  • Android Studioを使用して、TestAidlDemo1という名前の新しいプロジェクトを作成します。
  • 新しいIAidlInterfaceという名前のAIDLファイルを右クリックします。ASは、プロジェクトディレクトリに同じパスを持つAIDLフォルダーを自動的に生成します。
  • メッセージをコールバックしたいので、コールバックインターフェースも必要です。同じように、IAidlCallBack.aidlファイルを作成してから、コードの記述に進んでください

コードロジックを実装する

  • IAidlInterface.aldiコードを記述します。コールバックメッセージが必要なため、コールバックを登録および登録解除する必要があります。メッセージを送信するためのインターフェイス、履歴メッセージを取得するためのインターフェイスです。コードは次のとおりです(AIDLファイルは自動的にガイドされません。一部は基本的なサポートではありません)データ型は自分で手動でインポートする必要があります
    import com.pgc.testaidldemo1.IAidlCallBack;
    interface IAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void registerCallBack(IAidlCallBack iAidlCallBack);
        void unregisterCallBack(IAidlCallBack iAidlCallBack);
        void sendMessage(String message);
        List<String> getMessages();
    }
    

     

  • IAidlCallBack.aidlコードを記述します。これはコールバックインターフェースであるため、メッセージを正常に送信するにはコールバックインターフェースのみが必要です。コードは次のとおりです。

    interface IAidlCallBack {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void onMessageSuccess(String message);
    }

     

  • これはサーバーであるため、メッセージを受信して​​メッセージを処理するためのロジックコードを実装する必要があります。サービスはコールバックを直接受信できないため、コールバックを登録するためのRemoteCallbackListを提供するため、AidlServiceを作成してサービスを継承します。

    private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>();

    同時に、RemoteCallbackListはbeginBroadcastを提供して現在登録されているコールバックの数を取得するため、このメソッドを使用してコールバック処理を実行できます(beginBroadcastを使用した後、finishBroadcastを呼び出す必要があります。そうでない場合は、ブロードキャストエラーが発生しているときに呼び出されたbeginBroadcast()を報告します

    final int num=callbackList.beginBroadcast();
    for (int i=0;i<num;i++){
         IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
         iAidlCallBack.onMessageSuccess(message);
        }
    callbackList.finishBroadcast();

     次に、バインダーオブジェクトがインスタンス化され、クライアントに返されます。

    @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
            @Override
            public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.register(iAidlCallBack);
            }
    
            @Override
            public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.unregister(iAidlCallBack);
            }
    
            @Override
            public void sendMessage(String message) throws RemoteException {
                messages.add(message);
                final int num=callbackList.beginBroadcast();
                for (int i=0;i<num;i++){
                    IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
                    iAidlCallBack.onMessageSuccess(message);
                }
                callbackList.finishBroadcast();
            }
    
            @Override
            public List<String> getMessages() throws RemoteException {
                return messages;
            }
        };

      

  • AndroidManifest.xmlにサービスを登録する

    <service android:name=".AidlService"
             android:enabled="true"
             android:exported="true"
                >
        <intent-filter android:priority="1000">
                <action android:name="AIDL.service"></action>
       </intent-filter>
    </service>

     

  • AidlServiceすべてのコード

    package com.pgc.testaidldemo1;
    
    import android.annotation.SuppressLint;
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteCallbackList;
    import android.os.RemoteException;
    
    import androidx.annotation.Nullable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    /**
     * Created by PengGuiChu on 2020/4/11.
     */
    @SuppressLint("Registered")
    public class AidlService extends Service {
        private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>();
        private List<String> messages=new ArrayList<>();
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
            @Override
            public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.register(iAidlCallBack);
            }
    
            @Override
            public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.unregister(iAidlCallBack);
            }
    
            @Override
            public void sendMessage(String message) throws RemoteException {
                messages.add(message);
                final int num=callbackList.beginBroadcast();
                for (int i=0;i<num;i++){
                    IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
                    iAidlCallBack.onMessageSuccess(message);
                }
                callbackList.finishBroadcast();
            }
    
            @Override
            public List<String> getMessages() throws RemoteException {
                return messages;
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    }
    

     

  • サーバーとクライアントが相互メッセージコールバックを実装しているため、サーバーとAidlServiceが同じスレッド上にあるため、クライアントに対して、サーバー側のバインダーサービスを通じてバインダーも取得する必要があります。

    Intent intent=new Intent(getApplicationContext(),AidlService.class);
    bindService(intent,serviceConnection,BIND_AUTO_CREATE);

    次にServiceConnectionをインスタンス化します

    private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
    };

    次に、onServiceConnectedでバインダーを取得します。

    iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
    try {
          iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
          iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
          messages.addAll(iAidlInterface.getMessages());//获取历史消息
          listView.setAdapter(arrayAdapter=new ArrayAdapter<> 
          (getApplicationContext(),android.R.layout.simple_list_item_1,messages));
    } catch (RemoteException e) {
           e.printStackTrace();
    }

    DeathRecipientインスタンス

        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
            }
        };

    iAidlCallBackインスタンス

        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };

     MainActivity完全なコード

    package com.pgc.testaidldemo1;
    
    
    
    import android.annotation.SuppressLint;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.RemoteException;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class MainActivity extends AppCompatActivity {
        @BindView(R.id.list_view)
        ListView listView;
        private IAidlInterface iAidlInterface;
        private int num;
        private List<String> messages=new ArrayList<>();
        private ArrayAdapter arrayAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            Intent intent=new Intent(getApplicationContext(),AidlService.class);
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
        }
    
    
        @OnClick(R.id.send_message)
        public void onViewClicked(View view) {
            if (iAidlInterface!=null){
                try {
                    iAidlInterface.sendMessage("消息"+num);
                    num++;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
                try {
                    iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
                    iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
                    messages.addAll(iAidlInterface.getMessages());//获取历史消息
                    listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    
        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
            }
        };
    
        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };
    
        @SuppressLint("HandlerLeak")
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                arrayAdapter.notifyDataSetChanged();
            }
        };
    
        @Override
        protected void onDestroy() {
            //解除注册
            if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            //解除绑定服务
            unbindService(serviceConnection);
            super.onDestroy();
        }
    }
    

    この時点で、サーバーは効果を達成するようにコード化されています

3.クライアントの実装

   クライアントプロジェクトを作成する

  •      TestAidlDemo1プロジェクトを選択し、clientという名前の新しいモデルを右クリックします。
  • クライアントプロジェクトをサービスに接続できる場合は、上記のプロジェクトのAIDLファイルをクライアントプロジェクトのメインファイルに直接コピーします。これにより、2つのプロジェクトのAIDLファイルのパスが同じになります。

       

  • 呼び出しロジックは基本的に上記のMainActivityと同じです。1つの注意点は、2つの異なるプロセスであるため、ここでは直接bindServiceを使用してサーバーを呼び出すことはできませんが、次のコードを使用することです。
    Intent intent=new Intent();
    String ACTION = "AIDL.service";//对应服务端AndroidManifest.xml配置service action:name
    intent.setAction(ACTION);
    intent.setPackage("com.pgc.testaidldemo1");//对应服务端AndroidManifest.xml package
    bindService(intent,serviceConnection,BIND_AUTO_CREATE);

     

  • クライアントMainActivityのすべてのコード

    package com.pgc.client;
    
    import android.annotation.SuppressLint;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.RemoteException;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.pgc.testaidldemo1.IAidlCallBack;
    import com.pgc.testaidldemo1.IAidlInterface;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class MainActivity extends AppCompatActivity {
        @BindView(R.id.list_view)
        ListView listView;
        private IAidlInterface iAidlInterface;
        private int num;
        private List<String> messages=new ArrayList<>();
        private ArrayAdapter arrayAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            Intent intent=new Intent();
            String ACTION = "AIDL.service";
            intent.setAction(ACTION);
            intent.setPackage("com.pgc.testaidldemo1");
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
        }
    
    
        @OnClick(R.id.send_message)
        public void onViewClicked(View view) {
            if (iAidlInterface!=null){
                try {
                    iAidlInterface.sendMessage("消息"+num);
                    num++;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
                try {
                    iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);
                    iAidlInterface.registerCallBack(iAidlCallBack);
                    messages.addAll(iAidlInterface.getMessages());
                    listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    
        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
                //断线重来逻辑
            }
        };
    
        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };
    
        @SuppressLint("HandlerLeak")
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                arrayAdapter.notifyDataSetChanged();
            }
        };
    
        @Override
        protected void onDestroy() {
            //解除注册
            if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            //解除绑定服务
            unbindService(serviceConnection);
            super.onDestroy();
        }
    }
    

     

  • ランニング効果

ソースコードのダウンロードアドレス

https://github.com/pengkongkong/TestAidlDemo1

16件の元の記事を公開 19件の賞賛 40,000回以上の閲覧

おすすめ

転載: blog.csdn.net/pengguichu/article/details/105456309