onBind方法
在Android中写Service
时总有一个onBind
方法, 默认情况下返回null
, 在最新的Android Studio中是抛出一个异常.
之所以有这个方法, 是因为在Activity
中启动Service
之后, 他俩就没有联系了, 这个方法可以让我们给Service
发消息, 让其执行相关的操作.
写作原因
最近看书看到了Service
部分, 里面恰好讲到了onBind
. 我突然想起来在UC实习的时候有做过一个app, 里面有个需求是在后台播放音乐, 我记得当时也是用onBind
返回的对象操作Service
控制MediaPlayer
. 不同的地方在于, 我当时使用了AIDL, 而我正在看的这本书没有用这个.
当时用AIDL完成那个控制后台播放音乐的功能没有遇到多少困难, 唯独感觉这种实现方法太麻烦了, 有点不科学. 现在看了这本书才发现好像我做了一件大炮打蚊子的事情.
查了一下AIDL, 那是给IPC准备的, 如果需要把自己的服务暴露给其他的app调用, 就需要用AIDL. 我这边自己控制自己的服务, 根本不需要IPC, 是我自己弄麻烦了.
后台播放音乐
这次的例子是后台播放音乐, 需要在服务中完成对MediaPlayer
的所有控制, 所以需要使用到onBind
方法.
关于MediaPlayer
, 有个很复杂的状态图, 如果要控制它就一定要看官方文档, 这不是本文的主要目标, 所以我不涉及这方面内容, 仅仅演示一下如何使用onBind
.
Service实现
创建一个继承自Service
的MusicPlayer
, 然后在里面再定义一个继承自Binder
的PlayerBinder
类. 注意设为public, 然后还需要声明一个类型为PlayerBinder
的成员变量mBinder
, 可以在onCreate
中实例化, 这就是我们要在onBind
中返回的东西. PlayerBinder
类中的方法就是我们可以控制MusicPlayer
执行的方法.
public class MusicPlayer extends Service implements MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
private PlayerBinder mBinder;
private MediaPlayer mMediaPlayer = null;
public MusicPlayer() {
}
@Override
public void onCreate() {
super.onCreate();
mBinder = new PlayerBinder();
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer.setOnPreparedListener(this);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return true;
}
@Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
public class PlayerBinder extends Binder {
public void play() {
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(getAssets().openFd("roadsuntraveled.mp3").getFileDescriptor());
mMediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
}
public void resume() {
if (!mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
}
}
public void stop() {
mMediaPlayer.stop();
}
public void release() {
mMediaPlayer.release();
}
}
}
我在src/main/assets下放了一个叫roadsuntraveled.mp3的文件, 这是我们播放的本地音频. 如果使用eclipse, 那么就放在assets/目录下.
注意如果照搬这个代码, 还需要在AndroidManifest.xml中添加<service>
和<uses-permission android:name="android.permission.WAKE_LOCK" />
Activity
在Activity
中除了一些控制用的控件之外, 最主要的是一个类型为MusicPlayer.PlayerBinder
的成员变量, 和一个类型为ServiceConnection
的成员变量.
其中ServiceConnection
在启动服务时传入, 在它的方法中我们获取Binder
, 并赋值给mPlayerBinder
. 注意启动服务是调用bindService
.
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private MusicPlayer.PlayerBinder mPlayerBinder;
private Button start;
private Button resume;
private Button pause;
private Button stop;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPlayerBinder = (MusicPlayer.PlayerBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.start);
resume = (Button) findViewById(R.id.resume);
pause = (Button) findViewById(R.id.pause);
stop = (Button) findViewById(R.id.stop);
start.setOnClickListener(this);
resume.setOnClickListener(this);
pause.setOnClickListener(this);
stop.setOnClickListener(this);
Intent serviceIntent = new Intent(this, MusicPlayer.class);
bindService(serviceIntent, mConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPlayerBinder.release();
unbindService(mConnection);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
mPlayerBinder.play();
break;
case R.id.resume:
mPlayerBinder.resume();
break;
case R.id.pause:
mPlayerBinder.pause();
break;
case R.id.stop:
mPlayerBinder.stop();
break;
default:
break;
}
}
}
随后我们通过mPlayerBinder
就可以完成对Service
的控制了. 可以通过四个按钮控制音频的播放, 暂停等.
最后不要忘了unBindService
.
另外本人还开设了个人公众号:JiandaoStudio ,会在公众号内定期发布行业信息,以及各类免费代码、书籍、大师课程资源。
扫码关注本人微信公众号,有惊喜奥!公众号每天定时发送精致文章!回复关键词可获得海量各类编程开发学习资料!
例如:想获得Python入门至精通学习资料,请回复关键词Python即可。