Activity
aidl接口文件
package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为【.aidl】去掉public等所有修饰符。 更改后,会在gen目录下生成一个同名的.java文件,此java文件中有一个名为【Stub】的内部类,此内部类继承自Binder类且实现了我们这里定义的IBinderInterface接口 此内部类的【asInterface(IBinder)】方法会将IBinder类型的对象转换成IBinderInterface接口类型,此内部类可以在进程间通讯*/ void callMethodInService(); }
自动生成的Java接口文件
/* * This file is auto-generated. DO NOT MODIFY. Original file: * D:\\workspace_bqt\\??????\\src\\com\\bqt\\aidlservice\\IBinderInterface.aidl */ package com.bqt.aidlservice; public interface IBinderInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.bqt.aidlservice.IBinderInterface { private static final java.lang.String DESCRIPTOR = "com.bqt.aidlservice.IBinderInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.bqt.aidlservice.IBinderInterface interface, * generating a proxy if needed. */ public static com.bqt.aidlservice.IBinderInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.bqt.aidlservice.IBinderInterface))) { return ((com.bqt.aidlservice.IBinderInterface) iin); } return new com.bqt.aidlservice.IBinderInterface.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_callMethodInService: { data.enforceInterface(DESCRIPTOR); this.callMethodInService(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.bqt.aidlservice.IBinderInterface { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } /* * 更改文件后缀为.aidl,去掉public等所有修饰符。 更改后,会在gen/包名 * 目录下生成一个同名的java文件,此java文件中有一个名为 * 【Stub】的内部类,此内部类继承自Binder类且实现了我们这里定义的IBinderInterface接口 * 此内部类的【asInterface * (IBinder)】方法会将IBinder类型的对象转换成IBinderInterface接口类型,此内部类可以在进程间通讯 */ @Override public void callMethodInService() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_callMethodInService, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_callMethodInService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } /* * 更改文件后缀为.aidl,去掉public等所有修饰符。 更改后,会在gen/包名目录下生成一个同名的java文件 * 此java文件中有一个名为【Stub】的内部类,此内部类继承自Binder类且实现了我们这里定义的IBinderInterface接口 * 此内部类的【asInterface(IBinder)】方法会将IBinder类型的对象转换成IBinderInterface接口类型,此内部类可以在进程间通讯 */ public void callMethodInService() throws android.os.RemoteException; }
远程Service
public class MyRemoteService extends Service { @Override public void onCreate() { Log.i("bqt", "onCreate"); super.onCreate(); } @Override public IBinder onBind(Intent intent) {//如果再次使用bindService绑定Service,系统不会再调用onBind()方法,而是直接把IBinder对象传递给其他后来增加的客户端 Log.i("bqt", "onBind"); return new MyBinder();//当访问者通过bindService方法与Service连接成功后,系统会将此返回的IBinder接口类型对象,通过bindService中的参数ServiceConnection对象的onServiceConnected方法,传递给访问者,访问者通过该对象便可以与Service组件进行通信 } @Override public void onRebind(Intent intent) { super.onRebind(intent); Log.i("bqt", "onRebind"); } @Override public int onStartCommand(Intent intent, int flags, int startId) {//客户端每次调用startService方法时都会回调此方法;调用bindService时不会回调此方法 Log.i("bqt", "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) {//绑定多客户端情况下,需要解除所有的绑定后才会(就会)调用onDestoryed方法,除非service也被startService()方法开启 Log.i("bqt", "onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i("bqt", "onDestroy"); super.onDestroy(); } //****************************************************************************************** /**这是服务里面的一个方法,对外是隐藏的,只能通过IBinder间接访问*/ private void methodInService() { Log.i("bqt", "服务里的方法被调用了……"); // Toast.makeText(this, "服务里的方法被调用了……", Toast.LENGTH_SHORT).show(); //弹土司会报异常 RuntimeException: Can‘t create handler inside thread that has not called Looper.prepare() } private class MyBinder extends IBinderInterface.Stub {//由【extends Binder implements IBinderInterface】改为【extends IBinderInterface.Stub】 @Override public void callMethodInService() throws RemoteException { methodInService();//间接调用了服务中的方法 } } }
清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bqt.aidlservice" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 声明权限 --> <permission android:name="com.bqt.permission" android:protectionLevel="normal" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 指定激活此Service需要的权限 --> <service android:name=".MyRemoteService" android:permission="com.bqt.permission" > <intent-filter> <action android:name="com.bqt.service.REMOTE_SERVICE" /> </intent-filter> </service> </application> </manifest>
调用者Activity
public class MainActivity extends ListActivity { public static final String ACTION_REMOTE_SERVICE = "com.bqt.service.REMOTE_SERVICE"; private MyServiceConnection conn; private IBinderInterface mIBinder;//之所以另外定义一个接口IBinderInterface,而不是直接用MyService.MyBinder,是为了使用统一接口访问,达到解耦、隐藏的目的 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); List<String> mData = new ArrayList<String>(Arrays.asList("startService方式开启服务", "stopService方式关闭服务", // "bindService方式开启服务 ", "unbindService方式解除绑定服务",// "startService启动服务后再bindService", "通过IBinder间接调用服务中的方法")); ListAdapter mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mData); setListAdapter(mAdapter); conn = new MyServiceConnection(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent intent = new Intent(ACTION_REMOTE_SERVICE); switch (position) { case 0://startService方式开启服务。onCreate()--> onStartCommand() --->onDestory() 。onBind()方法并没有 startService(intent);//当调用者结束了自己的生命周期,但是只要没调用stopService,那么Service还是会继续运行 break; case 1://stopService方式关闭服务。service不建议采用隐式方式启动,在高版本可能警告"不安全",更高版本可能直接异常退出 stopService(intent);//服务只会被停止一次,但多次调用并不会异常 break; case 2://绑定的方式开启服务 onCreate() --->onBind();--->onUnbind()-->onDestory() 绑定服务不会调用onStartCommand方法 bindService(intent, conn, BIND_AUTO_CREATE);//flags:绑定时如果Service还未创建是否自动创建;0:不自动创建;1:自动创建 break; case 3: unbindService(conn);//多次调用会异常! mIBinder = null;//若不把mIBinder置为空,则服务销毁后仍然可以调用服务里的方法,因为内部类的引用还在 break; case 4: startService(intent); //使用bindService来绑定一个【已启动】的Service时,系统只是将Service的内部IBinder对象传递给Activity,并不会将Service的生命周期与Activity绑定 bindService(intent, conn, BIND_AUTO_CREATE);//所以,此时调用unBindService方法取消绑定后,Service不会调用onDestroy方法 break; case 5: if (mIBinder != null) { try { mIBinder.callMethodInService(); } catch (RemoteException e) { e.printStackTrace(); } } else { Toast.makeText(this, "还没有绑定呦……", Toast.LENGTH_SHORT).show(); } break; } } private class MyServiceConnection implements ServiceConnection {//Interface for monitoring监控 the state of an application service @Override /**此方法中的IBinder即为我们调用bindService方法时Service的onBind方法返回的对象,我们可以在此方法回调后通过这个IBinder与Service进行通信 */ public void onServiceConnected(ComponentName name, IBinder service) {//访问者与Service连接成功时回调 //Called when a connection连接 to the Service has been established确定、已建立, with the IBinder of the communication channel to the Service. mIBinder = IBinderInterface.Stub.asInterface(service);//回调方法中获得中间人时要调用IMiddlePerson.Stub.asInterface(service)方法。 Toast.makeText(MainActivity.this, "服务已连接……", Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName name) {//异常终止或者其他原因终止导致Service与访问者断开连接时回调 Toast.makeText(MainActivity.this, "服务已断开连接……", Toast.LENGTH_SHORT).show(); } } }
调用者需拷贝远程服务的aidl文件
package com.bqt.aidlservice; interface IBinderInterface { //直接把服务中的此文件连同包名一起复制到调用者的src根目录中 void callMethodInService(); }
调用者清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bqt.bindremote" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <!-- 声明使用指定的权限。一定要先【安装???】远程服务App再安装调用者App --> <uses-permission android:name="com.bqt.permission" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.bqt.bindremote.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
附件列表
时间: 2024-12-28 15:56:39