Android 는 Aidl 기반 의 크로스 오 버 간 양 방향 통신 관리 센터

요즘 시간 과 정력 이 좀 있어 서 생각 나 는 게 있어 요.바로 상기 회사 에서 회사 가 앱 프로 세 스 간 의 통신 기능 을 요구 하 는 것 이다.앱 이 앱 에 대한 직접적인 크로스 프로 세 스 통신 이 아니 라 하나의 서비스 센터 를 통 해 수신 한 다음 에 리 트 윗 을 해서 앱 간 의 결합 성 이 높 지 않도록 한다.그렇지 않 으 면 앱 을 추가 하고 다른 앱 도 업그레이드 업 데 이 트 를 해 야 한다(서비스 센터 가 있 는 채 팅 방 과 유사).
내 가 몇 시간 동안 뭘 좀 쓸 게,기록 하 는 김 에.
안 드 로 이 드 장치 에 서 는 방송,socket,공유 메모리,adl 등 여러 가지 방식 이 있다 는 것 을 잘 알 고 있 습 니 다.그 중에서 방송 과 adl 은 모두 안 드 로 이 드 에서 iBinder 체 제 를 바탕 으로 합 니 다.
방송:
방송 에 결함 이 있다.즉,효율 이 높 지 않 아서 가끔 방송 을 잃 어 버 리 거나 방송의 대기 행렬 이 너무 길 어서 메시지 발송 이 느리다 는 것 이다.
공유 메모리:
공유 메모리 에 안전성 이 없고 다 중 스 레 드 로 데 이 터 를 읽 고 쓰 면 제어 할 수 없습니다.
socket:
socket 결합 도가 높 고 메모 리 는 두 번 복사 해 야 하 며 크로스 네트워크 에 적 용 됩 니 다.
AIDL:
binder 기반 으로 효율 이 높 음;C/S 구 조 를 바탕 으로 층 이 뚜렷 하고 기능 이 명확 하 다.리 눅 스 의 프로 세 스 ID 개념,더 안전 하 다 는 장점 이 있 습 니 다.
흐름 도

간단 한 구조 로 모든 앱 메시지 전달 은 서버 를 통 해 이 루어 집 니 다.프로젝트 구 조 는 다음 과 같 습 니 다.center(메시지 센터),app 1,app 2 는 lib(adl 인터페이스 라 이브 러 리)에 의존 합 니 다.

aidl 의 RemoteCallbackList 클래스(원리 와 원본 코드 를 이용 하여 더 이상 말 하지 않 겠 습 니 다.사실 Client 호출 Server 는 대동소이 합 니 다.단지 반대 자가 한 번 왔 을 뿐 입 니 다)를 이용 하여 client 의 인터페이스 리 셋 을 실현 할 수 있 습 니 다.그래 야 server 에서 자발적으로 client 에 게 메 시 지 를 보 낼 수 있 습 니 다.일반적으로 우 리 는 client 가 자발적으로 Server 를 호출 합 니 다.지금 은 Server 가 주동 적 으로 client 를 호출 할 차례 입 니 다.
서버 의 코드 는 다음 과 같 습 니 다.프로젝트 의 요구 에 따라 할 수 있 습 니 다.

package com.helang.messagecenterdemo;
 
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
 
import com.helang.lib.IMyAidlCallBackInterface;
import com.helang.lib.IMyAidlInterface;
 
/**
 *       (    manifest.xml    android:exported="true")
 */
public class MyService extends Service {
  private final static String TAG = MyService.class.getSimpleName();
  private RemoteCallbackList<IMyAidlCallBackInterface> callbackList = new RemoteCallbackList<>();//     (API>=17,    )
 
