您的位置:首页 > 移动开发 > Android开发

android 的 service远程运用

2016-09-28 19:39 281 查看
Service 是 android的一个重要组建,用到的地方也比较多。

Service 上一章讲的是本地服务,现在讲讲远程服务,即跨进程服务。

如果是本地服务,按照下面的写法

    public class MyService extends Service {  

 

        @Override  

        public void onCreate() {  

            super.onCreate();  

            try {  

                Thread.sleep(60000);  

            } catch (InterruptedException e) {  

                e.printStackTrace();  

            }  

        }  

 

    }  

在activity中点击Start Service按钮,开启该服务,会发现,几秒钟后程序报出了ANR异常提示框。这是因为本地service也是在UI线程中,如果要做耗时操作,可以在里面开启一个子线程,在子线程中做耗时操作,操作完成后,可以和广播配合,把数据发回activity中。

把一个本地服务变成远程服务,很简单,在配置清单里面,服务配置的节点里,添加  <service android:process=":remote" > 即可。

我们重新点击Start Service按钮,发现没有ANR异常,因为该service和UI线程已经不在同一个进程中了,不会阻塞UI线程。有些app采用多进程方法,提高app的运行流畅度,但多进程用起来有一定难度,少不留神就出错了,主要原因为数据传递和共享问题。

多进程中,所谓的自定义单例模式 application 单例等等统统失效了,不能共享数据,因为没在一个进程中,所以数据处理是一个难题。

service还有一个问题,就是在绑定服务时,程序会报错,因为此时service已经是远程服务了,activity和service运行在两个不同的进程里面,传统的关联方式不适用了,所以报错。此时,一个技术就闪亮登场了,那就是AIDL。

我们可以手写一个aidl,用记事本写,像写接口一样,把.txt 后缀名 改为 .aidl即可。

 interface AIDLService {  

    int add(int a, int b);  

}

保存后,编译器会自动编译。

在上述service里面,绑定自己的bind。

    public class MyService extends Service {  

        @Override  

        public IBinder onBind(Intent intent) {  

            return mBinder;  

        }      

        AIDLService.Stub mBinder = new Stub() {  

            @Override  

            public int add(int a, int b) throws RemoteException {  

                return a + b;  

            }  

        };    

    }  

Stub是Binder的子类,所以在onBind()方法中可以直接返回Stub的实现,进行绑定。

activity中,绑定的写法和参数不变,启动的方法也一样,只需要改写一点即可,即ServiceConnection

private AIDLService myAIDLService;  

    private ServiceConnection connection = new ServiceConnection() {  

        @Override  

        public void onServiceDisconnected(ComponentName name) {  

        }  

 

        @Override  

        public void onServiceConnected(ComponentName name, IBinder service) {  

            myAIDLService = AIDLService.Stub.asInterface(service);  

            try {  

                int result = myAIDLService.add(3, 5);     

                Log.d("TAG", "result " + result);  

            } catch (RemoteException e) {  

                e.printStackTrace();  

            }  

        }  

    };  

如此,即可,其实跨进程看着也没什么难的。

以上是在自己的程序里调用,如果想让别的程序调用怎么办呢?就好把调用支付宝支付,其实就是支付宝的远程服务,封装好了,提供 .aidl文件,让我们调用。其实原理也间单

封装的service远程服务不用改写,在配置清单里,给服务的注册添加一个actiion数据,要保证这个action是独一无二的,

<service  

        android:name="com.example.cn.MyService"  

        android:process=":remote" >  

        <intent-filter>  

            <action android:name="com.example.cn.AIDLService"/>  

        </intent-filter>  

    </service>

然后再把我们编写的.aidl文件,大公无私的贡献出来就可以了,剩下的就是调用者的工作了。

在另一个程序B里,我们想调用上述的远程服务,要做几件事,首先要把.aidl文件拷到自己的项目里,注意,文件夹的名字也要与上述程序.aidl文件所在文件的名字相同。

ServiceConnection里面的写法不用修改,要改变的是启动service的方法,上述是直接启动,现在远程调用,需要用到隐式启动了,

Intent intent = new Intent("com.example.cn.AIDLService");  

bindService(intent, connection, BIND_AUTO_CREATE);

如此,完工了。跨进程通讯完成了。还有另一种跨进程的方式,是使用Messenger,好奇的可以自己搜搜。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android service 跨进程