Pro Android学习笔记(八十):服务(5):访问远程服务

来源:互联网 发布:2g手机怎么用4g网络 编辑:程序博客网 时间:2024/05/21 22:47

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处:http://blog.csdn.net/flowingflying/

和Local service不同,remote service可以被其他进程,即其他应用所调用。

Client的AIDL文件在onBind()中将stub对象返回给client,client对stub对象的操作,就如同操作service的对外接口。继上学习了AIDL文件和远程服务的实现,我们将学习client如何访问远程服务。

Client的AIDL文件

Client要访问远程服务,必须清楚服务接口,因此同样需要用AIDL文件来将该接口描述清楚,可以直接从remote service中copy过来,AIDL文件是client和server之间的契约,对双方之间的接口进行说明。

我们将remote service中的IStockQuoteService.aidl文件copy到client的src下面。由于aidl中的包名和client的包名不一样,我们将看到下面的视图:

Client的代码

客户端的activity很简单,主要又两个button组成,第一个是ToggleButton,有两个状态,点击分别连接remote service和断开连接,即bind和unbind。第二个button是请求远程服务,得到的结果用toast显示,只有成功连接远程服务后才能请求服务,故button根据连接状态确实是否enable。

public class MainActivity extends Activity {
    private ToggleButton bindButton = null;
    private Button callButton = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindButton = (ToggleButton)findViewById(R.id.bindButton);
        callButton = (Button)findViewById(R.id.callButton);

    } 

    @Override 
    protected void onDestroy() { 
        Log.v("client","Activity onDestroy() is called");
        if(bindButton.isChecked()){ 
            unbindService(servCon); //【3】在activity退出时断开连接
        }
        super.onDestroy();

    }

    // 按Button的处理
    public void doClick(View v){
        switch(v.getId()){
        case R.id.bindButton:
            Log.v("client","bindButton check ? " + bindButton.isChecked());
            if(bindButton.isChecked()){ //want bind
               /* 【1】连接远程服务:通过bindService()进行,有三个参数:
                 * 1、service的名字,我们在remote service的AndroidManifest.xml中在<intent-fliter>定义
                 * 2、ServiceConnetion,连接 
                 * 3、flag,表明如服务部存在则自动创建。
                 * */ 
                bindService(new Intent(IStockQuoteService.class.getName()),
                        servCon,
                        Context.BIND_AUTO_CREATE);
           
            }else{//want unbind 
                callButton.setEnabled(false);
                unbindService(servCon);    //【3】断开服务连接
            }
            break;
       
        case R.id.callButton:
            callService();
            break;
           
        default:
            return;
        }
    }
    //【1】连接远程服务
    private IStockQuoteService remoteService = null;
   // 【1.1】存储远程服务返回的stub中的代理实例
    private ServiceConnection servCon = new ServiceConnection() {         
        @Override //【1.2】当远程服务出现异常,如crash,导致连接中断时触发,注意,unBindService()并不会触发此。
        public void onServiceDisconnected(ComponentName name) { 
            Log.v("client","onServiceDisconnected() is called");
            bindButton.setChecked(false);
            callButton.setEnabled(false);
            remoteService = null;

        }
       
        @Override //【1.3】当远程服务连接成功时,即bindService()成功时触发,在此需要获得Stub对象,实际是获得Stub中的代理实例,操作这个代理对象,就如同直接操作远程服务,使用起来很是方便
        public void onServiceConnected(ComponentName name, IBinder service)
            Log.v("client","onServiceConnected() is called");
           //从接口中获取代理对象,操作这个对象,就如同操作接口一般,下面是自动生成的接口文件中相关的代码, 
            /* 在 IStockQuoteService.Stub:在接口中获取一个IBinder对象作为proxy(代理),有则返回,无则生成之。
             * Cast an IBinder object into an cn.wei.flowingflying.proandroidservice.IStockQuoteService interface,
             * generating a proxy if needed.
             *  public static cn.wei.flowingflying.proandroidservice.IStockQuoteServiceasInterface(android.os.IBinder obj)
                {
                    if ((obj==null)) {
                        return null;
                    }
                    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                    if (((iin!=null)&&(iin instanceof cn.wei.flowingflying.proandroidservice.IStockQuoteService))) {
                        return ((cn.wei.flowingflying.proandroidservice.IStockQuoteService)iin);
                    }
                    return new cn.wei.flowingflying.proandroidservice.IStockQuoteService.Stub.Proxy(obj);
                }
             * */
            remoteService = IStockQuoteService.Stub.asInterface(service);
            bindButton.setChecked(true);
            callButton.setEnabled(true);

        }
    };

    private void callService(){
        try{
            double value = remoteService.getQuote("WEI"); //【2】请求服务:操作接口代理实例,如果本地操作远程服务接口
            Log.v("client","callService(): get stockQuote from reference :" + value);
            Toast.makeText(this, "Stock quote is " + value, Toast.LENGTH_LONG).show();
        }catch(RemoteException e){
            Log.e("client",e.toString());
        }
    }
}

client访问远程服务分为三步:【1】建立连接、【2】请求服务、【3】断开连接。

建立连接

远程服务可以被本应用和其他应用调用,client通过bindService()和远程服务建立连接,并从中获取接口代理对象。对应的在远程服务中,如果服务不存在,则服务启动,执行onCreate(),然后执行onBind();如果服务存在则直接执行onBind()。

bindService()是异步,即asynchronouse call,也就是它不会等到服务执行完onCreate()、onBind()然后返回,因此我们需要serviceConnection中的onServiceConnected()回调函数来表明已经成功连接。serviceConnection中的onServiceDisconnected()是在service崩溃的时候触发,如果原来存在连接,Android系统会自动重启服务。我们可以通过DDMS中强制终止remote Service的进程来实现,可以看到触发了onServiceDisConnected(),remote Service会被重新启动,接着连接的onServiceConnected()会被触发。

请求服务

直接操作接口代理实例,操作远程服务就如同在本地操作一样便捷。

断开连接

通过unBindService()断开远程服务的连接,相应地执行远程服务的onDestroy()。也许你会担心,如果我在程序中进行unBindService(),或不会影响其他应用对远程服务的调用。这不需要担心。在上一次学习中,我们在remote service中定义一个静态变量(static int count)进行跟踪。当我们unbind,从新再bind时,我们发现count继续计数,而不是重头开始,说明service实际一直在后台存在,这点也可以通过DDMS查看进程来确定。这就很有趣了,Stub是针对每个接口,而remote service中的onCreate(),onDestroy(),onBind()也是针对连接,或者说针对为每个接口分配的Stub。因此不同应用去连接远程服务,并请求服务或者访问服务时,他们之间不会发生混淆,服务可以分隔每一个连接。当然如果我们不使用静态变量,而采用普通的变量,unbind后再bind,是会从新计数。

本笔记涉及的例子代码,可以在Pro Android学习:Android service小例子中下载。

相关链接: 我的Android开发相关文章

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 下身体痒痒得不得了怎么办 头皮干痒头屑多怎么办 头发掉的露头皮怎么办 头上老是有结痂怎么办 婴儿头上的黄痂怎么办 头皮屑多又痒怎么办小偏方 皮肤瘙痒起红疙瘩怎么办 头又油又痒怎么办 头上反复长脓包怎么办 额头上长了粉刺怎么办 身上长红疙瘩很痒怎么办 脸上的痘痘变硬怎么办 痘痘变成硬疙瘩怎么办 痘痘变硬了怎么办知乎 痘痘里面是硬的怎么办 皮肤出油毛孔大怎么办 蹭无线网信号差怎么办 无线网离得太远怎么办 无线网不好使了怎么办 火疖子化脓破了怎么办 脸上长了个疖子怎么办 脸上起了火疖子怎么办 脸上长了火疙瘩怎么办 脸上长疖子了该怎么办? 头上神经线疼怎么办 打了肉毒发烧了怎么办 不小心吃了活蛆怎么办 吃了生蛆的东西怎么办 我的世界中毒了怎么办 如果人染了尸气怎么办 汽车没油了怎么办紧急 不小心吃氧化钾怎么办 看3d电影没眼镜怎么办 wps宏被禁用了怎么办 京东三天不发货怎么办 京东商家不退款怎么办 苹果保修卡丢了怎么办 手机保修卡丢了怎么办 键盘上没有win键怎么办 用别人id被锁了怎么办 苹果手机被偷了怎么办