zoukankan      html  css  js  c++  java
  • Service绑定模式

     Service绑定模式
         使用绑定的Service能够实现组件与Service的通信。


         组件与被绑定的Service能够不归属于同一个应用程序。因此通过绑定Service能够实现进程间通信。
         调用bindService(Intent service,ServiceConnectionconn,int flags)方法就可以实现当前组件与Service的绑定。
     參数说明
         Intent service:配置被激活的Service组件,该Intent能够是显式的,也能够是隐式的;
         ServiceConnection conn:当前组件与被激活的Service的连接对象,当成功的以绑定模式激活Service后,该
         Service的onBlind()方法的返回值(非null)对象被回传到当前组件,即当前组件与被激活的Service存在同样的IBinder对象;


     关于Service的onBind()方法
           在绑定Service时,定义的Service类中,onBind()方法应该返回一个非null的值。
    onBind()方法的返回值类型是IBinder类型。IBinder是接口。开发者能够自定义类实现该接口
    Google官方并不推荐开发者直接定义类实现IBinder接口,而是通过继承Binder类就可以,Binder类是
    IBinder接口的实现类
    假设onBind()方法的返回值是null,则该绑定过程是失败的,虽然Service也会运行onCreate()方法開始工作。
    但其它的组件无法与Service通信。


            实现Activity绑定Service的开发过程例如以下:
         创建Activity类继承android.app.Service类。并在AndroidMainfest.xml中注冊该Service;
         在自己定义的Service类中创建IBinder的对象,作为onBind()方法的返回值;
         在Activity中创建ServiceConnection的对象。
         在Activity中调用bindService()方法实现与Service的绑定;
         重写Activity的onDestroy()方法,调用unbindService()方法取消与Service的绑定,以避免
         当Activity被销毁时绑定仍然存在而导致的异常。
       取消绑定
            当与Service绑定的组件被销毁时,应该及时取消与Service的绑定。否则会导致异常。
    在组件中。调用unbindService(ServiceConnection conn)方法则能够取消与Service的绑定。
    Service的生命周期
                   ServiceConnection的onServiceDisconnected()方法并不会随着组件取消与Service的绑定而
          回调,该方法仅在Service在意外情况下崩溃时被调用。
          普通情况下,onRebind()方法并不会被回调,被回调的情景通常为:
              与该Service的全部组件都已经取消与它的绑定,导致该Service的onUnbind()方法被回调,
      且重写了onUnbind()方法返回值为true;
      该Service没有被销毁且再次被绑定时,则被回调onRebind()方法;
                   
               注意:以绑定模式激活的Service租价那并非粘性的,且与Service绑定的组件在退出之前必须取消绑定
      ,即无法保证Service依旧存在。所以。为了保证其他组件能够销毁,但Service依旧存在。能够:
               1、先调用startService()激活Service组件;
       2、再调用bindService()实现绑定。
    实现Activity与Service的通信
                     已知:在Service中。onBind()方法的返回值能够被Activity获得,即Activity与Service共同拥有一个IBinder类型的对象;
    结论:开发者能够在Service中自己定义IBinder的实现类。并在该类中定义若干个方法,当Activity获得该实现类
    的对象时,就可以调用这些方法。
       矛盾:IBinder的实现类的相关业务可能与Activity发送的Intent、service的生命周期等存在密切关系,
       使用Service的内部类则无法让Activity知晓该实现类的数据库类型。


       解决方法:使用接口定义Activity须要让Service完毕的方法。




      绑定Service时,接口的作用为:
             约定一种数据类型,让组件与Service均可使用这样的类型的数据;
    约定组件与Service通信的标准。以使得组件能够调用相关的方法;
    绑定Service的音乐播放器
               在Activity中加入2个button,分别表示“播放”与“暂停”。
      歌曲的播放与暂停功能由Service实现;
    关于MediaPlayer暂停
         通过MediaPlayer的isPlaying()方法的布尔类型返回值可知晓是否正在播放(假设没有在播放,则不许须要暂停);
         通过MediaPlayer的getCurrentPositon()方法可知晓当前的播放进度;
         通过MediaPlayer的seekTo()方法可快进到指定位置在播放。

      

    案例:

          布局:

             

    <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"
         >
    
        <ImageButton
            android:id="@+id/pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/play"
            android:layout_marginLeft="58dp"
            android:onClick="pause"
            android:layout_toRightOf="@+id/play"
            android:src="@android:drawable/ic_media_pause" />
    
        <ImageButton
            android:id="@+id/play"
            android:onClick="play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="61dp"
            android:layout_marginTop="68dp"
            android:src="@android:drawable/ic_media_play" />
    
    </RelativeLayout>
    
    MainActivity,

          

    package com.example.music_service;
    
    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.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    
    public class MainActivity extends Activity {
    	private ServiceConnection conn;
    	private Player player;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		conn = new InnerServiceConnection();
    		int flags = BIND_AUTO_CREATE;
    		Intent service = new Intent(this,PlayService.class);
    		bindService(service, conn, flags);
    	}
    	public void pause(View view){
    		player.playMusic();
    	}
    	public void play(View view){
    		player.pauseMusic();
    	}
    	private class InnerServiceConnection implements ServiceConnection{
    
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    			// TODO Auto-generated method stub
    			player = (Player) service;
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
    		
    	}
    	protected void onDestroy(){
    		unbindService(conn);
    		super.onDestroy();
    	}
    	
    }
    
    Service:

    package com.example.music_service;
    
    import java.io.IOException;
    
    import android.app.Service;
    import android.content.Intent;
    import android.media.MediaPlayer;
    import android.os.Binder;
    import android.os.Environment;
    import android.os.IBinder;
    
    public class PlayService extends Service{
        private MediaPlayer player;
        private int Current;
        @Override
        public void onCreate() {
        	// TODO Auto-generated method stub
        	player = new MediaPlayer();
        	player.setOnPreparedListener(new InnerPreparedListener());
            player.setOnCompletionListener(new InnerCompletionListener());
        }
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		return new InnerBinder();
    	}
    	public class InnerBinder extends Binder implements Player{
    
    		@Override
    		public void playMusic() {
    			// TODO Auto-generated method stub
    			play();
    		}
    
    		@Override
    		public void pauseMusic() {
    			pause();
    			// TODO Auto-generated method stub
    		}
    		
    		
    	}
    	private void play(){
    		
    		try {
    			 player.reset();
    			 player.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/Groove Coverage - She.mp3");
    			 player.prepareAsync();
    //			 player.start();
    		} catch (IllegalArgumentException e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}catch(SecurityException e){
    			e.printStackTrace();
    		}
            catch(IllegalStateException  e){
    			e.printStackTrace();
    		}
            catch(IOException  e){
    				e.printStackTrace();
    			}
    	}
    	private void pause(){
    		if(player.isPlaying()){
    			Current = player.getCurrentPosition();
    			player.pause();
    		}
    	}
    	
    	private class InnerPreparedListener implements MediaPlayer.OnPreparedListener{
    
    		@Override
    		public void onPrepared(MediaPlayer mp) {
    			// TODO Auto-generated method stub
    			mp.seekTo(Current);
    			mp.start();
    			Current = 0;
    		}
    		
    	}
    	private class InnerCompletionListener implements MediaPlayer.OnCompletionListener{
    
    		@Override
    		public void onCompletion(MediaPlayer mp) {
    			// TODO Auto-generated method stub
    			play();
    		}
    		
    	}
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		player.release();
    		player = null;
    		super.onDestroy();
    	}
    
    }
    

    接口:

            

    package com.example.music_service;
    
    public interface Player {
           void playMusic();
           void pauseMusic();
    }
    
    OK,对了,service不要忘了在AndroidMainfest.xml中配置一下

  • 相关阅读:
    浅谈3次登录错误
    JDK一键安装,配置环境
    火炬之光2_辅助工具 内存读写相关
    学习资料
    如何在google colab加载kaggle数据
    Trie树
    日常
    Kmeans
    【leet-code】135. 加油站
    Mac CLion下OpenGL环境配置
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6964364.html
Copyright © 2011-2022 走看看