android service 学习(下)

来源:互联网 发布:数据库脱机 编辑:程序博客网 时间:2024/05/17 09:04

转自:http://www.cnblogs.com/allin/archive/2010/05/15/1736462.html

通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在android平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在android为我们提供了AIDL工具可以来做这件事。

 

AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。

 

要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:

 
先创建一个IMyRemoteService.aidl文件

1
2
3
4
5
6
package org.allin.android.remote;
interfaceIMusicControlService{
        voidplay(); 
        voidstop(); 
        voidpause();
}

 
如果你正在使用eclipse的Android插件,则它会根据这个aidl文件生成一个Java接口类。生成的接口类中会有一个内部类Stub类,你要做的事就是去继承该Stub类:

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
/**
 * @author allin.dev
 *http://allin.cnblogs.com/
 *
 */
public class RemoteMusicService extendsService {
  
    privatestatic final String TAG = "RemoteMusicService";
    privateMediaPlayer mediaPlayer;
  
    /*
     * (non-Javadoc)
     
     * @see android.app.Service#onBind(android.content.Intent)
     */
    @Override
    publicIBinder onBind(Intent intent) {
        returnbinder;
    }
  
    privatefinal IMusicControlServic<SCRIPT type=text/javascript><!--mce:1--></SCRIPT>e.Stub binder =new IMusicControlService.Stub() {
  
        @Override
        publicvoid stop() throwsRemoteException {
            Log.d(TAG,"stop....");
            if(mediaPlayer != null) {
                mediaPlayer.stop();
                try{
                    // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
                    mediaPlayer.prepare();
                }catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
  
        }
  
        @Override
        publicvoid play() throwsRemoteException {
            Log.d(TAG,"play....");
            if(mediaPlayer == null) {
                mediaPlayer = MediaPlayer.create(RemoteMusicService.this,
                        R.raw.tmp);
                mediaPlayer.setLooping(false);
            }
            if(!mediaPlayer.isPlaying()) {
                mediaPlayer.start();
            }
        }
  
        @Override
        publicvoid pause() throwsRemoteException {
            Log.d(TAG,"pause....");
              
            if(mediaPlayer != null&& mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
            }           
        }
  
    };
      
      
    @Override
    publicvoid onDestroy() {
        super.onDestroy();
          
        Log.d(TAG,"onDestroy");
        if(mediaPlayer !=null){
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }
}

  
当客户端应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private ServiceConnection sc = new ServiceConnection() {
          
        @Override
        publicvoid onServiceDisconnected(ComponentName name) {
            musicService =null;
            Log.d(TAG,"in onServiceDisconnected");
        }
          
        @Override
        publicvoid onServiceConnected(ComponentName name, IBinder service) {
            musicService = IMusicControlService.Stub.asInterface(service);
            Log.d(TAG,"in onServiceConnected");
        }
    };

 
 启动后的界面如下