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();}
!
生成的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
!
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中加入自定义的服务
- Android service通信
- Android 远程Service通信
- Android Service 通信
- Android Service通信详解
- Android Service通信
- Android Service通信
- android Service通信
- Android Service 通信
- android service 与activity通信--绑定service
- Android中的Service的通信
- android Service 跨进程通信
- android activity与service通信
- Android Activity与Service通信
- android Service 跨进程通信
- Android service与Activity通信
- android activity 与service通信
- Android service 与 activity通信
- Android Service与Activity通信
- unicode编码
- golang加载css和js
- Python学习总结笔记(8)-- Socket通信初探
- 如何将其他函数设置为程序入口点
- 计算机网络之网络层-概述
- android Service通信
- 拉普拉斯平滑
- APP在加载外部html时选择加载本地的js、css、img等资源文件(上:安卓篇)
- VLC for Android多窗口播放及画中画
- Java 16
- Java培训总结笔记(一)
- 关于方向
- 猴子吃桃-经典问题
- 操作系统概念性题目总结