用绑定服务来实现放歌的功能
绑定服务—与调用者同生死的服务
简单来讲相比于普通service,绑定服务就显得专情多了。。先来一个布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.musicplayer.MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/text_tv"
android:layout_centerHorizontal="true"
android:onClick="bind"
android:layout_marginTop="63dp"
android:text="绑定" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="26dp"
android:onClick="unbind"
android:text="解除绑定" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button2"
android:layout_below="@+id/button2"
android:layout_marginTop="23dp"
android:onClick="playmusic"
android:text="播放音乐" />
<Button
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button3"
android:layout_below="@+id/button3"
android:layout_marginTop="28dp"
android:onClick="stopmusic"
android:text="停止音乐" />
<TextView
android:id="@+id/text_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="64dp"
android:text="界面" />
</RelativeLayout>
MainActivity的代码如下
public class MainActivity extends Activity {
// private MyBinder myBinder;//声明服务的代理对象
private MyBinder myBinder;
private boolean bindFlag=false;
private static final String TAG = "BindActivity";
private ServiceConnection conn=new ServiceConnection() {
//当调用者与服务连接不成功,则回调该方法, 当连接出现异常会回调该方法,假如调用者自己实现的解绑操作,则不会回调该方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG,"onServiceDisconnected");
bindFlag=false;
}
/**当调用者与服务连接成功,则回调该方法
* ComponentName: 调用者的组件名
* IBinder: 实现了IBinder接口的对象 ,当要绑定的服务成功回调onBind()方法,则表示绑定成功,即onBind的返回值作为该方法的输入参数
* 通过该IBinder参数来获取服务的实例或者是代理对象
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.v(TAG,"onServiceConnected");
myBinder=(MyBinder) service; //获取代理对象
// myBinder=(IService) service; //获取代理对象
bindFlag=true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Log.v(TAG,"onCreate");
}
//绑定服务
public void bind(View v){
Log.v(TAG,"bind");
Intent intent=new Intent(this, BindMusic.class);
/**绑定服务
* Intent :要绑定的服务的意图描述
* ServiceConnection : 服务连接接口, 调用者和服务 通过这个接口实现通信的,即是调用者与被调用者的桥梁
* 通过这个接口,可以获取服务的实例或者服务的代理对象
* BIND_AUTO_CREATE: 绑定自动创建
*/
this.bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
//解绑服务
public void unbind(View v){
Log.v(TAG,"unbind");
this.unbindService(conn);
bindFlag=false;
// conn=null;
}
//播放音乐
public void playmusic(View v){
Log.v(TAG,"playMusic");
if(myBinder!=null){
myBinder.playMusic();
}
}
//停止音乐
public void stopmusic(View v){
Log.v(TAG,"stopMusic");
if(myBinder!=null){
myBinder.stopMusic();
}
}
@Override
protected void onDestroy() {
// if(conn!=null){
// unbindService(conn);
// }
if(bindFlag){
this.unbindService(conn);
}
super.onDestroy();
}
}
绑定服务的代码
public class BindMusic extends Service {
private static final String TAG = "BindMusic";
private MediaPlayer player;
// 返回Ibinder对象(把服务的实例或者代理的对象通过Ibinder返回给调用者)
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.v(TAG, "onBind");
return new MyBinder();
}
public void closeMusic() {
// TODO Auto-generated method stub
if (player != null) {
player.stop();
player.release();
player = null;
}
}
public void startMusic() {
// TODO Auto-generated method stub
if (player == null) {
player = new MediaPlayer();
try {
player.setDataSource(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath()
+ "/imissyou.mp3");
player.prepare();// 缓冲
} catch (Exception e) {
// TODO: handle exception
}
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.v(TAG, "oncreat");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.v(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.v(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.v(TAG, "onDestroy");
if (player != null) {
player.stop();
player.release();// 释放资源
player = null;
}
super.onDestroy();
}
// 返回服务的代理类 ,通过该代理来对外暴露服务的相应方法
public class MyBinder extends Binder {
private static final String TAG = "MyBinder";
// 对外暴露 播放音乐的方法
public void playMusic() {
Log.v(TAG, "playMusic+IService");
startMusic();
}
// 对外暴露停止音乐的方法
public void stopMusic() {
Log.v(TAG, "stopMusic+IService");
closeMusic();
}
}
}
注意要在配置文件中注册绑定服务
<service android:name=".BindMusic">
</service>
面向接口的代理的实现
先定义两个接口Iservice和Iservice2
public interface Iservice {
public void playMusic();
public void stopMusic() ;
}
public interface Iservice2 {
public void playMusic();
public void stopMusic() ;
public void psuseMusic();
}
内部类实现接口的方法
public class MyBinder extends Binder implements Iservice{
private static final String TAG = "MyBinder";
// 对外暴露 播放音乐的方法
public void playMusic() {
Log.v(TAG, "playMusic+IService");
startMusic();
}
// 对外暴露停止音乐的方法
public void stopMusic() {
Log.v(TAG, "stopMusic+IService");
closeMusic();
}
}
效果如下
我们来看打印信息