bindService:绑定本地服务和远程服务示例

绑定本地服务

AndroidManifest.xml中声明服务:

            <service android:name=".TestLocalService">
                <intent-filter>
                    <action android:name="maureen.intent.action.BIND_LOCAL_SERVICE"/>
                </intent-filter>
            </service>

TestLocalService.java

    public class TestLocalService extends Service {
        private final String TAG = TestLocalService.class.getSimpleName();
        private IBinder mServiceBinder = new TestLocalServiceBinder();
     
        public class TestLocalServiceBinder extends Binder {
                public TestLocalService getService() {
                    return TestLocalService.this;
                }
        }
     
        public void testFunc() {
            Log.d(TAG,"testFunc");
            Log.d(TAG, Log.getStackTraceString(new Throwable()));
        }
     
        @Override
        public void onCreate() {
            super.onCreate();
        }
     
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG, "onBind:mServiceBinder=" + mServiceBinder);
            return mServiceBinder;
        }
     
        @Override
        public boolean onUnbind(Intent intent) {
            return super.onUnbind(intent);
        }
     
        @Override
        public void onDestroy() {
            super.onDestroy();
        }
    }

TestBindServiceActivity.java

    点击按钮绑定service
    绑定成功后调用TestLocalService里的testFunc方法
    点击back键解绑服务

    public class TestBindServiceActivity extends Activity {
        private static final String TAG = TestBindServiceActivity.class.getSimpleName();
        private static final String ACTION_BIND_LOCAL_SERVICE = "maureen.intent.action.BIND_LOCAL_SERVICE";
        private Button mBindLocalServiceBtn;
        private static ServiceConnection mLocalConnection;
        private static TestLocalService mLocalService = null;
     
        private static class TestLocalConenction implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Log.d(TAG,"onServiceConnected:iBinder=" + iBinder);
                mLocalService = ((TestLocalService.TestLocalServiceBinder)iBinder).getService();
                mLocalService.testFunc();
            }
     
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                mLocalService = null;
            }
        }
     
        private static class ButtonClickListener implements View.OnClickListener {
            private WeakReference<TestBindServiceActivity> mActivity;
            public ButtonClickListener(TestBindServiceActivity activity) {
                mActivity = new WeakReference<>(activity);
            }
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.bind_local_service:
                        Intent localIntent = new Intent();
                        //Without this, throw exception.
                        localIntent.setPackage("com.example.maureen.mytestbindservice");
                        localIntent.setAction(ACTION_BIND_LOCAL_SERVICE);
                        mActivity.get().bindService(localIntent, mLocalConnection, BIND_AUTO_CREATE);
                        break;
                    default:
                        break;
                }
            }
        }
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate");
            setContentView(R.layout.activity_test_bind_service);
            mLocalConnection = new TestLocalConenction();
            mBindLocalServiceBtn = findViewById(R.id.bind_local_service);
            mBindLocalServiceBtn.setOnClickListener(new ButtonClickListener(this));
        }
     
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy");
            unbindService(mLocalConnection);
        }
    }

值得注意的是,在TestLocalService中onBind函数返回的mBinder和TestBindServiceActivity中onServiceConnected中的参数iBinder是相同的:

onBind:mServiceBinder=com.example.maureen.mytestbindservice.TestLocalService$TestLocalServiceBinder@3ef6efd

onServiceConnected:iBinder=com.example.maureen.mytestbindservice.TestLocalService$TestLocalServiceBinder@3ef6efd

从Activity中调用testFunc并未通过Binder调用:

    2010-01-02 04:29:32.944 5947-5947/com.example.maureen.mytestbindservice D/TestLocalService: testFunc
    2010-01-02 04:29:32.950 5947-5947/com.example.maureen.mytestbindservice D/TestLocalService: java.lang.Throwable
            at com.example.maureen.mytestbindservice.TestLocalService.testFunc(TestLocalService.java:22)
            at com.example.maureen.mytestbindservice.TestBindServiceActivity$TestLocalConenction.onServiceConnected(TestBindServiceActivity.java:27)
            at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1652)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1681)
            at android.os.Handler.handleCallback(Handler.java:790)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6523)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:940)

