您的位置:首页 > 移动开发 > Android开发

深入浅出 Android核心组件Service(4)

2013-07-10 16:34 357 查看
在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>  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: