—今天在做毕设的时候需要用到播放提示音,想了想,当需要提示的时候新建一个Service来播放提示音比较好,而且可以在响应事件中控制提示音的播放,就先专门弄了个小的例子来练下手,于是修改了下之前入门Service时候写的代码,实现一个简易的音乐播放。(这里使用的是MediaPlayer,如果是较短提示音的话使用SoundPool比较好)
什么是服务:
服务是Android中实现程序后台运行的解决方案,它非常适合用于去执行哪些不需要和用户交互而且还要求长期运行的任务,服务不依赖于任何界面,即使当程序被切换到后台,或者打开了另外一个程序,服务仍然能够保持正常运行,服务的优先级是高于Activity的,另外服务作为四大组件,在新建的时候一定要在AndroidManifest.xml文件中进行注册才能使用。
服务运行环境:
服务不是独立运行在进程中的,而是依赖于创建该服务时所在的应用程序进程,当某个应用程序被杀掉时,所依赖于这个进程的服务也会被停止。
需要注意的是,服务不会自己开启线程,所有的代码都是默认运行在主线程当中的,也就是说,我们需要在服务的内部手动创建子线程,并在其中执行具体的任务,负责就可能出现子线程被阻塞的情况,可以用多线程编程解决,Android专门为我们提供了一个类---IntentService,可以创建异步的、可自动停止运行的服务。
常见的服务用途:后台放音乐,后台记录地理位置的改变,监听程序动作
常见使用服务的方式:
启动:startService(Intent实例);
Intent intent1 = new Intent(MainActivity.this,MyStartService.class);
startService(intent1);关闭:stopService(Intent实例);
stopService(intent1);
启动和关闭的时候Intent实例必须是同一个,不然不能停止服务;
启动:bindService(Intent实例,ServiceConnection实例,BIND_AUTO_CREATE);
Intent intent2 = new Intent(MainActivity.this,MyBindService.class);
bindService(intent2, conn, BIND_AUTO_CREATE);关闭:unbindService(conn);
unbindService(conn);
conn是ServiceConnection实例的实例,待会在代码中给出,需要注意的是,如果要活Service自动关闭,上面两种都可以使用stopSelf();但是如果既使用了startService又使用了bingService的话,就要同时调用stopService和ubBindService方法才能使服务的onDestory()执行;
今天正好用到下面通过一个小的简易音乐播放来演示下Activity和Service之间的通信:主要利用服务中的onBind方法,新建一个专门的Binder对象进行通信。
1、建一个服务,用来定义一些播放的操作。
package com.service.css.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.IOException;
/**
* Created by css on 2016/3/29.
*/
public class MyBindService extends Service implements MediaPlayer.OnCompletionListener{
private MediaPlayer mediaPlayer;
//实现MediaPlayer.OnCompletionListener接口的方法
@Override
public void onCompletion(MediaPlayer mp) {
stopSelf();
}
//新建类同于回调
public class MyBinder extends Binder
{
public MyBindService getService()
{
//获得MyBindService,可以执行它的方法
return MyBindService.this;
}
}
//用于传送Binder对象给Activity
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("TAG", "这里是 onBind");
return new MyBinder();
}
//初始化的时候使用,对此绑定只执行一次
@Override
public void onCreate() {
Log.d("TAG","这里是 onCreate");
mediaPlayer = MediaPlayer.create(this, R.raw.alarm);
mediaPlayer.setOnCompletionListener(this);
//开始震动
// vibrator = (Vibrator) getApplicationContext().getSystemService(Service.VIBRATOR_SERVICE);
super.onCreate();
}
//初始化的时候使用,对此绑定执行多次,
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
return START_STICKY;
}
//解绑定的时候执行的方法
@Override
public boolean onUnbind(Intent intent) {
Log.d("TAG", "这里是 onUnbind");
return super.onUnbind(intent);
}
//重写onDestroy方法
@Override
public void onDestroy() {
Log.d("TAG", "这里是 onDestroy");
//停止
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
//释放
mediaPlayer.release();
super.onDestroy();
}
//播放
public void play()
{
Log.d("TAG", "播放");
//如果不正在播放,则开始播放
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
}
//暂停
public void pause()
{
Log.d("TAG", "暂停");
//暂停播放,下次点击播放可以接着暂停的地方播放
mediaPlayer.pause();
}
//停止
public void stop()
{
Log.d("TAG", "停止");
//如果不为空,停止
if (mediaPlayer != null) {
mediaPlayer.stop();
try {
mediaPlayer.prepare();//stop后下次重新播放要首先进入prepared状态
mediaPlayer.seekTo(0);//须将播放时间设置到0;这样才能在下次播放是重新开始,否则会继续上次播放
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、主Activity中的代码:
package com.service.css.servicedemo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private MyBindService myBindService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//使用ServiceConnection,在Activity和Service连接、断开的时候执行操作;
ServiceConnection conn = new ServiceConnection() {
//连接执行的操作
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("TAG","service is onServiceConnected!");
myBindService = ((MyBindService.MyBinder)service).getService();
}
//断开执行的操作
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("TAG","service is onServiceDisconnected!");
}
};
//处理Button的点击事件(在布局文件中指定了onClick属性)
public void doClick(View v)
{
switch(v.getId())
{
//Activity和Service绑定
case R.id.bind:
Intent intent2 = new Intent(MainActivity.this,MyBindService.class);
bindService(intent2, conn, BIND_AUTO_CREATE);
break;
//播放操作
case R.id.play:
myBindService.play();
break;
//暂停操作
case R.id.pause:
myBindService.pause();
break;
//停止操作
case R.id.stop:
myBindService.stop();
break;
//解绑定操作
case R.id.unbind:
unbindService(conn);
myBindService = null;
break;
}
}
}
对了,今天遇到了一个问题,在Activity绑定Service的操作可以在Activity的onCreate方法中直接进行,但是如果想要在Activity中播放音乐的话,不能把上面的myBindService.play();写在onCreate或者onResume中。
源码