绑定远程服务

    AndroidManifest.xml中声明service,指定service运行的进程:

            <service android:name=".TestRemoteService"
                     android:process=":remote">
                <intent-filter>
                    <action android:name="maureen.intent.action.BIND_REMOTE_SERVICE"/>
                </intent-filter>
            </service>

    编写AIDL文件- IRemoteServiceAidlInterface.aidl

    interface IRemoteServiceAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void testFunc1();
        void testFunc2();
    }

生成的对应的java文件-IRemoteServiceAidlInterface.java

    public interface IRemoteServiceAidlInterface extends android.os.IInterface {
        /** Local-side IPC implementation stub class. */
        public static abstract class Stub extends android.os.Binder implements com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface {
            private static final java.lang.String DESCRIPTOR = "com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface";
            
            /** Construct the stub at attach it to the interface. */
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
            
            /**
             * Cast an IBinder object into an com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface interface,
             * generating a proxy if needed.
             */
            public static com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface asInterface(android.os.IBinder obj) {
                if ((obj==null)) {
                    return null;
                }
                ndroid.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin!=null)&&(iin instanceof com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface))) {
                    return ((com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface)iin);
                }
                return new com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface.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 {
                java.lang.String descriptor = DESCRIPTOR;
                switch (code) {
                    case INTERFACE_TRANSACTION: {
                        reply.writeString(descriptor);
                        return true;
                    }
                    
                    case TRANSACTION_testFunc1: {
                        data.enforceInterface(descriptor);
                        this.testFunc1();
                        reply.writeNoException();
                        return true;
                    }
                    
                    case TRANSACTION_testFunc2: {
                        data.enforceInterface(descriptor);
                        this.testFunc2();
                        reply.writeNoException();
                        return true;
                    }
                    
                    default: {
                        return super.onTransact(code, data, reply, flags);
                    }
                }
            }
            
            private static class Proxy implements com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface {
                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;
                }
                
                /**
                 * Demonstrates some basic types that you can use as parameters
                 * and return values in AIDL.
                 */
                @Override
                public void testFunc1() 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_testFunc1, _data, _reply, 0);
                        _reply.readException();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                }
                
                @Override
                public void testFunc2() 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_testFunc2, _data, _reply, 0);
                        _reply.readException();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                }
            }
            
            static final int TRANSACTION_testFunc1 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
            static final int TRANSACTION_testFunc2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        }
        
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        public void testFunc1() throws android.os.RemoteException;
        public void testFunc2() throws android.os.RemoteException;
    }

    TestRemoteService.java

    public class TestRemoteService extends Service {
        private final String TAG= TestRemoteService.class.getSimpleName();
        private IBinder mRemoteBinder = new RemoteServiceImpl(this);
     
        private static class RemoteServiceImpl extends IRemoteServiceAidlInterface.Stub {
            private final String TAG= RemoteServiceImpl.class.getSimpleName();
            private WeakReference<TestRemoteService> mRemoteService;
            public RemoteServiceImpl(TestRemoteService service) {
                mRemoteService = new WeakReference<>(service);
            }
            @Override
            public void testFunc1() {
                Log.d(TAG,"testFunc1");
                Log.d(TAG,Log.getStackTraceString(new Throwable()));
                mRemoteService.get().testMyFunc1();
            }
     
            @Override
            public void testFunc2() {
                Log.d(TAG,"testFunc2");
                mRemoteService.get().testMyFunc2();
            }
        }
     
        private void testMyFunc1() {
            Log.d(TAG,"testMyFunc1");
            Log.d(TAG,Log.getStackTraceString(new Throwable()));
        }
     
        private void testMyFunc2() {
            Log.d(TAG,"testMyFunc2");
        }
        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG,"onCreate");
        }
     
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG,"onBind:mRemoteBinder=" + mRemoteBinder);
            return mRemoteBinder;
        }
     
        @Override
        public boolean onUnbind(Intent intent) {
            Log.d(TAG,"onUnbind");
            return super.onUnbind(intent);
        }
     
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestroy");
        }
    }

    TestBindServiceActivity.java

       ① 点击按钮,绑定远程服务

       ②服务绑定成功后,调用aidl中声明的方法testFunc1和testFunc2

      ③点击back键,解绑服务

    package com.example.maureen.mytestbindservice;
     
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
     
    import java.lang.ref.WeakReference;
     
    public class TestBindServiceActivity extends Activity {
        private static final String TAG = TestBindServiceActivity.class.getSimpleName();
     
        private static final String ACTION_BIND_REMOTE_SERVICE = "maureen.intent.action.BIND_REMOTE_SERVICE";
        private Button mBindRemoteServiceBtn;
        private static ServiceConnection mRemoteConnection;
     
     
        private static class TestRemoteConection implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Log.d(TAG,"onServiceConnected:iBinder=" + iBinder);
                IRemoteServiceAidlInterface remoteService = IRemoteServiceAidlInterface.Stub.asInterface(iBinder);
                try {
                    remoteService.testFunc1();
                    remoteService.testFunc2();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
     
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
     
            }
        }
     
        private static class ButtonClickListener implements View.OnClickListener {
            private WeakReference<TestBindServiceActivity> mActivity;
            public ButtonClickListener(TestBindServiceActivity activity) {
                mActivity = new WeakReference<>(activity);
            }
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.bind_remote_service:
                        Intent remoteIntent = new Intent();
                        //Without this, throw exception.
                        remoteIntent.setPackage("com.example.maureen.mytestbindservice");
                        remoteIntent.setAction(ACTION_BIND_REMOTE_SERVICE);
                        mActivity.get().bindService(remoteIntent, mRemoteConnection, BIND_AUTO_CREATE);
                        break;
                    default:
                        break;
                }
            }
        }
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate");
            setContentView(R.layout.activity_test_bind_service);
            mRemoteConnection = new TestRemoteConection();
            mBindRemoteServiceBtn = findViewById(R.id.bind_remote_service);
            mBindRemoteServiceBtn.setOnClickListener(new ButtonClickListener(this));
        }
     
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy");
            unbindService(mRemoteConnection);
        }
    }

