简述:
1. Android开发中会用到Service这个类,Service用于实现进程间方法的调用,UI中调用音乐播放服务就用到Service,起到跨进程通信的作用
2. AIDL: Android Interface Definition Language,Android内部进程通信接口的描述语言,通过他可以定义进程间通信接口,结合service在后台运作,暴露接口用来和当前程序通信
3,.Android 提供了Parcel类型,Parcel用作封装数据的容器,封装后的数据可以通过Intent或IPC传递,除了基本类型之外,只有实现了Parcelable接口的类才能被放入Parcel
本文参考:
http://blog.csdn.net/stonecao/article/details/6425019
http://blog.csdn.net/liuhe688/article/details/6409708
http://blog.sina.com.cn/s/blog_78e3ae430100pxba.html
知识点:
1. Android service
2. AIDL的使用,在aidl文件中复杂类型的导入
3. Parcelable接口的使用
项目工程文件目录
其中gen下的com.atp.aidl是AIDL自带生成的(clean->build之后就能生成)
代码:
com.atp.aidl包
Fruit.java
package com.atp.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Fruit implements Parcelable {
private String name;
private Integer size;
public Fruit(String name, Integer size) {
this.name = name;
this.size = size;
}
public Fruit(Parcel source) {
readFromParcel(source);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getsize() {
return size;
}
public void setsize(Integer size) {
this.size = size;
}
@Override
public String toString() {
return "[name: " + name + ", size: " + size + "]";
}
//AIDL needs CREATOR static final android.os.Parcelable.Creator<T> to call service
public static final Parcelable.Creator<Fruit> CREATOR = new Parcelable.Creator<Fruit>() {
@Override
public Fruit createFromParcel(Parcel source) {
return new Fruit(source);
}
@Override
public Fruit[] newArray(int size) {
return new Fruit[size];
}
};
@Override
public int describeContents() {
return 0;
}
//write and read must in the same sequence
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(size);
}
public void readFromParcel(Parcel source) {
name = source.readString();
size = source.readInt();
}
}
Fruit.aidl 复杂类型的aidl文件
package com.atp.aidl;
parcelable Fruit;
ITestService.aidl的接口文件
package com.atp.aidl;
import com.atp.aidl.Fruit;
interface ITestService {
String getSomething();
Fruit getFruit();
}
com.atp.service包
package com.atp.service;
import com.atp.aidl.Fruit;
import com.atp.aidl.ITestService;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service{
public static final String TAG = "com.atp.ui.MyService";
private class MyServiceImpl extends ITestService.Stub{
@Override
public String getSomething() throws RemoteException {
Log.e(TAG, "getSomething");
return "Apple";
}
@Override
public Fruit getFruit() throws RemoteException {
Fruit fruit = new Fruit("Banana", 10);
return fruit;
}
}
@Override
public IBinder onBind(Intent arg0) {
//return implementation of AIDL
return new MyServiceImpl();
}
@Override
public void onDestroy() {
Log.e(TAG, "Release MyService");
super.onDestroy();
}
}
com.atp.ui包
MainActivity.java
package com.atp.ui;
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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.atp.R;
import com.atp.aidl.Fruit;
import com.atp.aidl.ITestService;
import com.atp.service.MyService;
public class MainActivity extends Activity {
public static final String TAG = "com.atp.ui.MainActivity";
private Button myBtn = null;
private TextView myTv = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
myBtn = (Button) findViewById(R.id.myBtn);
myTv = (TextView) findViewById(R.id.myTv);
myBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
bindMyService();
}
});
}
private ITestService iService = null;
private ServiceConnection conn = new ServiceConnection(){
private String resultFromService;
private Fruit fruitFromService;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//return AIDL object,then call methods of AIDL
iService = ITestService.Stub.asInterface(service);
try {
resultFromService = iService.getSomething();
fruitFromService = iService.getFruit();
} catch (RemoteException e) {
Log.e(TAG, "Error while call on iService!");
e.printStackTrace();
}
Log.e(TAG, "something is:" + resultFromService);
myTv.setText("something is:" + resultFromService + "\n"
+ "fruit: " + fruitFromService.toString());
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
Log.i(TAG, "release iService");
}
};
private void bindMyService(){
Intent intent = new Intent(this, MyService.class);
startService(intent);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}
视图xml文件
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/myBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start"
android:textSize="22dip"
/>
<TextView
android:id="@+id/myTv"
android:layout_width="500dip"
android:layout_height="100dip"
android:layout_below="@id/myBtn"
android:text="Text Area"
android:textSize="22dip"/>
</RelativeLayout>
下面是在AndroidManifest.xml注册这个service
其中对于android:process这一属性的解释:
android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.atp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".ui.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".service.MyService"
android:process=":remote">
<intent-filter>
<action android:name=".aidl.ITestService" />
</intent-filter>
</service>
</application>
</manifest>
这是由com.atp.aidl下的aidl文件 自动generate出来的文件
ITestService.java
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: C:\\Users\\anialy.anialy-PC\\Desktop\\eclipse_work_space_2\\AndroidTestProject\\src\\com\\atp\\aidl\\ITestService.aidl
*/
package com.atp.aidl;
public interface ITestService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.atp.aidl.ITestService
{
private static final java.lang.String DESCRIPTOR = "com.atp.aidl.ITestService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.atp.aidl.ITestService interface,
* generating a proxy if needed.
*/
public static com.atp.aidl.ITestService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.atp.aidl.ITestService))) {
return ((com.atp.aidl.ITestService)iin);
}
return new com.atp.aidl.ITestService.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_getSomething:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getSomething();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getFruit:
{
data.enforceInterface(DESCRIPTOR);
com.atp.aidl.Fruit _result = this.getFruit();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.atp.aidl.ITestService
{
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 java.lang.String getSomething() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getSomething, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public com.atp.aidl.Fruit getFruit() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.atp.aidl.Fruit _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getFruit, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.atp.aidl.Fruit.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getSomething = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getFruit = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.lang.String getSomething() throws android.os.RemoteException;
public com.atp.aidl.Fruit getFruit() throws android.os.RemoteException;
}
效果,点击之后获取service中的方法,返回所需的数据: