android Service通信

来源:互联网 发布:mac 远程控制 windows 编辑:程序博客网 时间:2024/06/06 00:09

android Service通信

先在service上创建一个aidl后缀的文件,aidl是service和activity跨进程通信的接口。在eclipse下回自动把aidl文件在gen先生成同名的java文件的(有时需要clean下项目才会生成)

IPC.aidl:

package com.example.ipcservice;interface IPC{    void testipc();}

!aidl文件生成
生成的IPC.java:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: D:\\JAVA\\IPCservice\\src\\com\\example\\ipcservice\\IPC.aidl */package com.example.ipcservice;public interface IPC extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.example.ipcservice.IPC{private static final java.lang.String DESCRIPTOR = "com.example.ipcservice.IPC";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.example.ipcservice.IPC interface, * generating a proxy if needed. */public static com.example.ipcservice.IPC asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.ipcservice.IPC))) {return ((com.example.ipcservice.IPC)iin);}return new com.example.ipcservice.IPC.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_testipc:{data.enforceInterface(DESCRIPTOR);this.testipc();reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.example.ipcservice.IPC{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;}@Override public void testipc() 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_testipc, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_testipc = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public void testipc() throws android.os.RemoteException;}

生成的IPC.java有一个Stub子类,即IPC.Stub,Service中只需新建一个这样的子类对象并且实现override函数(即aidl文件中的接口函数),然后把子类对象通过onBind函数传给activity。
IPCService.java

