深入浅出 Android Service(4)

       在android平台中,一个进程通常不能访问其他进程中的内存区域的。但是,我们可以使用IDL语言来把对象伪装成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。
       如果想在应用程序中调用其他进程中的Service,则需要用到AIDL,AIDL(android接口描述语言)是一种IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
 

使用AIDL的方法如下:
1.首先要编写一个IMusicService.aidl的服务接口,ADT会根据这个接口文件帮我们自动生成一个 Stub类,这个类继承了Binder类,同时继承了IMusicService这个接口,还可以看到其中包含了一个Proxy代理类,以实现远程代理,访问不同的进程。(aidl和Stub类如下所示)。
/**
 * IMusicService.aidl
 * com.androidtest.service.mediaplayer
 *
 * Function: TODO 
 *
 *   ver     date      		author
 * ──────────────────────────────────
 *   		 2011-5-19 		Leon
 *
 * Copyright (c) 2011, TNT All Rights Reserved.
*/

package com.zuiniuwang.service;
/**
 * ClassName:IMusicService
 * Function: TODO ADD FUNCTION
 * Reason:	 TODO ADD REASON
 *
 * @author   Leon
 * @version  
 * @since    Ver 1.1
 * @Date	 2011-5-19
 */


interface IMusicService{
	void play();
	void pause();
	void stop();
}

2. 生成的Stub类如下,我们暂不做详细讲解,后面的课程中我们会尝试自己来写一个类似的类,完成不同进程的访问。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\myworkspace\\musicservice4\\src\\com\\zuiniuwang\\service\\IMusicService.aidl
 */
package com.zuiniuwang.service;
/**
 * ClassName:IMusicService
 * Function: TODO ADD FUNCTION
 * Reason:	 TODO ADD REASON
 *
 * @author   Leon
 * @version  
 * @since    Ver 1.1
 * @Date	 2011-5-19
 */
public interface IMusicService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.zuiniuwang.service.IMusicService
{
private static final java.lang.String DESCRIPTOR = "com.zuiniuwang.service.IMusicService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.zuiniuwang.service.IMusicService interface,
 * generating a proxy if needed.
 */
public static com.zuiniuwang.service.IMusicService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zuiniuwang.service.IMusicService))) {
return ((com.zuiniuwang.service.IMusicService)iin);
}
return new com.zuiniuwang.service.IMusicService.Stub.Proxy(obj);
}
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_play:
{
data.enforceInterface(DESCRIPTOR);
this.play();
reply.writeNoException();
return true;
}
case TRANSACTION_pause:
{
data.enforceInterface(DESCRIPTOR);
this.pause();
reply.writeNoException();
return true;
}
case TRANSACTION_stop:
{
data.enforceInterface(DESCRIPTOR);
this.stop();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.zuiniuwang.service.IMusicService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public void play() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public void pause() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_pause, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public void stop() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_pause = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
public void play() throws android.os.RemoteException;
public void pause() throws android.os.RemoteException;
public void stop() throws android.os.RemoteException;
}

3. 在Activity中得到Binder的方式,是通过Stub类的IMusicService.Stub.asInterface(binder)方法(这一点和以前不同)。相应的代码如下:
/**
 * RemoteMusicPlayerActivity.java
 * com.androidtest.activity.musicplayer
 *
 * Function: TODO 
 *
 *   ver     date      		author
 * ──────────────────────────────────
 *   		 2011-5-20 		Leon
 *
 * Copyright (c) 2011, TNT All Rights Reserved.
 */

package com.zuiniuwang.playeractivity;



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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.zuiniuwang.R;
import com.zuiniuwang.service.IMusicService;

/**
 * ClassName:RemoteMusicPlayerActivity Function: TODO ADD FUNCTION Reason: TODO
 * ADD REASON
 * 
 * @author Leon
 * @version
 * @since Ver 1.1
 * @Date 2011-5-20
 */
public class RemoteMusicPlayerActivity extends Activity implements
		OnClickListener { 

	private static final String TAG = RemoteMusicPlayerActivity.class
			.getSimpleName();

	private Button playButton, pauseButton, stopButton, closeActivityButton,
			exitActivityButton;

	private IMusicService musicServiceInterface;

	@Override
	protected void onCreate(Bundle savedInstanceState) {

		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.music_player_layout);
		findViews();
		bindViews();
		connection();
	}

	private void findViews() {
		playButton = (Button) this.findViewById(R.id.play);
		pauseButton = (Button) this.findViewById(R.id.pause);
		stopButton = (Button) this.findViewById(R.id.stop);
		closeActivityButton = (Button) this.findViewById(R.id.close);
		exitActivityButton = (Button) this.findViewById(R.id.exit);
	}

	private void bindViews() {
		playButton.setOnClickListener(this);
		pauseButton.setOnClickListener(this);
		stopButton.setOnClickListener(this);
		closeActivityButton.setOnClickListener(this);
		exitActivityButton.setOnClickListener(this);
	}

	private void connection() {
		Intent intent = new Intent(
				"com.androidtest.service.mediaplayer.RemoteMusicService");
		this.startService(intent);
		this.bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);

	}

	private ServiceConnection myServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName name, IBinder binder) {
			musicServiceInterface = IMusicService.Stub.asInterface(binder);
			Log.d(TAG, " onServiceConnected");
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			musicServiceInterface = null;
			Log.d(TAG, " onServiceDisconnected");
		}

	};

	@Override
	public void onClick(View view) {

		// TODO Auto-generated method stub
		try {
			switch (view.getId()) {
			case R.id.play:
				Log.d(TAG, "play.......");
				musicServiceInterface.play();
				break;
			case R.id.pause:
				Log.d(TAG, "pause.......");
				musicServiceInterface.pause();
				break;
			case R.id.stop:
				Log.d(TAG, "stop.......");
				musicServiceInterface.stop();
				break;
			case R.id.close:
				//Activity退出之前要解除绑定,不然会报错
				this.unbindService(myServiceConnection);
				Log.d(TAG, "close.......");
				this.finish();
				break;
			case R.id.exit:
				Log.d(TAG, "exit.......");
				this.unbindService(myServiceConnection);
				this.stopService(new Intent("com.androidtest.service.mediaplayer.RemoteMusicService"));
				this.finish();

			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

4. 最后在此Service注册的时候我们需要指定它是在一个不同的进程中运行的,本例子指定的是remote进程。注意 process参数。
       <!-- 注册Service -->
		<service android:enabled="true"
			android:name=".service.RemoteMusicService"  android:process=":remote">
			<intent-filter>
				<action android:name="com.androidtest.service.mediaplayer.RemoteMusicService" />
			</intent-filter>
		</service>

本节的源代码可在此下载:http://download.csdn.net/detail/internetman/3967828  
有问题可以发表评论或者微博私信我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值