android service 的简单实例 binder service

Service 这个一搜一大把详细的介绍,这里就不多说了。 实质就是一种不用和用户交互,在后台运行的一种 服务。

Service 分为 绑定的 和  不绑定的。

不绑定的:简单说:就是当你启动service后,不去主动的 StopService() 它 或者 不在service中调用  stopSelf() 是不会停止的。

绑定的:简单说:当你的绑定组件 启动service后,组件解除 绑定,那么service就会销毁,当然允许多个组件绑定,直到没有组件绑定到service的时候,它就会销毁了。

下来看例子。不绑定的 我注释的代码写的很清楚,那个很简单。主要说下 绑定的service,界面就是由2个按钮  1个是绑定,1个是解除绑定。


MainActivity.java 界面

public class MainActivity extends Activity {

	//用来绑定链接的
	private ServiceConnection conn;
	//判断是否已绑定
	public boolean isBind = false;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
              //当 service启动后,再次启动 service,不会调用oncreate方法了,而是直接调用onStartCommand 方法

		/**
		 * 1.
		 * 平常简单的启动service的方法  startService 
		 *          停止serviced的方法 stopService 
		 * 这个的特点就是 没有绑定service,当启动service的这个activity消失后,service仍然存在,
		 * 想要停止 service 必须手动 stop
		 * 
		 * //startService(new Intent())
		 * //stopService(name)
		 */
		
		
		/**
		 * 2. 绑定的(同一进程中)
		 */
		conn = new ServiceConnection(){
			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {

				 // 当绑定时 会从这个回调接口得到  binder对象   通过binder对象绑定的
				 MainBinService.BinServiceBind sBinder = (MainBinService.BinServiceBind)service;
				 //  然后使用 binder对象的方法
				 System.out.println( "11 + 11 = " + sBinder.add(11,11));
                 System.out.println("sBinder.getService().toString()"+ sBinder.getBinServiceBind().toString());
			}

			@Override
			public void onServiceDisconnected(ComponentName name) {
				
			}
		};

		
		//启动绑定button
		((Button)this.findViewById(R.id.button1)).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				
				 //BIND_DEBUG_UNBIND 这个flag 用于调试       BIND_AUTO_CREATE 默认使用的
			      MainActivity.this.bindService(new Intent(MainActivity.this, MainBinService.class), 
			    		  conn, 
			    		  Context.BIND_AUTO_CREATE);//这个flag 默认使用
			      
                  isBind = true;
				
				
			}
		});
		
		
		
		//解除绑定 button
		((Button)this.findViewById(R.id.button2)).setOnClickListener(new View.OnClickListener(){
			@Override
			public void onClick(View v) {
				  if(isBind){
					 // 多次调用 unbindService 会抛出异常
					  MainActivity.this.unbindService(conn);
				  }
			}
		});
	}


Service.java

public class MainBinService  extends Service{
	/**
	 *	android:process  ----------  表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字
	 *	android:enabled  ----------  如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false
	 *	android:exported  ---------  表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
	 */
	
	private  BinServiceBind myBind;
	//bind
	public class BinServiceBind extends Binder{	
		public MainBinService getBinServiceBind(){		
			return MainBinService.this;
		}

		public int add(int a,int b){			
			return a+b;
		}

	}
	
	// 返回binder 对象  
	@Override
	public IBinder onBind(Intent arg0) {
		return myBind;
	}
	
	
     @Override
    public void onCreate() {
    	super.onCreate();
    	System.out.println(" SERVCEI  oncreate =  ");
    	myBind = new BinServiceBind();
    }
	
     
     @Override  
     public boolean onUnbind(Intent intent) {  
         // 所有的客户端使用unbindService()解除了绑定   
         return false;  
     }  
     @Override  
     public void onRebind(Intent intent) {  
         // 一个客户端在调用onUnbind()之后,正使用bindService()绑定到service  
     }  
     
     @Override
    public void onDestroy() {
    	System.out.println(" service destory");
    	super.onDestroy();
    }
     
     
    /**
     * 注意方法onStartCommand()必须返回一个整数.这个整数描述了在系统杀死它的事件中系统如何继续这个服务
     * onStartCommand()返回值必须是下面常量之一:

       START_NOT_STICKY

           如果系统在onStartCommand()返回后杀死了服务,不要重新创建这个service,除非还有挂起的intent需要被传送.
                  这是避免在不必要时运行你的service和当你的应用可以简单重启任何未竟的工作时的最佳选择.

       START_STICKY

          如果系统在onStartCommand()返回后杀死了这个service,会重新创建这个service并且调用onStartCommand(),但是不再重新发送上次最后一个intent,
                  而是使用一个nullintent调用onStartCommand(),除非有一些挂起的intent,在此情况下,这些挂起的intent被派送.这适合于媒体播放器(or或相似也的服务),
                  它不执行命令,但是无限期的运行并等待一个工作.

       START_REDELIVER_INTENT

          如果系统在onStartCommand()返回后杀死了service,重新创建这个service并且使用上次最后一个intent调用onStartCommand().
                 任何挂起的intent都顺序地被派送.这适合于活跃地执行一个工作并且应被立即恢复的服务,比如下载一个文件.
     */
     
     
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    	return super.onStartCommand(intent, flags, startId);
    }
}