package com.example.ipcservice;import com.example.ipcservice.IPC.Stub;import android.app.Activity;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.Menu;import android.view.MenuItem;public class IPCService extends Service {    private static final String TAG = "IPCService";    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        return mipc;    }    private final IPC.Stub mipc = new Stub() {        @Override        public void testipc() throws RemoteException {            // TODO Auto-generated method stub            Log.w(TAG,"hello client ,this is server");        }    };}

然后把服务端的com.example.ipcservice包以及其下的IPC.aidl一起拷到客户端下面来。
客户端添加了服务端的包

客户端activity代码:

package com.example.ipcclient;import com.example.ipcservice.IPC;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.Menu;import android.view.MenuItem;import android.widget.TextView;public class IPCClient extends Activity {    private IPC mIPC ;    private static final String TAG = "IPCClient";    private TextView text ;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.w(TAG,"onCreate");        setContentView(R.layout.activity_main);        text = (TextView)findViewById(R.id.text);        Intent intent = new Intent("com.example.IPCService.intent");        bindService(intent, conn, BIND_AUTO_CREATE);    }    ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            // TODO Auto-generated method stub            mIPC = null;        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // TODO Auto-generated method stub            mIPC = IPC.Stub.asInterface(service);            try {                mIPC.testipc();            } catch (RemoteException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    };}

这样就实现了IPCClient跨进程调用IPCService的void testipc()

调用Service的另一种方式

上面的调用是属于匿名binder实现IPC,即实现的server没有加入ServiceManager中,client也不是通过ServiceManager获取到service的binger引用来调用的。是一般没有system权限的应用的调用方式。如果我们有system权限和签名并且有系统jar包,或者有android源码编译环境的话,可以用另外一种方式调用Service,那就是把Service加入到ServiceManager中,调用的时候从ServiceManager中获取Service的Binder对象进行通信。Server向SMgr注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。其实android framework层中的service和其对应的manager都是这种调用方式,如AudioManager就是通过这种方式调用的AudioService。
这种方式与bindService的区别:
1. 不一定需要创建Service,只需实现相应的Stub类并且创建Stub类对象;
2. 调用ServiceManager.add(String name,IBinder) (一般在Activity或Service的onCreate中调用)将上面创建的Stub类对象加入到ServiceManager中,注意,参数name是你定义的Service的名字,后面要通过这个名字从ServiceManager中获取Service的引用;
3. 上面的方式一样,把服务端的包以及其下的aidl文件一起拷到客户端下面来,客户端不需要在bindService了,而是直接调用ServiceManager.getService(String name)获取服务端的引用,再*.Stub.asInterface(mService)就可以调用服务端了
下面我用一个activity启动一个Service,Service中将服务端加入到ServiceManager中,客户端直接用一个activity操作

服务端代码:

mainactivity.java
package com.example.ipcservice;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.util.Log;public class mainactivity extends Activity{    private static final String TAG = "mainactivity";    private IPCService mService;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        Log.w(TAG,"onCreate");        super.onCreate(savedInstanceState);        startService(new Intent(this,IPCService.class));    }}
IPCService.java
package com.example.ipcservice;import com.example.ipcservice.IPC.Stub;import android.app.Activity;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.os.ServiceManager;import android.util.Log;import android.view.Menu;import android.view.MenuItem;public class IPCService extends Service {    private static final String TAG = "IPCService";    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        return null;    }    @Override    public void onCreate() {        // TODO Auto-generated method stub        super.onCreate();        Log.w(TAG,"onCreate");        ServiceManager.addService("penguinmipc", mipc);      }    private final IPC.Stub mipc = new Stub() {        @Override        public String testipc() throws RemoteException {            // TODO Auto-generated method stub            Log.w(TAG,"hello client ,this is server");            return "hello client ,this is server";        }    };}

客户端代码

IPCClient.java
package com.example.ipcclient;import com.example.ipcservice.IPC;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.Parcel;import android.os.RemoteException;import android.os.ServiceManager;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.widget.TextView;public class IPCClient extends Activity {    private static final String TAG = "IPCClient";    IBinder mService = null;    private IPC mIPC;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.w(TAG,"onCreate");        setContentView(R.layout.activity_main);        getService();    }    public void getService() {        mService = ServiceManager.getService("penguinmipc");        if(null == mService) {            Log.e(TAG, "Can't connect to skparam service: ");        }        mIPC = IPC.Stub.asInterface(mService);        try {            String result = mIPC.testipc();            Log.w(TAG,"result:"+result);        } catch (RemoteException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

上面实现的服务端还可以与C++代码的客户端通信

clientIPC.cpp

#include <binder/Parcel.h>#include <binder/IServiceManager.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <utils/String8.h>using namespace android;static sp<IBinder> mService = NULL;static String16 mIfname = String16("");static bool mInited = false;static String16 get_interface_name(sp<IBinder> service){    if (service != NULL) {        Parcel data, reply;        status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);        if (err == NO_ERROR) {            return reply.readString16();        }    }    return String16();}static int service_init(){    sp<IServiceManager> sm = defaultServiceManager();        fflush(stdout);    if(sm == NULL)    {        fprintf(stderr, "service: Unable to get default service manager!\n");        return -1;    }    mService = sm->checkService(String16("penguinmipc"));    mIfname = get_interface_name(mService);    if(mService == NULL || mIfname.size() <= 0)    {        fprintf(stderr, "can not find  service!\n");        return -1;    }    mInited = true;    return 0;}static int Cpp_testipc(char* value, int size){    if(!mInited){        printf("service init failed\n");        return -1;    }    Parcel data, reply;    data.writeInterfaceToken(mIfname);    //data.writeString16(String16(name));    mService->transact(1, data, &reply);    reply.setDataPosition(4);    String16 s16 = reply.readString16();    String8 s8 = String8(s16);    int len = (s8.length() > size)?size:s8.length();    strncpy(value, s8.string(), len);    value[len] = '\0';    return 0;}int main(int argc,  char *argv[]){    if(service_init() != 0){        printf("failed 1\n");        return -1;    }    char result[1024] = {0};    if(Cpp_testipc(result,sizeof(result)) == 0){        printf("result:%s\n",result);        return 0;    }    return -1;}

Android.mk

###########################################include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_SRC_FILES := clientIPC.cppLOCAL_SHARED_LIBRARIES := libutils libbinderLOCAL_MODULE := clientIPCinclude $(BUILD_EXECUTABLE)

本地Service调用

Service本地调用分为两种,一种简单的startService,没有数据交互,还有一种是bindService,我们只看bindService
下面是mainactivity调用本地IPCService

!aidl文件生成
IPCService.java:

package com.example.ipcservice;import com.example.ipcservice.IPC.Stub;import android.app.Activity;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.Menu;import android.view.MenuItem;public class IPCService extends Service {    private static final String TAG = "IPCService";    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        //return mipc;        return new MyBind();    }    public String hello(){        return "hello";    }    public class MyBind extends Binder {        public IPCService  getService(){            return IPCService.this;        }    }}mainactivity.java:```javapackage com.example.ipcservice;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.util.Log;public class mainactivity extends Activity{    private static final String TAG = "mainactivity";    private IPCService mService;    @Override    protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub        super.onCreate(savedInstanceState);        //startService(new Intent(this,IPCService.class));        bindService(new Intent(this,IPCService.class), conn, BIND_AUTO_CREATE);    }    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            // TODO Auto-generated method stub        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // TODO Auto-generated method stub              IPCService.MyBind mm = (IPCService.MyBind)service;              mService = mm.getService();              Log.w(TAG,"mService.hello():"+mService.hello());        }    };}

这样就实现了mainactivity调用IPCService的String hello()

参考:

android framework中如何添加Service
在ServiceManager中加入自定义的服务

0 0
原创粉丝点击