现在的位置: 首页 > 综合 > 正文

绑定服务后台播放音频的简单示例

2013年02月08日 ⁄ 综合 ⁄ 共 4371字 ⁄ 字号 评论关闭

1.服务

当应用程序不再位于前台且没有正在使用它的活动的时候,为了确保音频继续播放,我们需要创建一个服务。服务是安卓应用程序的一个组件,其用于在后台运行任务,而无须与用户交互。

2. 本地服务与远程服务

安卓中存在几个可用的不同服务类。本地服务(Local Service):作为特定应用程序的一部分存在,而且只能通过该应用程序访问和控制。远程服务(Remote Service):是另一种类型的服务,它们可以与其他应用程序进行通信,由其他应用程序访问和控制。在此,仅介绍使用一个本地服务提供音频播放的功能。

3.本地服务

服务类需要继承android.app.Service类。该类是抽象类,所以为了扩展它,必须实现onBind方法。

public IBinder onBind(Intent intent)
{
	// TODO Auto-generated method stub
	return msBinder;//*
}

通常如果只是实现简单服务,并不实现“绑定”的话,可以选择return null。

 

还有三个表示服务生命周期的方法,onCreate和onDestroy就不用说了,重点说说onStartCommand。每当利用一个匹配服务的意图调用startService时,就会调用onStartCommand方法,因此可能会多次调用它。onStartCommand方法将返回一个整数值,其表示如果结束该服务,那么操作系统应该如何执行操作。可以使用START_STICKY表明如果结束服务,那么将重新启动该服务。

public int onStartCommand(Intent intent, int flags, int startId)
	{
		// TODO Auto-generated method stub
		Log.v(TAG,"onStartCommand");
		if(!mediaPlayer.isPlaying())
		{
			mediaPlayer.start();
		}
		return START_STICKY;
		//return super.onStartCommand(intent, flags, startId);
	}

 

 

插一句:从android2.0中引入了onStartCommand方法,在此之前使用的是onStart方法。onStart方法的参数是一个意图和一个表示startId的整数。它不包括int类型的flags参数,而且没有返回值。如果目标电话在2.0之前运行,那么需要使用onStart方法。

注意,别忘了在清单文件中加入一个条目指定该服务。

下一步,我们还希望能够通过活动来控制服务中的MediaPlayer,而发出命令则显得更为复杂。为了控制MediaPlayer,需要利用bindService方法把该活动与服务绑定在一起(解绑定则使用unbindService)。一旦这样做了,由于活动与服务在相同的进程中运行,因此可以直接调用服务中的方法。如果正在创建一个远程服务,那么必须采取更深入一步的步骤。

                //启动音乐服务
		playMusicServiceIntent=new Intent(this,MusicService.class);
		startService(playMusicServiceIntent);
		//serviceConnection是一个ServiceConnection类型的对象,它是一个接口,用于监控所绑定服务的状态
		serviceConnection=new ServiceConnection()
		{
			
			@Override
			public void onServiceDisconnected(ComponentName name)
			{
				// TODO Auto-generated method stub
				musicService=null;
			}
			//注意该方法传入了一个IBinder对象,其实际上是由服务本身创建并提交的
			@Override
			public void onServiceConnected(ComponentName name, IBinder service)
			{
				// TODO Auto-generated method stub
				musicService=((MusicService.MusicServiceBinder)service).getService();
			}
		};
		
		//绑定服务时,需要传入intent和serviceConnection
		bindService(playMusicServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);

我们在服务类中创建了一个私有内部类,其继承自Binder类,在活动中请求连接服务时,用于返回服务本身

 

 

public class MusicServiceBinder extends Binder//*
	 {
		 MusicService getService()
		 {
			 return MusicService.this;
		 }
	 }

 

现在就搭好了基础,可以向服务中添加任何喜欢的功能,同时通过绑定服务,可以直接调用服务中定义的各种方法。如果不绑定服务的话,那么除了启动和停止服务之外,我们将不能做任何其他的事情。

完整代码示例:

活动中的代码:

//启动音乐服务
		playMusicServiceIntent=new Intent(this,MusicService.class);
		startService(playMusicServiceIntent);
		
		serviceConnection=new ServiceConnection()
		{
			
			@Override
			public void onServiceDisconnected(ComponentName name)
			{
				// TODO Auto-generated method stub
				musicService=null;
			}
			
			@Override
			public void onServiceConnected(ComponentName name, IBinder service)
			{
				// TODO Auto-generated method stub
				musicService=((MusicService.MusicServiceBinder)service).getService();
			}
		};
		
		//绑定服务
		bindService(playMusicServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
		//控制音乐服务的按钮
		Musicbtn=(Button) findViewById(R.id.musicOn);
		Musicbtn.setBackgroundResource(R.drawable.musicon);
		Musicbtn.setOnClickListener(new OnClickListener()
		{

			@Override
			public void onClick(View v)
			{
				// TODO Auto-generated method stub
				if(musicService.IsPlayNow())
				{
					Musicbtn.setBackgroundResource(R.drawable.musicoff);
					musicService.PauseMusic();
				}
				else
				{
					Musicbtn.setBackgroundResource(R.drawable.musicon);
					musicService.ResumeMusic();
				}
				
			}
			
		});

服务类代码:

public class MusicService extends Service implements OnCompletionListener
{
	 static final String TAG="PLAYERSERVICE";
	 MediaPlayer mediaPlayer;
	 private final IBinder msBinder=new MusicServiceBinder();//*
	 
	 public class MusicServiceBinder extends Binder//*
	 {
		 MusicService getService()
		 {
			 return MusicService.this;
		 }
	 }
	@Override
	public void onCreate()
	{
		// TODO Auto-generated method stub
		//super.onCreate();
		Log.v(TAG,"onCreate");
		mediaPlayer=MediaPlayer.create(this,R.raw.music);
		mediaPlayer.setOnCompletionListener(this);
	}

	@Override
	public void onDestroy()
	{
		// TODO Auto-generated method stub
		if(mediaPlayer.isPlaying())
		{
			mediaPlayer.stop();
		}
		mediaPlayer.release();
		Log.v(TAG,"onDestroy");
		//super.onDestroy();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		// TODO Auto-generated method stub
		Log.v(TAG,"onStartCommand");
		if(!mediaPlayer.isPlaying())
		{
			mediaPlayer.start();
		}
		return START_STICKY;
		//return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent)
	{
		// TODO Auto-generated method stub
		return msBinder;//*
	}

	@Override
	public void onCompletion(MediaPlayer mediaPlayer)
	{
		// TODO Auto-generated method stub
		//stopSelf();
		mediaPlayer.start();
	}
	
	public void PauseMusic()
	{
		if(mediaPlayer.isPlaying())
		{
			mediaPlayer.pause();
		}
	}
	
	public void ResumeMusic()
	{
		if(!mediaPlayer.isPlaying())
		{
			mediaPlayer.start();
		}
	}
	
	public boolean IsPlayNow()
	{
		return mediaPlayer.isPlaying();
	}
}

 

 

抱歉!评论已关闭.