天天看点

Android学习之远程绑定调用service

http://blog.csdn.net/q1234456gggg_jkjg/article/details/8479070

远程绑定调用service主要是用来不同进程的信息共享。就比如服务器和客户端,在服务器端设置好一个service提供方法或信息,然后客户端可以直接调用服务器端service提供方法或信息。这里有个前提是客户端必须有和服务器端一份一样的aidl,然后服务器端在客户端使用的系统上有注册过(也就是安装运行过一次),之后客户端就可以远程绑定调用服务器端的service了。

具体的步骤如下:

1.首先,是服务器的

  1)创建一个android应用工程  

Android学习之远程绑定调用service
Android学习之远程绑定调用service
Android学习之远程绑定调用service

  2)  在主aitivity所在的包里新建个aidl文件,这是adt会自动帮你在gen目录下生成一个和aidl文件同名的java文件(这里的aidlservice.java是下一步骤生成的,这里可以先忽略)

Android学习之远程绑定调用service
Android学习之远程绑定调用service

  3)如上图所示,创建一个用来使用service的类(aidlservice.java)

  具体每个文件的代码如下:

  aidlserveractivity.java

[java] view

plaincopy

package com.ds.server;  

import android.app.activity;  

import android.content.intent;  

import android.os.bundle;  

import android.view.view;  

import android.view.view.onclicklistener;  

import android.widget.button;  

import android.widget.toast;  

public class aidlserveractivity extends activity {  

    /** called when the activity is first created. */  

    @override  

    public void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        setcontentview(r.layout.main);  

        button bt = (button) findviewbyid(r.id.bt);  

        bt.setonclicklistener(new onclicklistener() {  

            @override  

            public void onclick(view v) {  

                // todo auto-generated method stub  

                intent service = new intent(aidlserveractivity.this,  

                        aidlservice.class);  

                startservice(service);  

                toast.maketext(aidlserveractivity.this, "service started",  

                        toast.length_long).show();  

            }     

        });    

    }  

}  

iaidlservice.aidl

interface iaidlservice {    

    int gettype();   

}    

 aidlservice.java

import android.app.service;  

import android.os.ibinder;  

import android.os.remoteexception;  

import android.util.log;  

public class aidlservice extends service {  

    private boolean unrunnable;  

    private int count;  

    private class mybinder extends iaidlservice.stub {  

        @override  

        public int gettype() throws remoteexception {  

            // todo auto-generated method stub  

            return 100;  

        }  

    private void log(string str) {   

        log.d("aidlservice", "------ " + str + "------");  

    public void oncreate() {  

        super.oncreate();  

        /* 

        new thread(new runnable(){ 

            @override 

            public void run(){ 

                while(!unrunnable){ 

                    try{ 

                        thread.sleep(1000); 

                    }catch(interruptedexception e){ 

                    } 

                    count++; 

                    log.v("aidlservice","count:"+count); 

                }        

            } 

        }).start(); 

        */  

        log.v("remotecountservice","oncreate");  

        log("service create");  

/* 

    @override 

    public void onstart(intent intent, int startid) { 

        log("service start id=" + startid); 

    } 

*/  

    public ibinder onbind(intent t) {  

        log("service on bind");  

        return new mybinder();  

    public void ondestroy() {  

        log("service on destroy");  

        unrunnable=true;  

        super.ondestroy();  

    /* 

    public boolean onunbind(intent intent) { 

        log("service on unbind"); 

        return super.onunbind(intent); 

    public void onrebind(intent intent) { 

        log("service on rebind"); 

        super.onrebind(intent); 

    */  

布局文件androidmanifest.xml

[html] view

<?xml version="1.0" encoding="utf-8"?>  

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  

    package="com.ds.server"  

    android:versioncode="1"  

    android:versionname="1.0" >  

    <uses-sdk android:minsdkversion="8" />  

    <application  

        android:icon="@drawable/ic_launcher"  

        android:label="@string/app_name" >  

        <activity  

            android:name=".aidlserveractivity"  

            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  

            android:name=".aidlservice"  

            android:enabled="true"  

            android:process=":remote" >  

                <!-- aidl完整路径名。必须指明,客户端能够通过aidl类名查找到它的实现类 -->  

                <action android:name="com.ds.server.iaidlservice" />  

                <category android:name="android.intent.category.default" />  

        </service>  

    </application>  

</manifest>  

这里,服务器端的工作做好了,接下来是客户端的工作。

2.接着,是客户端的:

 1)首先,创建一个工程

Android学习之远程绑定调用service
Android学习之远程绑定调用service

 2)接着,把服务器端的一些文件拷贝过来(创建com.ds.server这个包,然后往里面复制进入如下图的服务器端的文件(iaidlservice.java)

Android学习之远程绑定调用service
Android学习之远程绑定调用service

下面是个文件的内容

    aidlclientactivity.java

package com.ds.client;  

import com.ds.server.iaidlservice;  

import android.content.componentname;  

import android.content.serviceconnection;  

import android.widget.textview;  

public class aidlclientactivity extends activity {  

    iaidlservice iservice;   

    int count;  

    private serviceconnection connection = new serviceconnection() {  

        public void onserviceconnected(componentname name, ibinder service) {  

            // 浠庤繙绋媠ervice涓幏寰桝idl瀹炰緥鍖栧璞�            

            iservice = iaidlservice.stub.asinterface(service);  

            log.i("client","bind success:" + iservice);  

        }    

        public void onservicedisconnected(componentname name) {  

            iservice = null;  

            log.i("client","onservicedisconnected");  

    };    

    public void oncreate(bundle savedinstancestate) {    

        final textview tv = (textview) findviewbyid(r.id.tv);  

            public void onclick(view arg0) {  

                intent service = new intent(iaidlservice.class.getname());  

                bindservice(service, connection, bind_auto_create);  

                if (iservice != null) {    

                    try {  

                        log.v("aidlclientactivity","oncreate"+iservice.gettype()+" "+count);  

                    } catch (remoteexception e) {  

                        e.printstacktrace();  

                    }  

                }  

                else{  

                    count++;  

            }  

        });  

 androidmanifest.xml

    package="com.ds.client"  

            android:name=".aidlclientactivity"  

这样客户端的工作也算完了,但这里我还想说下一个问题。

你可能会看到在客户端的activity文件里,有个count的变量,觉得是多余的,但这是为了说明下面这个问题的需要。

最开始的count是0,然后我运行客户端后,鼠标左击bind按钮,会发现logcat的verbose窗口会显示

Android学习之远程绑定调用service
Android学习之远程绑定调用service

为什么没有执行 log.v("aidlclientactivity","oncreate"+iservice.gettype()+" "+count);这一句,然后我再点击下bind

Android学习之远程绑定调用service
Android学习之远程绑定调用service

终于出现想要的结果,这里你就会发现count变成1了,也就是之前执行过一次count+1了,这就说明了,第一次只是绑定,返回的 iservice是null,第二次以上才会返回对象。

到这里就是我之前一直错误的地方,是理解错了,我之前写的程序没有按钮,是直接启动客户端后就绑定调用service,由于没有按钮不能多次按,也就会造成得不到想要的结果了。这里总算明白它的一些运行机制了,先写到这里,后面有什么新发现会及时更新。

继续阅读