  @Override
  public void onCreate() {
    super.onCreate();
  }
 
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return iBinder;
  }
 
  /**
   *   iBinder
   */
  private IMyAidlInterface.Stub iBinder = new IMyAidlInterface.Stub() {
    @Override
    public void sendMessage(String tag, String message) throws RemoteException {
      callbackList.beginBroadcast();
      sendMessageToAllClient(tag,message);
      Log.d(TAG,"tag="+tag+" message="+message);
      callbackList.finishBroadcast();
    }
 
    @Override
    public void registerListener(IMyAidlCallBackInterface listener) throws RemoteException {
      callbackList.register(listener);//    listener
      Log.d(TAG,"registerListener");
    }
 
    @Override
    public void unregisterListener(IMyAidlCallBackInterface listener) throws RemoteException {
      callbackList.unregister(listener);//    listener
      Log.d(TAG,"unregisterListener");
    }
  };
 
  /**
   *         client(           client,  
   *              Bean,     Parcelable      
   * @param tag
   * @param message
   */
  private void sendMessageToAllClient(String tag,String message){
    for (int i = 0 ; i < callbackList.getRegisteredCallbackCount();i++){
      try {
        callbackList.getBroadcastItem(i).callback(tag,message);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }
  }
}
Client 1 과 Client 2 코드 는 같 습 니 다.서로 메 시 지 를 보 내 는 것 입 니 다.

package com.helang.app2;
 
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
import com.helang.lib.IMyAidlCallBackInterface;
import com.helang.lib.IMyAidlInterface;
 
public class MainActivity extends AppCompatActivity {
  private EditText editText;
  private Button bt_send;
  private TextView text;
 
  private IMyAidlInterface iMyAidlInterface;
  private ServiceCallBack serviceCallBack;
 
  private MyServiceConnection myServiceConnection;
 
  private Handler handler = new Handler();
 
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    bt_send = findViewById(R.id.bt_send);
    editText = findViewById(R.id.editText);
    text = findViewById(R.id.text);
 
    bt_send.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        if (iMyAidlInterface != null){
          try {
            iMyAidlInterface.sendMessage("app2",editText.getText().toString().trim());
          } catch (RemoteException e) {
            e.printStackTrace();
          }
        }
      }
    });
 
    bindService();
  }
 
  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService();
  }
 
  private void bindService(){
    myServiceConnection = new MyServiceConnection();
    serviceCallBack = new ServiceCallBack();
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.helang.messagecenterdemo",
        "com.helang.messagecenterdemo.MyService"));
    startService(intent);//      
    bindService(intent,myServiceConnection,BIND_AUTO_CREATE);//    
 
  }
 
  private void unbindService(){
    if (myServiceConnection != null){
      try {
        iMyAidlInterface.unregisterListener(serviceCallBack);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
      unbindService(myServiceConnection);
    }
  }
 
  /**
   *   Service
   */
  class MyServiceConnection implements ServiceConnection {
 
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
      iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
 
      handler.post(new Runnable() {
        @Override
        public void run() {
          //    
          if (iMyAidlInterface != null){
            try {
              iMyAidlInterface.registerListener(serviceCallBack);
            } catch (RemoteException e) {
              e.printStackTrace();
            }
          }
        }
      });
 
    }
 
    @Override
    public void onServiceDisconnected(ComponentName componentName) {
 
    }
  }
 
  /**
   * service  client  
   */
  class ServiceCallBack extends IMyAidlCallBackInterface.Stub{
 
    @Override
    public void callback(final String tag, final String message) throws RemoteException {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          text.append("tag="+tag+" message="+message);
        }
      });
    }
  }
}
효 과 를 보 세 요.클 라 이언 트 2(app 2)에서 클 라 이언 트 1(app 1)에 게 메 시 지 를 보 냅 니 다.


참고 로 Center 서 비 스 를 미리 엽 니 다.안 드 로 이 드 8.0 이후 버 전 은 다른 App 배경 프로 세 스 서 비 스 를 원 격 으로 시작 하기 때문에 통 하지 않 습 니 다.프론트 프로 세 스 를 연결 할 수 있 습 니 다.인터넷 방법 이 많 습 니 다.저 는 간단하게 처리 하 겠 습 니 다.
소스 코드 는 모두 github 에 두 었 습 니 다.MessageCenter
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기