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

移动开发 Android
本文51CTO专栏作者傻蛋将向我们介绍深入浅出 Android核心组件Service第四部分的系列文章。

在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();   
}   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

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;   
}   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.

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();   
        }   
   
    }   
   
}   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.

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>   
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

本节的源代码可在此下载:http://down.51cto.com/data/326382

责任编辑:佚名 来源: 最牛网
相关推荐

2012-02-07 14:45:52

Android核心组件Service

2012-02-07 15:29:17

Android核心组件Service

2012-02-07 14:37:01

Android核心组件Service

2012-02-07 15:09:03

Android核心组件Service

2012-02-21 13:55:45

JavaScript

2011-07-04 10:39:57

Web

2021-03-16 08:54:35

AQSAbstractQueJava

2011-05-05 14:44:43

SurfaceFlinSurfaceActivity

2013-11-14 15:53:53

AndroidAudioAudioFlinge

2022-09-26 09:01:15

语言数据JavaScript

2022-05-06 07:19:11

DOMDiff算法

2021-07-20 15:20:02

FlatBuffers阿里云Java

2012-05-21 10:06:26

FrameworkCocoa

2019-01-07 15:29:07

HadoopYarn架构调度器

2017-07-02 18:04:53

块加密算法AES算法

2022-01-13 09:38:25

Android架构设计

2016-10-14 14:32:58

JavascriptDOMWeb

2016-10-14 13:53:05

JavascriptDOMWeb

2009-11-17 17:31:58

Oracle COMM

2021-07-19 11:54:15

MySQL优先队列
点赞
收藏

51CTO技术栈公众号