Service的启动方式有两种,一种是用startService()方法启动服务,另一种是用bindService()方法启动服务。startService启动的服务一般不和UI交互,只是在后台运行,后台程序结束后,Service应该关闭。bindService是一种和前台绑定的服务,他可以和UI交互,一个这样的服务可以多个组件绑定,当这些组件都取消和这个服务进行绑定的时候,这个服务会被销毁。
自定义的Service一般都继承Service这个类,并且应该实现这些方法:
1.onStartCommand(): 这个方法是用startService()方法启动时会被调用。
2.onBind(): 这个方法是用bindService()方法启动时被调用. 这个方法一定要实现,如果用startService()启动的服务,那么这个方法返回null即可.
3.onCreate(): 第一次生成Service时调用
4.onDestory(): 一般用于销毁Service时回收系统资源,停止线程。
下面是用startService()方法启动服务的例子,模仿音乐播放器,在Activity中有三个按钮:"启动服务"、“暂停服务”、“撤销服务”.当点击“启动服务”按钮的时候会调用startService()方法启动服务,“暂停服务”功能还没实现,“撤销服务”会调用stopService()方法撤销服务。当启动服务的时候,Service会启动一个线程,由1计数到100,这个模拟播放进度,并将这个进度值传递到MyMusicPlayer对象中,这个对象是由Activity传递到Service中的。在Activity中也启动一个线程,实时监听MyMusicPlayer的播放进度,达到一定值的时候提示用户.
运行结果:
Service:MyService
public class MyService extends Service { // 播放进度类的引用 private MyMusicPlayer player; private MyPlayerThread playerThread; @Override public void onCreate() { System.out.println("Service--->onCreate"); super.onCreate(); } /** * 当以startService方法启动服务时候,调用这个方法。<br> * 如果是以bindService绑定服务,则可以不用实现这个方法 */ @Override public int onStartCommand(Intent intent, int flags, int startId) { // 得到Activity传来的播放进度类的引用 if (null == player) { player = (MyMusicPlayer) intent.getSerializableExtra("Player"); playerThread = new MyPlayerThread(); playerThread.setName("thread_in_service"); playerThread.start(); } System.out.println("Service--->onStartCommand"); return super.onStartCommand(intent, flags, startId); } /** * 这个方法必须实现,如果是以bindService方法绑定服务,这个要返回指定IBinder<br> * 如果是以startService方法启动服务,则这个方法返回null */ @Override public IBinder onBind(Intent intent) { System.out.println("Service--->onBind"); return null; } @Override public void onDestroy() { System.out.println("Service--->onDestory"); super.onDestroy(); if (null != playerThread) playerThread.setProgress(100); } /** * 播放进度线程 */ class MyPlayerThread extends Thread { // 开始的时候进度为0 int progress = 0; public void setProgress(int progress) { this.progress = progress; } @Override public void run() { while (progress < 100) { player.setProgress(progress); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } progress++; System.out.println("Progress is: " + progress); } } } }
Activity: ServiceDemo
public class ServiceDemo extends Activity { // 播放进度的类的引用,传递到service中,与service交互 private MyMusicPlayer player; // 三个按钮控件的引用 private Button startButton; private Button stopButton; private Button destoryButton; // 线程控制器 private Handler handler; // 线程 private ProgressListener progressListener; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); System.out.println("Activity--->onCreate"); startButton = (Button) findViewById(R.id.start_button); stopButton = (Button) findViewById(R.id.stop_button); destoryButton = (Button) findViewById(R.id.destory_button); // 实例化 player = new MyMusicPlayer(); // 处理ProgressListener线程传来的消息 handler = new Handler() { public void handleMessage(android.os.Message msg) { if (ProgressListener.PROGRESS == msg.what) { System.out.println("当前进度为: " + msg.arg1); if (50 == msg.arg1) Toast.makeText(ServiceDemo.this, "当前进度为: " + msg.arg1, Toast.LENGTH_LONG).show(); if(100 <= msg.arg1) Toast.makeText(ServiceDemo.this, "已经播放完毕", Toast.LENGTH_LONG).show(); } } }; // 实例化线程 progressListener = new ProgressListener(); ServiceStateControl ssc = new ServiceStateControl(); startButton.setOnClickListener(ssc); stopButton.setOnClickListener(ssc); destoryButton.setOnClickListener(ssc); } /** * 三个按钮的监听器,点击后用intent通知service启动、暂停或者关闭 */ class ServiceStateControl implements OnClickListener { Intent intent = new Intent(); public void onClick(View v) { intent.setClass(ServiceDemo.this, MyService.class); if (v == startButton) { // 将MyMusicPlayer引用传递过Service里 intent.putExtra("Player", player); // 启动Service startService(intent); progressListener.start(); progressListener.setIsStart(true); } if (v == stopButton) { // 暂停服务 } if (v == destoryButton) { // 撤销Service stopService(intent); progressListener.setIsStart(false); } } } /** 监听播放进度的线程,将进度封装在Message中传递给Handler,让Handler处理 */ class ProgressListener extends Thread { // 此线程的编号 public static final int PROGRESS = 1001; // 服务启动状态 private boolean isStart = false; public void setIsStart(boolean isStart) { this.isStart = isStart; } @Override public void run() { while (isStart) { Message message = new Message(); message.what = ProgressListener.PROGRESS; // 传递进度值 message.arg1 = player.getProgress(); handler.sendMessage(message); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
传递数据的类:MyMusicPlayer
public class MyMusicPlayer implements Serializable { private static final long serialVersionUID = 1L; // 播放进度 public static int progress; public int getProgress() { return MyMusicPlayer.progress; } public void setProgress(int progress) { MyMusicPlayer.progress = progress; } }
这个MyMusicPlayer之前写在ServiceDemo中作为内部类,即使实现了Serializable接口也传递不了,后来意识到MyMusicPlayer作为ServiceDemo的内部类,如果要序列化的话,ServiceDemo里面的所有成员都要序列化,所以把MyMusicPlayer单独出来了