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方法启动服务时候,调用这个方法。
* 如果是以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
* 如果是以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单独出来了