四大组件之Service
一、什么是服务
服务是一个没有界面,长期运行在后台的一个组件,它适合执行那些不用和用户交互且需要长期运行的任务,例如播放MP3或者下载。
二、服务的启动方式
服务的启动方式有两种,一种为startService(),另外一种为bindService。
startService方式启动服务
活动将服务开启之后 ,服务和活动之间基本没什么关系
第一步:我们自定义一个类,继承Service类
public class MyService extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } }
第二步:在清单文件里面注册服务。其实四大组件都必须在清单文件里面注册。
<service android:name="com.example.servicedemo.MyService"> </service>
第三步:在MainActivity里面开启服务。我们通过在布局文件中添加了两个按钮,一个用来启动服务,一个用来停止服务,布局文件很简单,这里就不粘出来了。
public class MainActivity extends Activity implements OnClickListener{ private Button start_service; private Button stop_service; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start_service = (Button) findViewById(R.id.start_service); stop_service = (Button) findViewById(R.id.stop_service); start_service.setOnClickListener(this); stop_service.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub int id =v.getId(); Intent intent =new Intent(this,MyService.class); switch (id) { case R.id.start_service: startService(intent); Toast.makeText(this, "服务开启成功", 0).show(); break; case R.id.stop_service: stopService(intent); Toast.makeText(this, "服务关闭成功", 0).show(); break; } } }
当我们点击了启动服务的按钮后,我们可以在手机上的Setting–>apps–>running里面看见我们的服务正在运行。当我们退出Activity后,服务还是会继续在后台运行。我们可以在running界面点击服务,然后点击stop按钮中断服务,也可以在MainActivity界面点击我们的关闭服务按钮关闭按钮。
bindService启动服务
用bindService来启动服务,可以将Activity与服务绑定,并且可以通过service回传的对象来调用服务里面的方法。
第一步:我们自定义一个类,继承Service类。这里我们需要在Myservice里面写个内部类MyBinder,它继承了Binder,我们利用service里面的onbind()方法,将内部类实例返回到Activity里面,这个类的对象可以调用service里面的方法。
public class MyService extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new MyBinder(); } // 服务里的方法 public void method_1() { Log.i("TAG", "method_1"); } public void method_2() { Log.i("TAG", "method_2"); } //Binder类是IBinder的子类 class MyBinder extends Binder { public void callMethod_1() { method_1(); } public void callMethod_2() { method_2(); } } }
第二步:在清单文件里面注册service,这里和上面是一样的,这里就不再赘述。布局文件里面多添加了一个按钮,用来调用service里面的方法。
第三部:在MainActivity里面开启服务
public class MainActivity extends Activity implements OnClickListener{ private Button start_service; private Button stop_service; private MyBinder mb; private MyServiceConnection conn; private Button callMethod; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start_service = (Button) findViewById(R.id.start_service); stop_service = (Button) findViewById(R.id.stop_service); callMethod = (Button) findViewById(R.id.callMethod); start_service.setOnClickListener(this); stop_service.setOnClickListener(this); callMethod.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub int id =v.getId(); Intent intent =new Intent(this,MyService.class); switch (id) { case R.id.start_service: conn = new MyServiceConnection(); //绑定服务 bindService(intent, conn, BIND_AUTO_CREATE); Toast.makeText(this, "服务开启成功", 0).show(); break; case R.id.stop_service: //解除绑定 unbindService(conn); Toast.makeText(this, "服务关闭成功", 0).show(); break; case R.id.callMethod: mb.callMethod_1(); mb.callMethod_2(); Toast.makeText(this, "调用方法成功", 0).show(); break; } } //Activity 与service之间的连接。当建立连接完成,会回调onServiceConnected方法,接收service回传过来的对象 class MyServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { mb = (MyBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } }
三、服务的生命周期
Service和Activity一样,都有自己的生命周期方法。
public class ExampleService extends Service {
int mStartMode;
IBinder mBinder;
boolean mAllowRebind;
@Override
public void onCreate() {
// 服务第一次被创建的时候调用该方法
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 启动时候会被调用该方法
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
// 客户端与service绑定的时候调用该方法
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// 所用的客户端都解除绑定后调用该方法
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
// A client is binding to the service with bindService(),
// onUnbind已经被回调后,一个客户端又来绑定服务的时候。
}
@Override
public void onDestroy() {
// 服务销毁的时候调用
}
}
四、两种启动Service的方式混合使用案例(音乐播放器)
下面我们通过这两种启动service的方式来写一个音乐播放器,主要是通过这个Demo来认识两种启动方式的作用。
布局文件:我们在布局文件里面写了三个Button,用来控制音乐的播放、暂停、继续播放。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click_play" android:text="播放"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click_play" android:text="暂停"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click_play" android:text="继续播放"/> </LinearLayout>
创建一个服务,用来播放音乐。
public class MusicService extends Service { MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return myBinder; } //播放音乐 public void play(){ Log.i("TAG", "play"); } //暂停音乐 public void pause(){ Log.i("TAG", "pause"); } //继续播放 public void resume(){ Log.i("TAG", "resume"); } private class MyBinder extends Binder implements Iservice{ @Override public void callPlay() { // TODO Auto-generated method stub play(); } @Override public void callPause() { // TODO Auto-generated method stub pause(); } @Override public void callResume() { // TODO Auto-generated method stub resume(); } } }
这里我们将Mybinder实现了一个Iservice的接口,这是为了方便将service里面的方法暴露出去。利用这个接口,我们可以将我们想要暴露的方法暴露出去。
public interface Iservice { public void callPlay(); public void callPause(); public void callResume(); }
在清单文件中注册service。
<service android:name="com.example.MusicService"> </service>
在MainActivity中利用两种启动service.
public class MainActivity extends Activity { private MyServiceConnection conn; private Iservice is; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent service =new Intent(this,MusicService.class); //启动服务 startService(service); //绑定服务 conn = new MyServiceConnection(); bindService(service, conn, BIND_AUTO_CREATE); } //播放音乐 public void click_play(View v){ is.callPlay(); } //暂停音乐 public void click_pause(View v){ is.callPause(); } //继续播放 public void click_resume(View v){ is.callResume(); } class MyServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { is = (Iservice) service; } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); //解除绑定 unbindService(conn); } }
如果想实现具体的播放音乐的功能,可以自己在MusicService 里面利用MediaPlayer 类来实现这个功能。