简述:
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中的方法,返回所需的数据: