• Android学习总结(四)—— Activity和 Service进行通信


    一.Activity 和 Service进行通信的基本概念

         前面我们学习我生命周期里面包含了启动和停止服务的方法,虽然服务器在活动里启动,但在启动了服务之后,活动与服务基本就没有什么关系了。我们在活动里调用了startService()方法来启动Service这个服务,然后Service的onCreate()和onStartCommaned()方法就会得到执行.之后服务会一直运行状态,但具体运行的是什么逻辑,活动就控制不了咯,这就类似于活动通知了服务一下,“你可以启动了”,然后服务就去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成的如何......很多人就会问有没有什么办法能让活动和服务的关系更紧密一些呢? 比如在活动中指挥服务去干什么,服务就会去干什么。当然可以了,这时候就需要用到onBind()方法。

    二.验证BindService启动Service的顺序:

          在写代码前首先去了解一些东西先,Context的bindService方法如下:

          ServiceConnection对象:监听访问者与Service间的连接情况,如果成功连接,回调 onServiceConnected(),如果异常终止或者其他原因终止导致Service与访问者断开 连接则回调onServiceDisconnected方法,调用unBindService()不会调用该方法!

          onServiceConnected方法中有一个IBinder对象,该对象即可实现与被绑定Service 之间的通信!我们再开发Service类时,默认需要实现IBinder onBind()方法,该方法返回的 IBinder对象会传到ServiceConnection对象中的onServiceConnected的参数,我们就可以 在这里通过这个IBinder与Service进行通信!

         总结:

    1. 在自定义的Service中继承Binder,实现自己的IBinder对象 
    2. 通过onBind( )方法返回自己的IBinder对象
    3. 在绑定该Service的类中定义一个ServiceConnection对象,重写两个方法, onServiceConnected和onDisconnected!然后直接读取IBinder传递过来的参数即可!

    三.代码之旅

       OK!接下来就是写代码验证了,这里的话我们定义一个用来计数的Service, 然后来演示BindService的用法以及方法调用流程!

    package com.nyl.bindservice;  
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
    
    
    public class TestService extends Service{
    
        private static String TAG = TestService.class.getSimpleName();
        private int count;
        private boolean quit;
    
        //定义onBinder方法所返回的对象
        private MyBinder binder = new MyBinder();
    
        public class MyBinder extends Binder{
            public int getCount(){
                return count;
            }
        }
    
        //必须实现的方法,绑定该Service是回调该方法
        @Override
        public IBinder onBind(Intent intent) {
            Log.i(TAG,"onBind方法被回调!");
            return binder;
        }
    
        //Service被创建时回调
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i(TAG,"onCreate被回调");
            //创建一个线程动态的修改count的值
           new Thread(new Runnable() {
               @Override
               public void run() {
                   while (!quit){
                       try {
                           Thread.sleep(2000);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                       count++;
                   }
               }
           }).start();
        }
    
        //Service断开连接时回调
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i(TAG,"onUnbind方法被调用");
            return true;
        }
    
        //service被关闭前回调
        @Override
        public void onDestroy() {
            super.onDestroy();
            this.quit = true;
            Log.i(TAG,"onDestroy方法被调用");
        }
    
        @Override
        public void onRebind(Intent intent) {
            Log.i(TAG,"onRebind方法被调用");
            super.onRebind(intent);
        }
    }

       在AndroidManifest.xml中对Service组件进行注册:

      当一个活动和服务绑定之后,就可以调用该服务里的Binder提供的方法了,我们可以写一个MainActivity测试一下,代码如下:

    package com.nyl.bindservice;
    
    import android.app.Activity;
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements View.OnClickListener {
    
        private Button btnLockService;
        private Button btnUnLockService;
        private Button btnGetService;
    
        final Intent intent = new Intent();
    
        //保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象
        TestService.MyBinder binder;
    
        private ServiceConnection conn = new ServiceConnection() {
    
            //Activity与Service连接成功回调该方法
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                System.out.println("连接服务");
                binder = (TestService.MyBinder) iBinder;
            }
    
            //Activity与Service断开连接时回调该方法
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                System.out.println("不连接服务");
            }
        };
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView(); //初始化控件
        }
    
        private void initView() {
            btnLockService = (Button) findViewById(R.id.btnLockService);
            btnUnLockService = (Button) findViewById(R.id.btnUnLockService);
            btnGetService = (Button) findViewById(R.id.btnGetService);
    
            intent.setAction("com.nyl.bindservice.TestService");
            intent.setPackage(getPackageName());
    
            btnLockService.setOnClickListener(this);
            btnUnLockService.setOnClickListener(this);
            btnGetService.setOnClickListener(this);
    
        }
    
        @Override
        public void onClick(View view) {
            if (view.getId() == R.id.btnLockService){
                //绑定service
                bindService(intent,conn, Service.BIND_AUTO_CREATE);
            }
            if (view.getId() == R.id.btnUnLockService){
                if(conn!=null){
                    //解除service的绑定
                    unbindService(conn);
                }
            }
            if (view.getId() == R.id.btnGetService){
                Toast.makeText(getApplicationContext(),"Service的count的值为:" + binder.getCount(),Toast.LENGTH_SHORT).show();
            }
        }
    }

      注:有些时候我们使用Service的时需要采用隐私启动的方式,但是Android 5.0一出来后,其中有个特性就是Service Intent must be explitict,也就是说从Lollipop开始,service服务必须采用显示方式启动。解决方法:设置Intent的Action和packageName(intent.setPackage(getPackageName());

      运行MainActivity,如下图所示:

      

      点击锁定Service和解除锁定,运行结果如下图:

      点击获取Service状态按钮,如下图:

      

      关于Activity和 Service进行通信的内容就介绍这么多,文章如果有写得不对的地方,欢迎广大园友指正!

  • 相关阅读:
    基于数组的完全二叉树
    二叉树链式存储
    小程序-启动-问题1
    小程序----textarea层叠问题
    小程序中某个页面生成二维码,并下载二维码图片
    vue项目启动后自动在浏览器打开
    给卡片加角标
    布局图片和文字垂直对齐
    小程序npm包管理
    从浏览器输入域名到加载完页面的流程
  • 原文地址:https://www.cnblogs.com/nylcy/p/6504939.html
Copyright © 2020-2023  润新知