Android不同应用间的活动和服务的数据同步
在android的学习过程中,我理解了在同个应用中的活动和服务之间的数据同步;于是我想,不同应用中的活动和服务是否也可以同步数据呢,这里给出了我的一种方法,仅供参阅。
服务与活动之间的数据同步,在同一个应用中,可以通过定义回调接口来保持数据同步更新,但是在不同的应用中,活动无法获得另一个应用中服务的回调接口,这样的方法就不可行了。但是在活动和服务之间的连接是肯定可以建立的,通过设置这样的intent就行
`intent=new Intent();
intent.setComponent(new ComponentName("服务的包名","服务的包名.服务类名"));`
这时,我们通过启动和绑定服务就可以在活动和服务之间建立连接,我们都知道建立的连接得有一个binder,平常都是通过重写onBind函数的返回值来返回binder,然后通过活动中的onServiceConnected函数来获得binder。但是不同应用中获取binder的方法略有不同,我们需要返回的值不是自己定义的Binder类的一个变量,而是实现了AIDL接口的值,并且两个应用都需要定义同样的aidl文件。在aidl文件中,我们新声明了一个函数String getData(),用来返回服务中的数据,然后通过binder来存储这个值,传递到活动中去。
AIDL文件的代码,在原有aidl的基础上声明了一个函数:
// Declare any non-default types here with import statements
interface IAppSyncInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
String getData();
}
下面是服务的代码,服务所在的应用名称叫做app
/*app中的服务,我们需要使用这个服务来建立与another这个应用的通信;
* 在onCreate中创建一个线程,这个线程里存在一个不断变化的数字
* 我们需要将这个变化的数字同步与之进行通信的另一个应用中,这个应用的名称叫做app
* 我们通过AIDL接口来声明完成传递数据任务的函数getData,将不断变化的全局变量data传递出去*/
public class MyService extends Service {
private String data="默认数据";//服务中的数据
private int i=0;//服务中不断变化的数字
private boolean running=false ;//线程中while循环的执行条件,只要服务在运行,线程就不会停止
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new IAppSyncInterface.Stub() {//在这里重定义onBind的返回值,与activity进行绑定
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
public String getData(){//这个函数将服务中的数据传递出去,这个函数需要在AIDL接口(两个AIDL)中声明
return MyService.this.data;
}
};
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService","started");
running =true;
new Thread(){
@Override
public void run() {
super.run();
while(running){
i++;
data=i+"";
System.out.println(data);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
running=false;
Log.d("MyService","stoped");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
在这个服务中,我们定义了一个String data,用作这个服务中的数据,在onCreaet函数中,我们设置了一个线程,在这个线程中,我们让一个整型变量i不断增加,用于代替服务中不断变化的data。在onBind函数的返回值里,我们定义了接口中的函数getData,这样我们可以通过服务中的binder来获取服务中的data了,但是现在还不能实现数据的同步,因为没有回调函数来实现同步,接下来给出活动的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener,ServiceConnection{
private Intent intent;
private TextView textView;
private Bundle b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView)findViewById(R.id.textview);
findViewById(R.id.startService).setOnClickListener(this);
findViewById(R.id.stopService).setOnClickListener(this);
findViewById(R.id.bindService).setOnClickListener(this);
findViewById(R.id.unbindService).setOnClickListener(this);
intent=new Intent();
intent.setComponent(new ComponentName("com.example.test_startservicefromanotherapp","com.example.test_startservicefromanotherapp.MyService"));
//通过设置包名和类名来指定服务,启动服务和绑定服务都使用这个intent
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.startService:
startService(intent);
break;
case R.id.stopService:
stopService(intent);
break;
case R.id.bindService:
bindService(intent,this, Context.BIND_AUTO_CREATE);
break;
case R.id.unbindService:
unbindService(this);
binder=null;
break;
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//当bindService执行后,就会执行这个函数
Log.d("Myservice","绑定成功");
binder=IAppSyncInterface.Stub.asInterface(service);
//获取Service,转化为binder,全局变量binder这时已经代表了活动和服务之间的联系
new Thread(){
@Override
public void run() {
super.run();
while(binder!=null){
Message msg=new Message();
b=new Bundle();
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
if(binder!=null) {
b.putString("data", binder.getData());
}
} catch (RemoteException e) {
e.printStackTrace();
}
msg.setData(b);
handler.sendMessage(msg);
//将消息的获取和传递都放入这个线程中,不断的重新getData
//将binder所载的值传递进来
}
}
}.start();
}
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("死循环被关闭");
}
private IAppSyncInterface binder=null;
private Handler handler=new Handler(){
//将msg中的数据放入textView,实现两个进程间的通信
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText(msg.getData().getString("data"));
}
};
}
我们可以看到,在活动中,我们重写了onServiceConnected函数,将一个新的线程放入其中,刷新的频率相对较高,且循环执行的条件是binder不为空,并且在binder为空的时候也不能执行getData方法,防止了空对象的出现,在unbindService函数执行之后还将binder设为空,这样我们就可以实现数据的同步。
这里可能设计安全问题,由于我的能力尚且不足,还请各位多指正。