(七)Android中AIDL的应用与理解
一、跨应用启动Service
Intent serviceIntent=new Intent();
serviceIntent.setComponent(new ComponentName("com.example.shiyanshi.startservicefromanotherapp","com.example.shiyanshi.startservicefromanotherapp.AppService"));
跨应用启动Service时,Android5.0以前可以调用隐式Intent(通过在Service设置过滤器intent-filte),Android5.0之后只允许显示Intent来启动。首先创建Intent,之后调用setComponent函数来设置组件,该函数需要一个ComponentName的对象,ComponentName第一个参数为包名,第二个参数为包中的服务类名。
二、跨应用绑定Service并进行通信
app模块中:
1.MainActivity.java
package com.example.shiyanshi.startservicefromoterapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,MyService.class));
}
@Override
protected void onDestroy() {
super.onDestroy();
stopService(new Intent(this,MyService.class));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
2.MyService.java
package com.example.shiyanshi.startservicefromoterapp;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
private String data="default data";
private boolean flag;
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
//返回的是AIDL中的接口,并且此处实现了接口函数的重定义
return new IAppRemoteServiceBinder.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setData(String data) throws RemoteException {
MyService.this.data=data;
}
};
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("**********MyService onCreate************");
//该线程主要用于不断的输出该service种的数据data,data数据的值可以通过在anotherapp中调用setData函数进行设置,这样便实现了双方的通信
new Thread(){
@Override
public void run() {
super.run();
flag=true;
while (flag) {
System.out.println(data);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("***************MyService onDestroy********************");
flag=false;
}
}
//
不同的应用进行通信时需要创建aidl文件,并且在其中实现接口函数的定义
3.IAppRemoteServiceBinder.aidl
// IAppRemoteServiceBinder.aidl
package com.example.shiyanshi.startservicefromoterapp;
// Declare any non-default types here with import statements
interface IAppRemoteServiceBinder {
/**
* 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);
void setData(String data); //用于两个应用程序之间进行通信的接口函数
}
anotherapp中:
1.布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动外部服务"
android:id="@+id/btnStartService"
android:layout_gravity="bottom" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="关闭外部服务"
android:id="@+id/btnStopService"
android:layout_gravity="center_vertical" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定外部服务"
android:id="@+id/btnBindService" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解除绑定外部服务"
android:id="@+id/btnUnbindService" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="同步数据到外部服务"
android:id="@+id/btnSyncDataToAppService" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="**************"
android:id="@+id/editTextInput"/>
</LinearLayout>
2.MainActivity.java
package com.example.shiyanshi.anotherapp;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import com.example.shiyanshi.startservicefromoterapp.IAppRemoteServiceBinder;
public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection {
Intent serviceIntent;
private EditText editTextInput;
private IAppRemoteServiceBinder binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextInput=(EditText)findViewById(R.id.editTextInput);
findViewById(R.id.btnStartService).setOnClickListener(this);
findViewById(R.id.btnStopService).setOnClickListener(this);
findViewById(R.id.btnBindService).setOnClickListener(this);
findViewById(R.id.btnUnbindService).setOnClickListener(this);
findViewById(R.id.btnSyncDataToAppService).setOnClickListener(this);
serviceIntent=new Intent();
serviceIntent.setComponent(new ComponentName("com.example.shiyanshi.startservicefromoterapp","com.example.shiyanshi.startservicefromoterapp.MyService"));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btnStartService:
startService(serviceIntent);
break;
case R.id.btnStopService:
stopService(serviceIntent);
break;
case R.id.btnBindService:
bindService(serviceIntent,this, Context.BIND_AUTO_CREATE);
break;
case R.id.btnUnbindService:
unbindService(this);
binder=null;
break;
case R.id.btnSyncDataToAppService:
if (binder!=null){
try {
binder.setData(editTextInput.getText().toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
}
}
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
System.out.println("*******onServiceConnected*************");
//不能直接强制类型转换,因为两个类型处于不同的应用程序中
binder=IAppRemoteServiceBinder.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}