概述:
其实一开始我也不没有认真想过当我们在我们的Android程序中添加背景音乐时,这项功能应该怎么实现。只是傻乎乎地在Activity中添加这项功能,并且并不认为自己这样写会有什么问题。
思路分析:
可是,我们是否想过这样一个问题:如果我们添加的音乐播放器的这个Activity异常关闭或是我们人为关闭时,我们的音乐播放还是否能够继续呢?
答案肯定是不能的。我们的Activity都关闭了,那基于这个Activity的功能又怎么可能还能继续呢?那你可能会问:那我们应该怎么去实现这个功能呢?有人可能会想到,那我就去重新new一个线程,不就好了吗?我只能说这个想法很好,不过这个是行不通的。原因可能是你现在new的这个线程是作为UI线程一个子线程,当父线程都停止工作了,子线程又怎么还会苟活!
其实,我们不要忘了,Android的四大组件中,有一个Service。它的功能类似于Activity,只是Service是在后台工作,不出现在用户的视野中。当我们在前台上进行一个人机交互操作,让这个操作关联到Service上,这样,我们就能够解决之前我们遇到的那个问题了。
Service中也有一个onCreate()的回调方法,当我们的Service被创建时就会回调这个方法。我们可以在Service被创建时,启动背景音乐。Service中也有一个onDestroy()的回调方法,当我们的Service被关闭之前会回调这个方法。这样,我们就可以在onDestroy()这个方法里,写关闭背景音乐的代码。下面我给出这个程序的前台和后台的关键代码。
前台程序:
public class MusicActivity extends Activity { Button open, close, getTime; // 保持所启动的Service的IBinder对象 MusicService.MyBinder binder; // 定义一个ServiceConnection对象 private ServiceConnection conn = new ServiceConnection() { // 当该Activity与Service连接成功时回调该方法 @Override public void onServiceConnected(ComponentName name , IBinder service) { System.out.println("--Service Connected--"); // 获取Service的onBind方法所返回的MyBinder对象 binder = (MusicService.MyBinder) service; } // 当该Activity与Service断开连接时回调该方法 @Override public void onServiceDisconnected(ComponentName name) { System.out.println("--Service Disconnected--"); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 获取程序界面中的start、stop、<span style="font-family: Arial, Helvetica, sans-serif;">getTime</span><span style="font-family: Arial, Helvetica, sans-serif;">按钮</span> open = (Button) findViewById(R.id.bind); close = (Button) findViewById(R.id.unbind); getTime = (Button) findViewById(R.id.getServiceStatus); // 创建启动Service的Intent final Intent intent = new Intent(); // 为Intent设置Action属性 intent.setAction("com.music.service.BIND_SERVICE"); open.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { // 绑定指定Serivce bindService(intent, conn, Service.BIND_AUTO_CREATE); } }); close.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { // 解除绑定Serivce unbindService(conn); } }); getTime.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { // 获取、并显示Service的count值 Toast.makeText(MusicActivity.this, "Serivce的count值为:" + binder.getCount(), Toast.LENGTH_SHORT).show(); //② } }); } }
后台程序:
public class MusicService extends Service { private int count; private boolean close; MediaPlayer m_PlayMid = null; // 定义onBinder方法所返回的对象 private MyBinder binder = new MyBinder(); // 通过继承Binder来实现IBinder类 public class MyBinder extends Binder //① { public int getCount() { // 获取Service的运行状态:count return count; } } // 必须实现的方法,绑定该Service时回调该方法 @Override public IBinder onBind(Intent intent) { System.out.println("Service is Binded"); // 返回IBinder对象 return binder; } // Service被创建时回调该方法。 @Override public void onCreate() { super.onCreate(); System.out.println("Service is Created"); m_PlayMid = MediaPlayer.create(this, R.raw.just_the_way_you_are); m_PlayMid.setLooping(true); // 启动一条线程、动态地修改count状态值 new Thread() { @Override public void run() { while (!close) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; m_PlayMid.start(); } } }.start(); } // Service被断开连接时回调该方法 @Override public boolean onUnbind(Intent intent) { System.out.println("Service is Unbinded"); return true; } // Service被关闭之前回调该方法。 @Override public void onDestroy() { super.onDestroy(); this.close = true; m_PlayMid.stop(); System.out.println("Service is Destroyed"); } }
源代码分享:
下面是我的Demo源码地址:用Service来启动背景音乐