当我点击activity 中的绑定按钮时(看到service oncreate 并且进入回调方法):


当点击activity中的解除绑定按钮时(进入到了service  desroty 方法),

二,现在要实现 activity 和service间的相互通信



(xml 太过简单就不贴了,代码自己考过去画几个button 就可以测了呢 )当我点击 通信按钮。

           


上面第一张是,我点击通讯按钮后,进入到了service, 第2张是 service 处理完自己的事后(3秒后),给activity 返回的1个信息,并在activity中显示toast


要用到 Messenger(信使)     注释非常详细了,实质就是通过Messenger 对象然后进行消息的发送。

先来  HandlerActivity.java     

public class HandlerActivity extends Activity {
    //接收service的 Messenger
    private Messenger serviceMessenger = null;
    //activity本身 的 Messenger
    private Messenger myMessenger =null ;
    boolean mBound;
    static  final  int  service_back = 1;
    
    //Handler 
    private Handler handler = new Handler(){
		   public void handleMessage(Message msg) {
			   switch (msg.what){
			        case service_back:
			        //当service 完成自己的事情后 通知activity 显示 toast
			    	Toast.makeText(getApplicationContext(), "service back ==!", Toast.LENGTH_SHORT).show();					
					break;
			     }
		   };
	   };
	    
	   
    /**
     *与service的主接口交互的类
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // 当与service的连接已经建立时被调用,获得service 返回的 Ibinder对象     	
        	serviceMessenger = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // 当与service的连接意外断开时被调用-- 也就是,service的进程崩溃了
        	serviceMessenger = null;
            mBound = false;
        }
    };

    public void doSomethings() {
        if (!mBound){
        	return;
        }
        myMessenger = new Messenger(handler); 
        // 创建并发送一个消息给service
        Message msg = Message.obtain(null, HandlerService.Hello_Service, 0, 0);
        //指明此message发送到何处的可选Messenger对象。具体的使用方法由发送者和接受者决定。
        msg.replyTo = myMessenger;
        try {
        	//将包含本身 Messenger 的 message发送出去
        	serviceMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 	     //点击 activity的 button 给 service 发送消息 让其执行
 		((Button)this.findViewById(R.id.button3)).setOnClickListener(new View.OnClickListener() {
 			@Override
 			public void onClick(View v) {
 				//调用sen message
 				doSomethings();
 			}
 		});
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 这个class 是为了测试通讯,所以启动的时候直接绑定到service
        bindService(new Intent(this, HandlerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

HandlerService.java

public class HandlerService extends Service {
    
    public  static final int Hello_Service = 1;
 
    // Handler处理
    private Handler handler =new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Hello_Service:
                	//显示toast
                    Toast.makeText(getApplicationContext(), " Hello_Service_in_handler! ", Toast.LENGTH_SHORT).show(); 
                    //得到msg  就可以用 得到的  messenger 给客户端发送数据了
                    replyMessenger = msg.replyTo;
                    //执行相应的操作
                    th.start();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

   
     //使用 信息给客户端发送消息 发送消息的的对象
     private final Messenger serviceMessenger = new Messenger(handler);
     // 得到的客户端传递过来的 Messenger(信使)
     private  Messenger  replyMessenger ;
     
    
     //做了1个假的执行操作的线程
     private  Thread th = new Thread(){
     	public void run() {
     		try {
     			Thread.sleep(3000);
 				//假设上面执行了自己操作3秒
     			//现在给客户端回应
     			Message msg = Message.obtain(null, HandlerActivity.service_back, 0,0);
     			replyMessenger.send(msg);
     			
 			} catch (RemoteException e) {
 			} catch (InterruptedException e) {
 			}
     	};
     };
    
    
    /**
     * 当绑定到service,我们返回指向我们的messenger的接口
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return serviceMessenger.getBinder();
    }
    
    
    /**
     * 当你需要执行IPC时,为你的接口使用一个Messenger比使用AIDL实现它简单,
     * 因为Messenger把所有对service的调用入队列,一个纯AIDL接口并行发送请求到service,这样就必须用多线程来处理了.
          对于大多数应用,service不需使用多线程,所以使用一个Messenger允许service在一个时刻只处理一个请求.
                  如果要使用多线程,那么就要使用到AIDL
     */
    
    
    @Override
    public void onCreate() {
    	super.onCreate();
    }
    
    
    /**   Messenger:信使
                       官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。
                        该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,
                        客户端持有这个Messenger就可以与服务端通信了。
     * 
     *   以前我们使用Handler+Message的方式进行通信,都是在同一个进程中,从线程持有一个主线程的Handler对象,并向主线程发送消息。
		 而Android既然可以使用bindler机制进行跨进行通信,所以我们当然可以将Handler与bindler结合起来进行跨进程发送消息。
		 查看API就可以发现,Messenger就是这种方式的实现。

     */
    
    
    
}

好了这个有点长了 AIDL的通信下个说 = =,




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空白的泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值