android Service通信

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 := optional
LOCAL_SRC_FILES := clientIPC.cpp
LOCAL_SHARED_LIBRARIES := libutils libbinder
LOCAL_MODULE := clientIPC
include $(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:
```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
        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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值