服务 远程服务 AIDL 进程间通讯 IPC


Activity
服务 远程服务 AIDL 进程间通讯 IPC


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文件
服务 远程服务 AIDL 进程间通讯 IPC
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>

附件列表

上一篇:自己动手写插件底层篇—基于jquery移动插件实现


下一篇:SVN的Windows和Linux客户端操作详解