- 什么是aidl?
- aidl 能干什么?
- 怎么用 aidl?
- 实现一个最简单的aidl
以上4个问题,前面两个我不打算展开,我相信,关于这两个问题的说明和解答,已经有无数的大神详细的讲解过了。关于后面的两个问题,是我一直关心的问题。到刚才,我解决了第四个问题,但是第三个的话,我相信,得继续深入才能更好的回答。
好了,现在就开始第四个问题的实现。
- 简单说明一下,最简单的
aidl
实现,不需要多个app
,也不需要多个module
。只要一个service
,一个activity
,一个.aidl
文件。 - 但是,我不打算一开始就去实现最简单的
aidl
模型,我准备先写一个最简单的bindService
,作为过渡。一来,温习一下基础知识,二来,这个本身就是最简单的aidl
的前奏,必不可少。
那么,如何实现呢?还是从代码下手吧。
- 我先创建两个
activity
和一个service
.activity
为什么是两个?其实可以是一个,但是个人习惯,第一个总是作为入口,不做任何的真正逻辑,仅仅是作为目录和指引的作用。第二个是和服务对应的。也就是服务的调用者。清单文件如下:
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:supportsRtl="true"
- android:theme="@style/AppTheme" >
- <activity android:name=".activity.LauncherActivity" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <service
- android:name=".service.NormalService"
- android:enabled="true"
- android:exported="true" />
- <activity
- android:theme="@style/AppTheme.NoActionbar"
- android:name=".activity.NormalActivity" >
- </activity>
- </application>
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".activity.LauncherActivity" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".service.NormalService" android:enabled="true" android:exported="true" /> <activity android:theme="@style/AppTheme.NoActionbar" android:name=".activity.NormalActivity" > </activity> </application>
简单明了,我也没有任何的解释了。关于
service
上设置的两个属性分别是什么意思?我也不太了解。想了解的,可以自行搜索下,这个不是本文的重点。
- 然后,我们看一下入口的
activity
吧
- public class LauncherActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_launcher);
- findViewById(R.id.normal_service_btn).setOnClickListener(v -> {
- LogUtils.e("普通service 模式");
- // todo
- startActivity(new Intent(get(), NormalActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
- });
- findViewById(R.id.aidl_service).setOnClickListener(v -> {
- LogUtils.e("AIDL service 模式");
- // todo
- });
- }
- public AppCompatActivity get() {
- return this;
- }
- }
public class LauncherActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launcher); findViewById(R.id.normal_service_btn).setOnClickListener(v -> { LogUtils.e("普通service 模式"); // todo startActivity(new Intent(get(), NormalActivity.class) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); }); findViewById(R.id.aidl_service).setOnClickListener(v -> { LogUtils.e("AIDL service 模式"); // todo }); } public AppCompatActivity get() { return this; } }
依然是简单明了
- 接下来,我们去看看
NormalActivity
?不,这个是服务的调用者,我们先去看服务,这样清楚明了一点。
- public class NormalService extends Service {
- public NormalService() {
- }
- @Override
- public IBinder onBind(Intent intent) {
- LogUtils.w("normal service bind");
- return new LocalBinder();
- }
- @Override
- public boolean onUnbind(Intent intent) {
- LogUtils.w("normal service unbind");
- return super.onUnbind(intent);
- }
- @Override
- public void onRebind(Intent intent) {
- super.onRebind(intent);
- LogUtils.w("normal service rebind");
- }
- @Override
- public void onCreate() {
- super.onCreate();
- LogUtils.w("normal service create");
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- LogUtils.w("normal service start");
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- LogUtils.w("normal service destroy");
- }
- public class LocalBinder extends Binder {
- public NormalService get() {
- return NormalService.this;
- }
- }
- /**
- * public method invoked by caller
- *
- * @return a number of random
- */
- public int getResult() {
- return new Random().nextInt(500);
- }
- }
public class NormalService extends Service { public NormalService() { } @Override public IBinder onBind(Intent intent) { LogUtils.w("normal service bind"); return new LocalBinder(); } @Override public boolean onUnbind(Intent intent) { LogUtils.w("normal service unbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); LogUtils.w("normal service rebind"); } @Override public void onCreate() { super.onCreate(); LogUtils.w("normal service create"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.w("normal service start"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); LogUtils.w("normal service destroy"); } public class LocalBinder extends Binder { public NormalService get() { return NormalService.this; } } /** * public method invoked by caller * * @return a number of random */ public int getResult() { return new Random().nextInt(500); } }
代码略长,不过应该还算是清晰。而且里面没有什么实质性逻辑。最关键的方法就是
getResult()
。是让调用者调用的。另外,我实现了一个LocalBinder
,目的很明确,就是要让调用者可以绑定当前服务。
- 现在,该去看看该服务的调用者了。
- public class NormalActivity extends AppCompatActivity {
- public boolean bind;
- private NormalService.LocalBinder mBinder;
- private ServiceConnection mNormalConn;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_normal);
- setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle("Normal activity");
- final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
- upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP);
- getSupportActionBar().setHomeAsUpIndicator(upArrow);
- TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv);
- tvShowResult.setText(getString(R.string.show_about_normal_service, ""));
- Button btnExecute = (Button) findViewById(R.id.normal_ui_btn);
- btnExecute.setOnClickListener(v -> {
- LogUtils.w("execute normal service method...");
- LogUtils.w("execute normal service method...");
- if (bind) {
- int result = mBinder.get().getResult();
- LogUtils.e("result=====" + result);
- tvShowResult.setText(getString(R.string.show_about_normal_service, result));
- } else {
- LogUtils.e("bind service fail ,try again......");
- bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE);
- ToastHelper.show(getApplication(), "bind service fail ,try again......");
- }
- });
- mNormalConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- bind = true;
- LogUtils.w("normal activity connected normal service...");
- mBinder = (NormalService.LocalBinder) service;
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- bind = false;
- mBinder = null;
- LogUtils.w("normal activity disconnected normal service!");
- }
- };
- bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unbindService(mNormalConn);
- LogUtils.e("$$$ unbind normal service");
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }
public class NormalActivity extends AppCompatActivity { public boolean bind; private NormalService.LocalBinder mBinder; private ServiceConnection mNormalConn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("Normal activity"); final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha); upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP); getSupportActionBar().setHomeAsUpIndicator(upArrow); TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv); tvShowResult.setText(getString(R.string.show_about_normal_service, "")); Button btnExecute = (Button) findViewById(R.id.normal_ui_btn); btnExecute.setOnClickListener(v -> { LogUtils.w("execute normal service method..."); LogUtils.w("execute normal service method..."); if (bind) { int result = mBinder.get().getResult(); LogUtils.e("result=====" + result); tvShowResult.setText(getString(R.string.show_about_normal_service, result)); } else { LogUtils.e("bind service fail ,try again......"); bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); ToastHelper.show(getApplication(), "bind service fail ,try again......"); } }); mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); mBinder = (NormalService.LocalBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } }; bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mNormalConn); LogUtils.e("$$$ unbind normal service"); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } }
代码略长,因为里面还做了除了调用服务之外的其他操作。关键代码看 20~50 ,这30行的代码即可。这个代码也不用解释了,就是在界面上有一个按钮,每次点击按钮都会调用服务里面的方法得到一个随机数,并显示在
textview
上面罢了。至于怎么去绑定服务,我相信大家都很娴熟了,不必再解释了。
不过我觉得值得注意的是38行的代码mBinder = (NormalService.LocalBinder) service;
,也就是我们通过类型强转得到一个我们自己定义的IBinder
对象,也只有得到它,才能得到服务的对象,然后调用服务里面的方法。
- ok,代码结束了,一个最简单的
bindService
完成了。运行截图就不贴了,没意义,大家都知道是什么样子的。
.........................
现在,去实现最简单的aidl
,也就是基于当前代码的一些修改。
那么,要怎么修改呢? 首先,我们给service
设置一个单独的进程,修改清单文件,在service
节点里面添加一个属性android:process=":normal"
.这样就让service
和'activity'之间跨进程了。 然后,我们什么也不做,直接运行代码。注意:我们所做的修改仅仅是给service
设置了一个单独的进程,java
代码没有改动一行。
现在运行之后,是什么样子的效果呢?程序崩溃了。看日志:
- FATAL EXCEPTION: main
- Process: com.pythoncat.ipcorservice, PID: 2811
- java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder
- at com.pythoncat.ipcorservice.activity.NormalActivity$1.onServiceConnected(NormalActivity.java:58)
- at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1256)
- at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1273)
- at android.os.Handler.handleCallback(Handler.java:815)
- at android.os.Handler.dispatchMessage(Handler.java:104)
- at android.os.Looper.loop(Looper.java:194)
- at android.app.ActivityThread.main(ActivityThread.java:5667)
- at java.lang.reflect.Method.invoke(Native Method)
- at java.lang.reflect.Method.invoke(Method.java:372)
- at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:962)
- at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
FATAL EXCEPTION: main Process: com.pythoncat.ipcorservice, PID: 2811 java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder at com.pythoncat.ipcorservice.activity.NormalActivity$1.onServiceConnected(NormalActivity.java:58) at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1256) at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1273) at android.os.Handler.handleCallback(Handler.java:815) at android.os.Handler.dispatchMessage(Handler.java:104) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5667) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:962) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
真正有用的日志就一行
- java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder`.
java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.pythoncat.ipcorservice.service.NormalService$LocalBinder`.
看了日志我们大概明白了,我们拿到的Ibinder
对象,并不是我们在service
中定义的NormalService$LocalBinder
对象。
那么,为什么会这样呢?简单的理解就是,每个进程的内存是独立的,在A进程开辟的内存,B进程并不能访问。如何解决? 我并不知道怎么解决。看大神们的博客大概就是说,通过
IBinder
所在的共享内存区域进行数据交换,实现跨进程通信,实现起来也就是aidl
.
- 关于这方面的理论知识,我也不多介绍了,无论是android官方文档,还是一些大神的博客,都对此有比较清晰的介绍。我就简单说一下实现方式。
既然当前activity
和service
不在同一个进程了,无法通过之前的方式直接拿到IBinder
对象,那么,我们就定义一个.aidl
来实现之间的通信。
从上面的代码上看,我们实际上是希望调用service
中的getResult()
方法。那么,我们就定义一个.aidl
里面包含该方法即可。
- 1.如何操作?右键
app
module --> new --> AIDL -->AIDL File .然后写一个文件名如:NormalBinder
,然后直接回车。在里面添加需要调用的service
中的方法。
- interface NormalBinder {
- /**
- * Demonstrates some basic types that you can use as parameters
- * and return values in AIDL.
- */
- void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
- double aDouble, String aString);
- int getResult();
- }
interface NormalBinder { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); int getResult(); }
- 2.接下来,rebuild一下项目。会自动生成一些Java文件。至于生成的是什么,在哪里,这里也不说明了,跟主题无关。
- 3.然后,在
service
中去实现一个可用于aidl
的IBinder
.
- public class RemoteBinder extends NormalBinder.Stub {
- @Override
- public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
- }
- @Override
- public int getResult() throws RemoteException {
- return new Random().nextInt(500);
- }
- }
public class RemoteBinder extends NormalBinder.Stub { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int getResult() throws RemoteException { return new Random().nextInt(500); } }
修改之后的service
长这样子:
- public class NormalService extends Service {
- public NormalService() {
- }
- @Override
- public IBinder onBind(Intent intent) {
- LogUtils.w("normal service bind");
- // return new LocalBinder();
- return new RemoteBinder();
- }
- @Override
- public boolean onUnbind(Intent intent) {
- LogUtils.w("normal service unbind");
- return super.onUnbind(intent);
- }
- @Override
- public void onRebind(Intent intent) {
- super.onRebind(intent);
- LogUtils.w("normal service rebind");
- }
- @Override
- public void onCreate() {
- super.onCreate();
- LogUtils.w("normal service create");
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- LogUtils.w("normal service start");
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- LogUtils.w("normal service destroy");
- }
- public class LocalBinder extends Binder {
- public NormalService get() {
- return NormalService.this;
- }
- }
- /**
- * public method invoked by caller
- *
- * @return a number of random
- */
- public int getResult() {
- return new Random().nextInt(500);
- }
- public class RemoteBinder extends NormalBinder.Stub {
- @Override
- public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
- }
- @Override
- public int getResult() throws RemoteException {
- return new Random().nextInt(500);
- }
- }
- }
public class NormalService extends Service { public NormalService() { } @Override public IBinder onBind(Intent intent) { LogUtils.w("normal service bind"); // return new LocalBinder(); return new RemoteBinder(); } @Override public boolean onUnbind(Intent intent) { LogUtils.w("normal service unbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); LogUtils.w("normal service rebind"); } @Override public void onCreate() { super.onCreate(); LogUtils.w("normal service create"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.w("normal service start"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); LogUtils.w("normal service destroy"); } public class LocalBinder extends Binder { public NormalService get() { return NormalService.this; } } /** * public method invoked by caller * * @return a number of random */ public int getResult() { return new Random().nextInt(500); } public class RemoteBinder extends NormalBinder.Stub { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int getResult() throws RemoteException { return new Random().nextInt(500); } } }
- 4.然后需要修改调用的
activity
了。
得将之前的IBinder
对象换成可以aidl
的IBinder
了。
- mNormalConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- bind = true;
- LogUtils.w("normal activity connected normal service...");
- // mBinder = (NormalService.LocalBinder) service;
- mBinder = NormalBinder.Stub.asInterface(service);
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- bind = false;
- mBinder = null;
- LogUtils.w("normal activity disconnected normal service!");
- }
- };
mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); // mBinder = (NormalService.LocalBinder) service; mBinder = NormalBinder.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } };
发现什么改变了没有,就是将第6行替换成第7行。也就是
mbinder
的获取方式改变了,得到的对象也不是之前的对象了。
完全替换之后的activity
长这样子的
- public class NormalActivity extends AppCompatActivity {
- public boolean bind;
- private ServiceConnection mNormalConn;
- private NormalBinder mBinder;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_normal);
- setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle("Normal activity");
- final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
- upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP);
- getSupportActionBar().setHomeAsUpIndicator(upArrow);
- TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv);
- tvShowResult.setText(getString(R.string.show_about_normal_service, ""));
- Button btnExecute = (Button) findViewById(R.id.normal_ui_btn);
- btnExecute.setOnClickListener(v -> {
- LogUtils.w("execute normal service method...");
- LogUtils.w("execute normal service method...");
- if (bind) {
- // int result = mBinder.get().getResult();
- int result = 0;
- try {
- result = mBinder.getResult();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- LogUtils.e("result=====" + result);
- tvShowResult.setText(getString(R.string.show_about_normal_service, result));
- } else {
- LogUtils.e("bind service fail ,try again......");
- bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE);
- ToastHelper.show(getApplication(), "bind service fail ,try again......");
- }
- });
- mNormalConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- bind = true;
- LogUtils.w("normal activity connected normal service...");
- // mBinder = (NormalService.LocalBinder) service;
- mBinder = NormalBinder.Stub.asInterface(service);
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- bind = false;
- mBinder = null;
- LogUtils.w("normal activity disconnected normal service!");
- }
- };
- bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unbindService(mNormalConn);
- LogUtils.e("$$$ unbind normal service");
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }
public class NormalActivity extends AppCompatActivity { public boolean bind; private ServiceConnection mNormalConn; private NormalBinder mBinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_normal); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("Normal activity"); final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha); upArrow.setColorFilter(getResources().getColor(R.color.colorWhite), PorterDuff.Mode.SRC_ATOP); getSupportActionBar().setHomeAsUpIndicator(upArrow); TextView tvShowResult = (TextView) findViewById(R.id.normal_show_tv); tvShowResult.setText(getString(R.string.show_about_normal_service, "")); Button btnExecute = (Button) findViewById(R.id.normal_ui_btn); btnExecute.setOnClickListener(v -> { LogUtils.w("execute normal service method..."); LogUtils.w("execute normal service method..."); if (bind) { // int result = mBinder.get().getResult(); int result = 0; try { result = mBinder.getResult(); } catch (RemoteException e) { e.printStackTrace(); } LogUtils.e("result=====" + result); tvShowResult.setText(getString(R.string.show_about_normal_service, result)); } else { LogUtils.e("bind service fail ,try again......"); bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); ToastHelper.show(getApplication(), "bind service fail ,try again......"); } }); mNormalConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = true; LogUtils.w("normal activity connected normal service..."); // mBinder = (NormalService.LocalBinder) service; mBinder = NormalBinder.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { bind = false; mBinder = null; LogUtils.w("normal activity disconnected normal service!"); } }; bindService(new Intent(this, NormalService.class), mNormalConn, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mNormalConn); LogUtils.e("$$$ unbind normal service"); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } }
-
现在,一个最简单的
aidl
就完成了。现在运行代码,和之前的效果完全一样。还是每点击一次按钮,就会在textview
上显示一个500以内的随机数。不过,现在是跨进程调用了,不再是同一个进程了。为什么说是跨进程?你可以尝试分别输出service
所在的pid
和activity
所在的pid
就一目了然了。int pid = Process.myPid();
,可以使用这句代码完成当前pid
的获取。
吐槽下 amd 的cpu,超级辣鸡!android studio 能卡死,即使是16G内存,2G独显,120G的固态。
结语
- 相信通过这长篇的说明,大家知道怎么去写一个最简单的
aidl
了。我想,通过这个记录,我应该也会对实现最简单的一个aidl
更加熟练一点。 - 但是,我们知道
aidl
的使用场景往往是多module
之间,多app
之间。而且进行数据的交互可能是相互的,不仅仅是一方输出,一方接收。而是双方都能输出,双方都能够接收。而且传输的数据也不仅仅是基本类型的数据,可能是一个pojo
类型的数据。 - 没有关系,这只是一个开始。目的是抛砖引玉。
- 后续,我也会不定期更新这方面的知识。
最后,关于我:野生安卓猿一只,入安卓坑已有几年,一直徘徊在新手和菜鸟之间。