zoukankan      html  css  js  c++  java
  • android service 学习(上)

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

    Service是android 系统中的一种组件,它跟Activity的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service的启动有两种方式:context.startService() context.bindService()。
     
    使用context.startService() 启动Service是会会经历:
    context.startService()  ->onCreate()- >onStart()->Service running
    context.stopService() | ->onDestroy() ->Service stop 
     
    如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。 
     
    stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。
     
    所以调用startService的生命周期为:onCreate --> onStart(可多次调用) --> onDestroy
     
    使用使用context.bindService()启动Service会经历:
    context.bindService()->onCreate()->onBind()->Service running
    onUnbind() -> onDestroy() ->Service stop
     
    onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。 
          
    所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
     
    在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
     
    service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。
     
    下面我做了一个简单的音乐播放的应用,分别使用startService和bindService来启动本地的服务。
    而在下一篇《android service 学习(下) 》会介绍通过AIDL对Service进行远程调用。
     
    下面是整个应用启动界面:
    先从使用startService启动Service学起
     
     
    首先编写一个Activity

    01 public class PlayMusic extends Activity implements OnClickListener {
    02     private static final String TAG = "PlayMusic";
    03     private Button playBtn;
    04     private Button stopBtn;
    05     private Button pauseBtn;
    06     private Button exitBtn;
    07     private Button closeBtn;
    08   
    09     //....(详见源码)
    10   
    11 @Override
    12     public void onClick(View v) {
    13         int op = -1;
    14         Intent intent = new Intent("org.allin.android.musicService");
    15           
    16         //广播用
    17 //      Intent intent = new Intent("org.allin.android.musicReceiver");
    18           
    19         switch (v.getId()) {
    20         case R.id.play:
    21             Log.d(TAG, "onClick: playing muic");
    22             op = 1;
    23             break;
    24         case R.id.stop:
    25             Log.d(TAG, "onClick: stoping music");
    26             op = 2;
    27             break;
    28         case R.id.pause:
    29             Log.d(TAG, "onClick: pausing music");
    30             op = 3;
    31             break;
    32         case R.id.close:
    33             Log.d(TAG, "onClick: close");
    34             this.finish();
    35             break;
    36         case R.id.exit:
    37             Log.d(TAG, "onClick: exit");
    38             op = 4;
    39             stopService(intent);
    40             this.finish();
    41             break;
    42         }
    43           
    44         Bundle bundle  = new Bundle();
    45         bundle.putInt("op", op);
    46         intent.putExtras(bundle);
    47         startService(intent);
    48           
    49 //      sendBroadcast(intent);
    50     }
    51   
    52   
    53 }


     
    通过重写onClick方法来实现对播放音乐的控制。这里把播放音乐的各种操作用数字的方式通过Intent传递给service。 
    构造一个Intent ,ntent intent = new Intent("org.allin.android.musicService");
    "org.allin.android.musicService"是在AndroidManifest.xml文件中对service类的定义

    1 <service android:enabled="true" android:name=".MusicService">
    2 <intent-filter>
    3 <action android:name="org.allin.android.musicService" />
    4 </intent-filter>
    5 </service>

    把操作码放在Bundle中 
    Bundle bundle  = new Bundle();
    bundle.putInt("op", op);
    intent.putExtras(bundle);
    最后使用startService(intent);启动服务。 
    下面看看Service是怎么实现的。
     
    MusicService.java
     

    01 /**
    02  * @author allin.dev
    04  
    05  */
    06 public class MusicService extends Service {
    07   
    08     private static final String TAG = "MyService";
    09     private MediaPlayer mediaPlayer;
    10   
    11     /*
    12      * (non-Javadoc)
    13      
    14      * @see android.app.Service#onBind(android.content.Intent)
    15      */
    16     @Override
    17     public IBinder onBind(Intent arg0) {
    18         return null;
    19     }
    20   
    21     @Override
    22     public void onCreate() {
    23         Log.v(TAG, "onCreate");
    24         if (mediaPlayer == null) {
    25             mediaPlayer = MediaPlayer.create(this, R.raw.tmp);
    26             mediaPlayer.setLooping(false);
    27         }
    28     }
    29   
    30     @Override
    31     public void onDestroy() {
    32         Log.v(TAG, "onDestroy");
    33         if (mediaPlayer != null) {
    34             mediaPlayer.stop();
    35             mediaPlayer.release();
    36         }
    37     }
    38   
    39     @Override
    40     public void onStart(Intent intent, int startId) {
    41         Log.v(TAG, "onStart");
    42         if (intent != null) {
    43             Bundle bundle = intent.getExtras();
    44             if (bundle != null) {
    45   
    46                 int op = bundle.getInt("op");
    47                 switch (op) {
    48                 case 1:
    49                     play();
    50                     break;
    51                 case 2:
    52                     stop();
    53                     break;
    54                 case 3:
    55                     pause();
    56                     break;
    57                 }
    58   
    59             }
    60         }
    61   
    62     }
    63   
    64     public void play() {
    65         if (!mediaPlayer.isPlaying()) {
    66             mediaPlayer.start();
    67         }
    68     }
    69   
    70     public void pause() {
    71         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
    72             mediaPlayer.pause();
    73         }
    74     }
    75   
    76     public void stop() {
    77         if (mediaPlayer != null) {
    78             mediaPlayer.stop();
    79             try {
    80                 // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
    81                 mediaPlayer.prepare();
    82             } catch (IOException ex) {
    83                 ex.printStackTrace();
    84             }
    85         }
    86     }
    87   
    88 }

     
     
    服务 使用了系统自带MediaPlayer进行音乐的播放控制。 当调用了startService后服务会先调用onCreate,我们在里面对MediaPlayer进行初始化。接着会调用onStart,可以看到传递给startService()的Intent对象会传递给onStart()方法,这样我们就可以得到intent里面的操作码: 
    Iundle bundle = intent.getExtras(); 
    int op = bundle.getInt("op");
    然后更具定义好的操作码进行相应的f播放操作。启动后界面如下图: 
     
    图中的”close”和“exit”是不同的,close只是调用finish()退出当前的Activity,但是Service并没有关掉,音乐会继续播放。而exit就是调用了stopService(intent);来停止服务,Service会调用onDestroy()方法来对mediaPlayer进行停止和释放资源。
     
    有时候如果服务只提供一些操作接口,我们也可以通过广播的g方式来启动服务。
    首先要定义一个Receiver,并继承BroadcastReceiver,然后在AndroidManifest.xml中进行注册:

    1 <receiver android:name=".MusicReceiver">
    2 <intent-filter>
    3 <action android:name="org.allin.android.musicReceiver" />
    4 </intent-filter>
    5 </receiver>

     
    Receiver的实现:
     
    MusicReceiver.java

    01 /**
    02  * @author allin.dev
    04  *
    05  */
    06 public class MusicReceiver extends BroadcastReceiver {
    07   
    08     private static final String TAG = "MusicReceiver";
    09     @Override
    10     public void onReceive(Context context, Intent intent) {
    11         Log.d(TAG, "onReceive");
    12         Intent it = new Intent("org.allin.android.musicService");
    13         Bundle bundle = intent.getExtras();
    14         it.putExtras(bundle);
    15           
    16         if(bundle != null){
    17             int op = bundle.getInt("op");
    18             if(op == 4){
    19                 context.stopService(it);
    20             }else{
    21                 context.startService(it);
    22             }
    23         }
    24           
    25     }
    26   
    27 }

     
    然后对PlayMusic中的onclick方法进行些改造,把Intent指向Receiver
    Intent intent = new Intent("org.allin.android.musicReceiver");
    intent中绑定的操作码都不变,再调用sendBroadcast(intent);把intentg广播出去。
    MusicReceiver接受到广播后根据操作码进行相应的操作。




    接下来的例子就是使用bindService来启动Service
    首先一样是写一个Activity

    01 public class PlayBindMusic extends Activity implements OnClickListener {
    02   
    03     private static final String TAG = "PlayBindMusic";
    04     private Button playBtn;
    05     private Button stopBtn;
    06     private Button pauseBtn;
    07     private Button exitBtn;
    08       
    09     private BindMusicService musicService;
    10   
    11     @Override
    12     public void onClick(View v) {
    13   
    14         switch (v.getId()) {
    15         case R.id.play:
    16             Log.d(TAG, "onClick: binding srvice");
    17             musicService.play();
    18             break;
    19         case R.id.stop:
    20             Log.d(TAG, "onClick: stoping srvice");
    21             if(musicService != null){
    22                 musicService.stop();
    23             }
    24             break;
    25         case R.id.pause:
    26             Log.d(TAG, "onClick: pausing srvice");
    27             if(musicService != null){
    28                 musicService.pause();
    29             }
    30             break;
    31         case R.id.exit:
    32             Log.d(TAG, "onClick: exit");
    33             this.finish();
    34             break;
    35         }
    36     }
    37   
    38   
    39 private void connection(){
    40         Log.d(TAG, "connecting.....");
    41         Intent intent = new Intent("org.allin.android.bindService");
    42         bindService(intent, sc, Context.BIND_AUTO_CREATE);
    43           
    44     }
    45 private ServiceConnection sc = new ServiceConnection() {
    46         @Override
    47         public void onServiceDisconnected(ComponentName name) {
    48             musicService = null;
    49             Log.d(TAG, "in onServiceDisconnected");
    50         }
    51           
    52         @Override
    53         public void onServiceConnected(ComponentName name, IBinder service) {
    54             musicService = ((BindMusicService.MyBinder)(service)).getService();
    55             if(musicService != null){
    56                 musicService.play();
    57             }
    58               
    59             Log.d(TAG, "in onServiceConnected");
    60         }
    61     };
    62 }

    这里使用了bindService(intent, sc, Context.BIND_AUTO_CREATE);来启动服务的,
    我们需要定义ServiceConnectionnn,并实现里面的方法,当服务绑定成功后会调用ServiceConnectionnn中的回调函数:
    public void onServiceConnected(ComponentName name, IBinder service),
    回调函数里面使用musicService = ((BindMusicService.MyBinder)(service)).getService();来获取BindMusicService服务对象,有了BindMusicService实例对象,就可以调用服务提供的各种控制音乐播放的哦功能。
    下面看看BindMusicService.java的实现:

    01 /**
    02  * @author allin.dev
    04  */
    05 public class BindMusicService extends Service {
    06   
    07     private static final String TAG = "MyService";
    08     private MediaPlayer mediaPlayer;
    09   
    10     private final IBinder binder = new MyBinder();
    11   
    12     public class MyBinder extends Binder {
    13         BindMusicService getService() {
    14             return BindMusicService.this;
    15         }
    16     }
    17   
    18     /*
    19      * (non-Javadoc)
    20      
    21      * @see android.app.Service#onBind(android.content.Intent)
    22      */
    23     @Override
    24     public IBinder onBind(Intent intent) {
    25         Log.d(TAG, "onBind");
    26         play();
    27         return binder;
    28     }
    29   
    30     @Override
    31     public void onCreate() {
    32         super.onCreate();
    33           
    34         Log.d(TAG, "onCreate");
    35         Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();
    36           
    37           
    38     }
    39   
    40     @Override
    41     public void onDestroy() {
    42         super.onDestroy();
    43           
    44         Log.d(TAG, "onDestroy");
    45         Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);
    46         if(mediaPlayer != null){
    47             mediaPlayer.stop();
    48             mediaPlayer.release();
    49         }
    50     }
    51   
    52       
    53     public void play() {
    54         if (mediaPlayer == null) {
    55             mediaPlayer = MediaPlayer.create(this, R.raw.tmp);
    56             mediaPlayer.setLooping(false);
    57         }
    58         if (!mediaPlayer.isPlaying()) {
    59             mediaPlayer.start();
    60         }
    61     }
    62   
    63     public void pause() {
    64         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
    65             mediaPlayer.pause();
    66         }
    67     }
    68   
    69     public void stop() {
    70         if (mediaPlayer != null) {
    71             mediaPlayer.stop();
    72             try {
    73                 // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
    74                 mediaPlayer.prepare();
    75             } catch (IOException ex) {
    76                 ex.printStackTrace();
    77             }
    78         }
    79     }
    80   
    81 }



    我们看到Service中有个返回IBinder对象的onBind方法,这个方法会在Service被绑定到其他程序上时被调用,而这个IBinder对象和之前看到的onServiceConnected方法中传入的那个IBinder是同一个东西。应用和Service间就依靠这个IBinder对象进行通信。
    启动后的界面如下图:

    [源码下载]

  • 相关阅读:
    【GPS】Android O平台如何设置SUPL地址,以及GPS三个配置文件的优先级分析
    【GPS】gps.conf文件解读
    【GPS】SAP测试GPS模块拿不到sensor数据
    Linux系统安装Samba共享服务器详解及安装配置
    CentOS 6.5 编译安装 LNMP环境
    linux禁止root用户直接登录
    Linux下安装配置日志服务器
    Windows系统安装Oracle 11g客户端
    Linux系统zabbix_agentd客户端安装与配置
    Redhat6.5——解决yum功能不能正常使用
  • 原文地址:https://www.cnblogs.com/jeekun/p/2116698.html
Copyright © 2011-2022 走看看