关闭

Service之startServie简单范例

标签: servicebuttonthreadnullclassui
1574人阅读 评论(0) 收藏 举报
分类:

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单独出来了



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:92025次
    • 积分:792
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:6篇
    • 译文:0篇
    • 评论:16条
    文章分类
    最新评论