MyService

MyService.java

 1 import android.app.Service;
 2 import android.content.Intent;
 3 import android.content.ServiceConnection;
 4 import android.os.Binder;
 5 import android.os.IBinder;
 6 import android.util.Log;
 7 
 8 public class MyService extends Service {
 9     
10     //该方法是 Service 类中定义的抽象方法,必须实现
11     //用于获取该 Service 对象,如果返回  null,则意味着该 Service 不支持  bind
12     
13     @Override
14     public IBinder onBind(Intent arg0) {
15         Log.i("SINFO", "onBind running.");
16         return new MyIBinder();
17     }
18     
19 
20     //自定义类 继承 Binder,供 onBind 方法使用
21     class MyIBinder extends Binder{
22         MyService getService(){
23             return MyService.this;
24         }
25     }
26     
27     @Override
28     public void onCreate() {
29         Log.i("SINFO", "onCreate running.");
30         super.onCreate();
31     }
32     
33     @Override
34     public void onDestroy() {
35         Log.i("SINFO", "onDestroy running.");
36         super.onDestroy();
37     }
38     
39     @Override
40     public int onStartCommand(Intent intent, int flags, int startId) {
41         Log.i("SINFO", "onStartCommand running.");
42         return super.onStartCommand(intent, flags, startId);
43     }
44     
45     @Override
46     public boolean onUnbind(Intent intent) {
47         Log.i("SINFO", "onUnbind running.");
48         return super.onUnbind(intent);
49     }
50 
51 }

当 Activity 使用 bindService 方法,绑定 Service 时,并不能直接获取到 Service 对象,需要借助 ServiceConnection 对象。onServiceConnected 方法会在绑定成功时执行。其中参数 IBinder 就是 Service 对象中 onBind 方法返回的对象。获取到 Service 对象后,就可以执行其中的方法了。

启动一个 Service 有两种方法:调用 Context.startService() 或 Context.bindService。

(1)在同一个应用程序任何位置调用 startService() 方法都能启动 Service。系统回调 Service 类的 onCreate() 方法以及 onStart() 方法。这种方式启动的 Service 会一直运行在后台,直到调用 Context.stopService 或者 selfStop() 方法。如果一个 Service 已经被启动,其它代码再试图调用 startService() 方法启动 Service ,将不执行 onCreate(),而是重新执行一次 onstart() 方法。

(2)bindService() 方法也可以启动 Service,并把这个 Service 和调用 Service 的应用程序绑定起来。如果调用 Service 的应用程序类被销毁,Service 也将被销毁。使用这个方法的一个好处是:bindService() 方法执行后 Service 会回调 onBind() 方法,可以从这里返回一个实现了 IBinder 接口的类,在应用程序中就可以通过这个类和 Service 通信,得到 Service 运行的状态或其他操作。如果 Service 没有运行,使用这个方法启动 Service 会调用 onCreate() 方法,但不会调用 onStart() 方法。

 1 //用于连接 Activity 和 Service
 2     ServiceConnection sc = new ServiceConnection(){
 3         
 4         @Override
 5         public void onServiceConnected(ComponentName name, IBinder service) {
 6             //通过IBinder对象获取Service对象
 7             MyService ms = ((MyService.MyIBinder)service).getService();
 8             //此处  调用Service对象中的相应方法 即可
 9         }
10         
11         @Override
12         public void onServiceDisconnected(ComponentName name) {
13             
14         }
15     };
16         
17     @Override
18     public void onClick(View v) {
19         
20         if(v.getId() == R.id.bt_service1){
21             Intent intent = new Intent(this, MyService.class);
22             this.startService(intent);
23         }
24         else if(v.getId() == R.id.bt_service2){
25             Intent intent = new Intent(this, MyService.class);
26             this.stopService(intent);
27         }
28         else if(v.getId() == R.id.bt_service3){
29             Intent intent = new Intent(this, MyService.class);
30             //绑定Service
31             this.bindService(intent, sc, BIND_AUTO_CREATE);
32             isUnbind = true;
33         }
34         else if(v.getId() == R.id.bt_service4){
35             //解除绑定
36             if(isUnbind){
37                 this.unbindService(sc);
38                 isUnbind = false;
39             }
40         }        
41     }

 Context.bindService 第一个参数指明绑定的 Service,第二个参数是 ServiceConnection 对象,可以看作是 Activity 与 Service 的桥梁,第三个参数是绑定时的方式。如果重复执行解除绑定操作,会抛出异常信息。