值得注意的是TestRemoteService.java的onBind函数中返回的mRemoteBinder是一个Binder服务端对象,即RemoteServiceImpl对象:

nBind:mRemoteBinder=com.example.maureen.mytestbindservice.TestRemoteService$RemoteServiceImpl@3920201

而在TestBindServiceActivity的TestRemoteServiceConnection的onServiceConnected函数中iBinder是Binder代理端:

onServiceConnected:iBinder=android.os.BinderProxy@6ff13d8

即Activity调用到TestRemoteService是通过Binder调用完成的。

例如TestRemoteService.RemoteServiceImpl.testFunc1调用堆栈:

    2010-01-02 05:05:47.136 6482-6495/com.example.maureen.mytestbindservice:remote D/RemoteServiceImpl: testFunc1
    2010-01-02 05:05:47.140 6482-6495/com.example.maureen.mytestbindservice:remote D/RemoteServiceImpl: java.lang.Throwable
            at com.example.maureen.mytestbindservice.TestRemoteService$RemoteServiceImpl.testFunc1(TestRemoteService.java:24)
            at com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface$Stub.onTransact(IRemoteServiceAidlInterface.java:51)
            at android.os.Binder.execTransact(Binder.java:697)

而TestRemoteService.testFunc1调用堆栈:

    2010-01-02 05:05:47.140 6482-6495/com.example.maureen.mytestbindservice:remote D/TestRemoteService: testMyFunc1
    2010-01-02 05:05:47.143 6482-6495/com.example.maureen.mytestbindservice:remote D/TestRemoteService: java.lang.Throwable
            at com.example.maureen.mytestbindservice.TestRemoteService.testMyFunc1(TestRemoteService.java:37)
            at com.example.maureen.mytestbindservice.TestRemoteService.access$000(TestRemoteService.java:11)
            at com.example.maureen.mytestbindservice.TestRemoteService$RemoteServiceImpl.testFunc1(TestRemoteService.java:25)
            at com.example.maureen.mytestbindservice.IRemoteServiceAidlInterface$Stub.onTransact(IRemoteServiceAidlInterface.java:51)
            at android.os.Binder.execTransact(Binder.java:697)

源码位置

https://github.com/snowdrift1993/Android/tree/master/MyTestBindService
---------------------
作者:明朗晨光
来源:CSDN
原文:https://blog.csdn.net/u011386173/article/details/83575069
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-06-22 18:45  天涯海角路  阅读(538)  评论(0)    收藏  举报