了解Android粘合剂

时间:2016-04-21 03:39:43

标签: android android-service ipc android-binder

我正在尝试理解一段使用Android Binders和Messages来执行IPC的代码。我已经阅读了一些关于绑定器的文章,论文和幻灯片,但我仍然感到困惑并且很难理解代码,因为我没有遇到任何在java代码中实际实现绑定器的教程/示例。我列出了下面的清理/缩写代码,以及我对它的作用以及混淆程度的理解。如果有人能帮助我理解这一点,我将不胜感激,特别是有关包裹和信息的流动。

MyService.java

public class MyService extends Service
{
  private final IMyService.Stub mBinder;
  private Context _mContext;
  private MyServiceHandler mHandler;
  private HanderThread mHandlerThread;
  private IHelperService mHelperService;

  public MyService() {
    this.mBinder = new IMyService.Stub() {
      public void start_data(final String data) {
      try {
        if (MyService.this.mHelperService == null) {
          return;
        }
        Message msg = MyService.this.getHandler().obtainMessage(3, (Object)data);
        MyService.this.getHandler().sendMessage(msg);
      } catch (SecurityException ex) {
        // do some logging
      }
    };
  }

  private void startMessageProcess(final String message) {
    // Process the message argument
    final byte[] dataArray = this.getByteArray(message);
    byte[] returnData;
    try {
      returnData = this.mHelperService.foo(dataArray);
    } catch (Exception e) {
      // do some logging
    }
    Message msg = this.getHandler().obtainMessage(3, (Object)message);
    this.getHandler.sendMessage(msg);
  }

  private String getServerData(int id) {
    // builds a Uri based on id and posts it, retrieves String data from HTTP entity and returns it
  }

  private boolean postDataToServer(final byte[] arrayData) {
    // builds a Uri, post data to it, gets the status code, returns true if successful
  }

  private void sendData(final byte[] arrayData) {
    final Intent intent = new Intent();
    intent.setAction("com.my.service.intent.action.MY_RESULT");
    intent.putExtra("com.my.service.intent.extra.RESULT", 0);
    intent.putExtra("com.my.service.intent.extra.MY_DATA", arrayData);
    this._mContext.sendBroadcast(intent, "com.my.service.permission.MY_PERMISSION");
  }

  public Handler getHandler() {
    return this.mHandler;
  }

  public IBinder onBind(final Intent intent) {
    if (intent != null) {
      final String action = intent.getAction();
      if (action != null && action.equals("com.my.service.intent.action.BIND_MY_SERVICE")) {
        this._mContext = this.getApplicationContext();
        return (IBinder)this.mBinder;
      }
    }
    return null;
  }

  public void onCreate() {
    super.onCreate();
    try {
      final Class<?> serviceManager = Class.forName("android.os.ServiceManager");
      this.mHelperService = mHelperService.Stub.asInterface((IBinder)serviceManager.getMethod("getService", String.class).invoke(serviceManager, "helperservice"));
      if (this.mHelperService == null) {
          return;
      }
    }
    catch (ClassNotFoundException ex2) {
        Log.e("MyService", "Helper service ClassNotFoundException !!!");
    }
    catch (Exception ex) {
        Log.e("MyService", "onCreate() Exception: " + Log.getStackTraceString((Throwable)ex));
    }
    this.mHandlerThread = new HandlerThread("MyService");
    this.mHandlerThread.start();
    this.mHandler = new MyServiceHandler(this.mHandlerThread.getLooper());
  }

  public int onStartCommand(final Intent intent, final int flags, final int startId) {
    if (intent != null) {
      super.onStartCommand(intent, flags, startId);
    }
    return START_NOT_STICKY;
  }

  private final class MyService Handler extends Handler
  {
    public MyServiceHandler(final Looper looper) {
      super(looper);
    }
    public void handleMessage(final Message message) {
      if (message != null) {
        switch (message.what) {
          case 2: {
            final String data = (String)message.obj;
            if (data != null) {
              MyService.this.startMessageProcess(data);
              return
            }
            break;
          }
          case 3: {
            MyService.this.sendData((byte[])message.obj);
          }
        }
      }
    }
  }
}

IMyService.java

public interface IMyService extends IInterface
{
  void start_data(final String p0) throws RemoteException;

  public abstract static class Stub extends Binder implements IMyService
  {

    public Stub() {
      this.attachInterface((IInterface)this, "com.my.service.IMyService");
    }

    public static IMyService asInterface(final IBinder binder) {
      if (binder == null) {
        return null;
      }
      final IInterface queryLocalInterface = binder.queryLocalInterface("com.my.service.IMyService");
      if (queryLocalInterface != null && queryLocalInterface instanceof IMyService) {
        return (IMyService)queryLocalInterface;
      }
      return new Proxy(binder);
    }

    public IBinder asBinder() {
      return (IBinder)this;
    }

    public boolean onTransact(final int code, final Parcel data, final Parcel reply, final int flags) throws RemoteException {
      switch (code) {
        case 1: {
          data.enforceInterface("com.my.service.IMyService");
          this.start_data(data.readString());
          reply.writeNoException();
          return true;
        }
        case 1000000000: {
          reply.writeString("com.my.service.IMyService");
          return true;
        }
        default: {
          return super.onTransact(n, data, reply, flags);
        }
      }
    }

    private static class Proxy implements IMyService
    {
      private IBinder mRemote;

      Proxy(final IBinder mRemote) {
        this.mRemote = mRemote;
      }

      public IBinder asBinder() {
        return this.mRemote;
      }

      public String getInterfaceDescriptor() {
        return "com.my.service.IMyService";
      }

      @Override
      public void start_data(final String data) throws RemoteException {
        final Parcel data = Parcel.obtain();
        final Parcel reply = Parcel.obtain();
        try {
          data.writeInterfaceToken("com.my.service.IMyService");
          data.writeString(data);
          this.mRemote.transact(1, data, reply, 0);
          reply.readException();
        }
        finally {
          reply.recycle();
          data.recycle();
        }
      }
    }
  }
}

IHelperService.java

public interface IHelperService extends IInterface
{
  // a bunch of method declarations here

  public abstract static class Stub extends Binder implements IHelperService
  {
    public Stub() {
      this.attachInterface((IInterface)this, "android.service.helper.IHelperService");
    }

    public static IHelperService asInterface(final IBinder binder) {
      if (binder == null) {
        if (queryLocalInterface != null && queryLocalInterface instanceof IHelperService) {
          return (IHelperService)queryLocalInterface;
        }
        return new Proxy(binder);
      }
    }

    public IBinder asBinder() {
      return (IBinder)this;
    }

    public boolean onTransact(int code, final Parcel data, final Parcle reply, int flags) throws RemoteException {
      switch (code) {
        // does a bunch of bunch of stuff here based on the incoming code            
      }
    }
  }

  private static class Proxy implements IHelperService
  {
    private IBinder mRemote;

    Proxy(final IBinder mRemote) {
      this.mRemote = mRemote;
    }

    @Override
    // a bunch of method definitions here, everything that was declared above
  }      
}

我很难跟踪谁发送给谁的东西。例如,在IMyService的代理中,start_data调用transact(mRemote),但是谁是mRemote?另外,在MyService()构造函数以及startMessageProcess中,调用sendMessage,是谁发送给?

然后,MyService中有一些似乎不在本地调用的私有方法,例如startMessageProcess和getServerData。如果他们是私人的,还有谁可以称这些方法?

0 个答案:

没有答案
相关问题