Service 的两种启动方法有可能出现交叉调用的情况。如果出现这种情况,需要按照启动的顺序依次调用与启动对应的结束方式。例如:先调用 startService() ,然后再调用 bindService(),启动并绑定 Service 可以达到既保持和 Service 的通信,又使得 Service 不会随着 Activity 的退出而退出。当不需要绑定时,先调用 unbindService() 方法,此时 Service 会执行 onUnbind(),但不会把这个 Service 销毁。只有再调用 stopService() 时,Service 才会销毁。

在 Manifest 文件中添加 Service 的相关信息。

1 <!-- service声明 -->
2         <service android:name=".MyService" android:enabled="true"></service>

 Service 启动后会运行在主线程中,如果有耗时操作,可以在 Service 中开启线程。根据所使用的区域不同,Service 分为 Local Service 和 Remote Service。

(1)Local Service(本地服务)用于应用程序内部,当不需要与 Service 交互时,可以采用 Context.startService() 方式启动;需要和Service 交互时,采用 Context.bindService() 方式启动。

  1 import java.io.IOException;
  2 
  3 import android.app.Service;
  4 import android.content.Intent;
  5 import android.media.MediaPlayer;
  6 import android.os.IBinder;
  7 import android.util.Log;
  8 
  9 public class PlayerService extends Service {
 10     MediaPlayer player;
 11     
 12     @Override
 13     public IBinder onBind(Intent intent) {
 14         return null;
 15     }
 16     
 17     @Override
 18     public void onCreate() {
 19         super.onCreate();
 20     
 21         //指定播放音乐文件
 22         player = new MediaPlayer();
 23         try {
 24             player.setDataSource("/sdcard/music/my love.mp3");
 25             player.prepare();
 26         } catch (IllegalArgumentException e) {
 27             // TODO Auto-generated catch block
 28             e.printStackTrace();
 29         } catch (IllegalStateException e) {
 30             // TODO Auto-generated catch block
 31             e.printStackTrace();
 32         } catch (IOException e) {
 33             // TODO Auto-generated catch block
 34             e.printStackTrace();
 35         }
 36     }
 37     
 38     @Override
 39     public void onDestroy() {
 40         super.onDestroy();
 41     
 42         //停止播放,释放资源
 43         if(player != null){
 44             player.stop();
 45             player.release();
 46         }
 47         Log.i("INFO", "Service destroy!");
 48     }
 49     
 50     @Override
 51     public int onStartCommand(Intent intent, int flags, int startId) {
 52         Log.i("INFO", "onStartCommand" );
 53         if(intent != null){
 54             int op = intent.getIntExtra("op", 0);
 55             Log.i("INFO", "op=" + op);
 56             if(op == 1){
 57                 play();
 58             }else if(op == 2){
 59                 pause();
 60             }else if(op == 3){
 61                 stop();
 62             }
 63         }
 64         return super.onStartCommand(intent, flags, startId);
 65     }
 66     
 67     //播放控制的方法
 68     private void stop() {
 69         Log.i("INFO", "stop op");
 70         if(player != null){
 71             player.stop();
 72             try {
 73                 player.prepare();
 74             } catch (IllegalStateException e) {
 75                 // TODO Auto-generated catch block
 76                 e.printStackTrace();
 77             } catch (IOException e) {
 78                 // TODO Auto-generated catch block
 79                 e.printStackTrace();
 80             }
 81         }
 82     }
 83     
 84     private void pause() {
 85         Log.i("INFO", "pause op");
 86         if(player != null && player.isPlaying())
 87             player.pause();
 88     }
 89     
 90     private void play() {
 91         Log.i("INFO", "play op");
 92         if(!player.isPlaying())
 93             player.start();
 94     }
 95     
 96     @Override
 97     public boolean onUnbind(Intent intent) {
 98         return super.onUnbind(intent);
 99     }
100 }
PlayerService.java

Activity 启动 Service 让播放器工作在 Service 中,这样即使 Activity 退出,播放依然会继续。在启动 Service 时需要向 Service 中传入数据,可以借助 Intent 来实现。

 1 import android.app.Activity;
 2 import android.content.Intent;
 3 import android.os.Bundle;
 4 import android.view.View;
 5 import android.view.View.OnClickListener;
 6 import android.widget.ImageButton;
 7 
 8 public class PlayerActivity extends Activity implements OnClickListener {
 9     
10     ImageButton ib1,ib2,ib3;
11     Intent intent;
12     
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         // TODO Auto-generated method stub
16         super.onCreate(savedInstanceState);
17     
18         setContentView(R.layout.playerlayout);
19         ib1=(ImageButton) findViewById(R.id.ib_play);
20         ib1.setOnClickListener(this);
21     
22         ib2=(ImageButton) findViewById(R.id.ib_pause);
23         ib2.setOnClickListener(this);
24         
25         ib3=(ImageButton) findViewById(R.id.ib_stop);
26         ib3.setOnClickListener(this);
27     }
28     
29     @Override
30     public void onClick(View v) {
31         
32         intent = new Intent(this,PlayerService.class) ;
33         switch (v.getId()){
34         case R.id.ib_play:
35             intent.putExtra("op", 1);
36             break;
37         case R.id.ib_pause:
38             intent.putExtra("op", 2);
39             break;
40         case R.id.ib_stop:
41             intent.putExtra("op", 3);
42             break;
43         }
44         //启动Service
45         startService(intent);
46     }
47     
48     @Override
49     protected void onDestroy() {
50         super.onDestroy();
51     }
52 }
PlayerActivity.java

(2)Remote Service(远程服务)可以让其他应用程序访问该服务(Android 各应用程序都是互相独立的,数据独享),实际上就是可以进程间通信(RPC),这时需要使用 Android 提供的接口描述语言(AIDL)来定义远程服务的接口。

 1 import java.util.Random;
 2 
 3 import com.freshen.service.MessageInterface;
 4 import com.freshen.service.MessageInterface.Stub;
 5 
 6 import android.app.Service;
 7 import android.content.Intent;
 8 import android.os.IBinder;
 9 import android.os.RemoteException;
10 import android.util.Log;
11 
12 public class MessageService extends Service {
13     static final String TAG = "Tag";
14     
15     //内部类继承AIDL自动生成类的内部类Stub,并实现AIDL中声明的方法
16     private class MessageInterfaceImp extends MessageInterface.Stub{
17         Random r = new Random();
18         
19         @Override
20         public String getMessage() throws RemoteException {
21             Log.i(TAG, "return msg");
22             return "msg " + r.nextInt(100);
23         }
24     }
25     
26     @Override
27     public IBinder onBind(Intent arg0) {
28         Log.i(TAG, "onBind run.");
29         //返回AIDL接口实现
30         return new MessageInterfaceImp();
31     }
32     
33     @Override
34     public void onCreate() {
35         Log.i(TAG, "onCreate run.");
36         super.onCreate();
37     }
38     
39     @Override
40     public void onDestroy() {
41         Log.i(TAG, "onDestroy run.");
42         super.onDestroy();
43     }
44     
45     @Override
46     public boolean onUnbind(Intent intent) {
47         Log.i(TAG, "onUnBind run.");
48         return super.onUnbind(intent);
49     }
50 }
MessageService.java

MessageInterface.aidl 文件

1 interface MessageInterface{
2     String getMessage();
3 }

 

posted @ 2015-05-19 17:08  壬子木  阅读(670)  评论(0)    收藏  举报