Android中的跨应用服务通信

文章中大部分代码来自网络,在此基础上我做了一定量的修改,这篇文章只是为了方便自己以后查看,转载请注明地址。
内容是安卓中跨应用的服务与界面的相互通信。

首先是文件结构,如下图,分别创建两个APP,app(service)和remoteApp(client),App只负责服务部分,remoteApp用于显示服务回传的数据和修改服务的数据的功能。现在需要跨应用通信的app中创建AIDL文件,分别为ITaskBinder.aidl和ITaskCallback.aidl,ITaskCallback,ITaskBinder用于编写提供给client回调用的接口,ITaskCallback用于编写注册callback的方法。

[img]http://dl2.iteye.com/upload/attachment/0111/7103/f2bbe941-a87f-394b-9abb-9bcff08cb686.png[/img]

ITaskCallback.aidl代码

// ITaskBinder.aidl
//注意修改包名
package ***.***.learnservice;
import ***.***.learnservice.ITaskCallback;

interface ITaskBinder {
void registerCallback(ITaskCallback cb); //用于注册callback
void unregisterCallback(ITaskCallback cb);//用于解除callback的注册
void setServicePrint(String str);
}


ITaskBinder.aidl代码

// ITaskCallback.aidl
//注意修改包名
package ***.***.learnservice;

interface ITaskCallback {
void sendString(String str); //向client回传字符串数据
}



下面来讲讲service中需要实现的内容
MyService.java代码

package ***.***.learnservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;


public class MyService extends Service {
private boolean running=false;
private String outStr="服务运行中...";
private boolean reg=false;

public MyService() {
}

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

@Override
public void onCreate() {
super.onCreate();
running=true;
System.out.println("服务启动");
}

@Override
public void onDestroy() {
super.onDestroy();
running=false;
System.out.println("服务销毁");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(){
@Override
public void run() {
super.run();
int i=0;
while (running)
{
String str=i+":"+outStr;
System.out.println(str);
if(reg){
callback(str);//条件符合就回传数据
}
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}


void callback(String str) {
final int N = mCallbacks.beginBroadcast();
System.out.println(N);
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).sendString(str);
}
catch (RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}

private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() {
public void registerCallback(ITaskCallback cb) {
if (cb != null) {
mCallbacks.register(cb);
reg=true;
}
}

public void unregisterCallback(ITaskCallback cb) {
if(cb != null) {
mCallbacks.unregister(cb);
reg=false;
}
}

@Override
public void setServicePrint(String str) throws RemoteException {
MyService.this.outStr=str;
}
};

final RemoteCallbackList<ITaskCallback> mCallbacks = new RemoteCallbackList <ITaskCallback>();
}


先来看 final RemoteCallbackList<ITaskCallback> mCallbacks = new RemoteCallbackList <ITaskCallback>();
快应用的通信时通过RemoteCallbackList来实现的,用一个RemoteCallbackList来存储callback的列表。
首先我们需要实现一个ITaskBinder.Stub,用于注册和接触注册,或者是更改服务里面的内容的IBinder实例,我们需要在onBind()中返回它给client。
然后编写一回调函数void callback(String str),在callback里面,先通过mCallbacks.beginBroadcast();来获取当前的数目(这里应该指的是注册了的回调函数的数目,不过我没有测试过),然后通过mCallbacks.getBroadcastItem(i).sendString(str);
向client发送数据,sendString(str);就是你之前在ITaskBinder.aidl中实现的接口。

下面来看removeApp的内容
MainActivity.java代码

//注意根据你的包名来更改
package ***.***.remoteapp;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

//注意根据你的包名来更改
import ***.***.learnservice.ITaskBinder;
import ***.***.learnservice.ITaskCallback;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

private TextView tv;
private EditText et;
private Intent anotherAppServiceIntent=new Intent();
private static String backStr="";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注意根据你的包名来更改
anotherAppServiceIntent.setComponent(new ComponentName("***.***.learnservice","***.***.learnservice.MyService"));
tv= (TextView) findViewById(R.id.tv);
et= (EditText) findViewById(R.id.et);
findViewById(R.id.startAnotherAppSercvice).setOnClickListener(this);
findViewById(R.id.stopAnotherAppSercvice).setOnClickListener(this);
findViewById(R.id.bindAnotherAppSercvice).setOnClickListener(this);
findViewById(R.id.unbindAnotherAppSercvice).setOnClickListener(this);
findViewById(R.id.changeAnothetAppService).setOnClickListener(this);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.startAnotherAppSercvice:
startService(anotherAppServiceIntent);
break;
case R.id.stopAnotherAppSercvice:
stopService(anotherAppServiceIntent);
break;
case R.id.bindAnotherAppSercvice:
bindService(anotherAppServiceIntent,this, Context.BIND_AUTO_CREATE);
break;
case R.id.unbindAnotherAppSercvice:
binder=null;
unbindService(this);
break;
case R.id.changeAnothetAppService:
if(binder!=null)
{
try
{
binder.setServicePrint(et.getText().toString());
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
break;
}
}
private ITaskBinder binder;

ITaskCallback mCallback = new ITaskCallback.Stub() {
@Override
public void sendString(String str) throws RemoteException {
Message message=new Message();
Bundle bundle=new Bundle();
bundle.putString("callbackString",str);
message.setData(bundle);
handler.sendMessage(message);
}
};

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("绑定服务");
binder=ITaskBinder.Stub.asInterface(service);
try {
binder.registerCallback(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}

}

@Override
public void onServiceDisconnected(ComponentName name) {
try {
binder.unregisterCallback(mCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("解绑服务");
}

Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv.setText(msg.getData().getString("callbackString"));
}
};


}


在client中,通过bindService绑定服务后,就可以在重写中的onServiceConnected方法中注册你写的callback函数, ITaskCallback mCallback = new ITaskCallback.Stub() {};
在mCallback里面通过复写sendString(String str)就可以获取到服务传过来的字符串数据了。由于安卓的安全机制,副线程不能更改当前的视图线程的资源,所以我们可以通过Handler来更新TextView中的内容。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值