Android AIDL创建Service

简述:

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值