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 }
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 }
(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 }
MessageInterface.aidl 文件
1 interface MessageInterface{ 2 String getMessage(); 3 }

浙公网安备 33010602011771号