zoukankan      html  css  js  c++  java
  • Service

    Service

    Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它没有用户界面,所以绝不会到前台来。一旦Service被启动起来之后,它就与Activity一样。它完全具有自己的生命周期。关于程序中Activity与Service的选择标准是:如果某个程序组件需要在运行时向用户呈现某种界面,或者该程序需要与用户交互,就需要使用Activity,否则就应该考虑使用Service了。

    开发者开发Service的步骤与开发Activity的步骤很像,开发Service组件需要先开发一个Service的子类,然后在AndroidManifest.xml文件中配置该Service,配置时可通过

    Service简介

    Service组件也是可执行的程序,它也有自己的生命周期。创建、配置Service与创建、配置Activity的过程基本相似。

    创建、配置Service

    就像开发Activity需要两个步骤,开发Service也需要两个步骤:

    1. 定义一个继承Service的子类。
    2. 在AndroidManifest.xml文件中配置该Service。

    Service与Activity还有一点相似之处,它们都是从Context派生出来的,因此它们都可调用Context里定义的如getResources()、getContentResolver()等方法。

    与Activity相似的是,Service中也定义了系列生命周期方法,如下所示。

    • abstract IBinder onBind(Intent intent):该方法是Service子类必须实现的方法。该方法返回一个IBinder对象,应用程序可通过该对象与Service组件通信。
    • void onCreate():当该Service第一次被创建后将立即回调该方法。
    • void onDestroy():当该Service被关闭之前将会回调该方法。
    • void onStartCommand(Intent intent, int flags, int startId):该方法的早期版本是void onStart(Intent intent, int startId),每次客户端调用startService(Intent)方法启动该Service时都会回调该方法。
    • boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。

    下面的类定义了第一个Service组件。

    public class FirstService extends Service {
        public FirstService() {
        }
    
        // 必须实现的方法
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        // Service被创建时回调该方法
        @Override
        public void onCreate() {
            super.onCreate();
            System.out.println("Service is Created");
        }
    
        // Service被启动时回调该方法
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            System.out.println("Service is Started");
            return START_STICKY;
        }
    
        // Service被关闭之前回调
        @Override
        public void onDestroy() {
            super.onDestroy();
            System.out.println("Service is Destroyed");
        }
    }

    定义了上面的Service之后,接下来需要在AndroidManifest.xml文件中配置该Service,配置Service使用

    <!-- 配置一个Service组件 -->
    <service android:name=".FirstService">
        <intent-filter>
            <!-- 为该Service组件的intent-filter配置action -->
            <action android:name="tk.zongzhankui.firstservice.FIRST_SERVICE">
        </intent-filter>
    </service>
    

    从上面的配置片段不难看出,配置Service与配置Activity的差别并不大,只是配置Service使用

    启动和停止Service

    下面的程序使用Activity作为Service的访问者,该Activity的界面中包含两个按钮,一个按钮用于启动Service,一个按钮用于关闭Service。

    该Activity的代码如下。

    public class MainActivity extends Activity {
        Button start, stop;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            start = (Button) findViewById(R.id.start);
            stop = (Button) findViewById(R.id.stop);
    
            // 创建启动Service的Intent
            final Intent intent = new Intent();
            intent.setAction("tk.zongzhankui.firstservice.FIRST_SERVICE");
            start.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    startService(intent);
                }
            });
            stop.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    stopService(intent);
                }
            });
        }
    
    }

    示例代码下载

    每当Service被创建时会回调onCreate方法,每次Service被启动时都会回调onStart方法——多次启动一个已有的Service组件将不会再回调onCreate方法,但每次启动时都会回调onStart方法。

    绑定本地Service并与之通信

    当程序通过startService()和stopService()启动、关闭Service时,Service与访问者之间基本上不存在太多的关联,因此Service和访问者之间也无法进行通信、数据交换。

    如果Service和访问者之间需要进行方法调用或数据交换,则应该使用bindService()和unbindService()方法启动、关闭服务。

    Context的bindService()方法的完整方法签名为:bindService(Intent service, ServiceConnection conn, int flags),该方法的三个参数的结束如下。

    • service:该参数通过Intent指定要启动的Service。
    • conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接情况。当访问者与Service之间连接成功时将回调该ServiceConnection对象的onServiceConnected(ComponentName name, IBinder service)方法;当访问者与Service之间断开连接时将回调该ServiceConnection对象的onServiceDisconnected(ComponentName name)方法。
    • flags:指定绑定时是否自动创建Service(如果Service还未创建)。该参数可指定为0(不自动创建)或BIND_AUTO_CREATE(自动创建)。

    注意到ServiceConnection对象的onServiceConnected方法中有一个IBinder对象,该对象即可实现与被绑定Service之间的通信。

    当开发Service类时,该Service类必须提供一个IBinder onBind(Intent intent)方法,在绑定本地Servcie的情况下,onBind(Intent intent)方法所返回的IBinder对象将会传给ServiceConnection对象里onServiceConnected(ComponentName name, IBinder service)方法的service参数,这样访问者就可通过该IBinder对象与Service进行通信。

    实际上开发时通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象。

    下面的程序示范了如何在Activity中绑定本地Service,并获取Service的运行状态。该程序的Service类需要“真正”实现onBind()方法,并让该方法返回一个有效的IBinder对象,该Service类的代码如下。

    public class BindService extends Service {
        private int count;
        private boolean quit;
        // 定义onBinder方法所返回的对象
        private MyBinder binder = new MyBinder();
        // 通过继承Binder来实现IBinder类
        public class MyBinder extends Binder {
            public int getCount() {
                // 获取Service的运行状态:count
                return count;
            }
        }
    
        // 必须实现的方法
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("Service is Binded");
            // 返回IBinder对象
            return binder;
        }
    
        // Service被创建时回调该方法
        @Override
        public void onCreate() {
            super.onCreate();
            System.out.println("Service is Created");
            // 启动一条线程,动态地修改count状态值
            new Thread() {
                @Override
                public void run() {
                    while (!quit) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        count++;
                    }
                }
            }.start();
        }
    
        // Service被关闭之前回调
        @Override
        public void onDestroy() {
            super.onDestroy();
            this.quit = true;
            System.out.println("Service is Destroyed");
        }
    
        // Service被断开连接时回调该方法
        @Override
        public boolean onUnbind(Intent intent) {
            System.out.println("Service is Unbinded");
            return true;
        }
    }

    上面Service类的粗体字代码实现了onBind()方法,该方法返回了一个可访问该Service状态数据(count值)的IBinder对象,该对象将被传给该Service的访问者。

    上面程序通过继承Binder类实现了一个IBinder对象,这个MyBinder类是Service的内部类,这对于绑定本地Service并与之通信的场景是一种常见的情形。当然也可以为MyBinder类提供一个借口,或把MyBinder类定义成一个外部类的形式,这无关紧要。

    接下来定义一个Activity来绑定该Service,并在该Activity中通过MyBinder对象访问Service的内部状态。该Activity的界面上包含三个按钮,第一个按钮用于绑定Service,第二个按钮用于解除绑定;第三个按钮用于获取Service的运行状态。该Activity的代码如下。

    public class MainActivity extends Activity {
        Button bind, unbind, getServiceStatus;
        // 保持所启动的Service的IBinder对象
        BindService.MyBinder binder;
        // 定义一个ServiceConnection对象
        private ServiceConnection conn = new ServiceConnection() {
            // 当该Activity与Service连接成功时回调该方法
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                System.out.println("--Service Connected--");
                // 获取Service的onBind方法所返回的MyBinder对象
                binder = (BindService.MyBinder) service;
            }
    
            // 当该Activity与Service断开连接时回调该方法
            @Override
            public void onServiceDisconnected(ComponentName name) {
                System.out.println("--Service Disconnected--");
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            bind = (Button) findViewById(R.id.bind);
            unbind = (Button) findViewById(R.id.unbind);
            getServiceStatus = (Button) findViewById(R.id.getServiceStatus);
    
            // 创建启动Service的Intent
            final Intent intent = new Intent();
            // 为Intent设置Action属性
            intent.setAction("tk.zongzhankui.bindservice.BIND_SERVICE");
            bind.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 绑定指定Service
                    bindService(intent, conn, BindService.BIND_AUTO_CREATE);
                }
            });
            unbind.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 解除绑定Service
                    unbindService(conn);
                }
            });
            getServiceStatus.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 获取并显示Service的count值
                    Toast.makeText(MainActivity.this, "Service的count值为:"
                            + binder.getCount(), Toast.LENGTH_LONG).show();
                }
            });
        }
    
    }

    示例代码下载

    对于Service的onBind()方法所返回的IBinder对象来说,它可被当成该Service组件所返回的回调对象,Service允许客户端通过该IBinder对象来访问Service内部的数据,这样即可实现客户端与Service之间的通信。

    与多次调用startService()方法启动Service不同的是,多次调用bindService()方法并不会执行重复绑定。对于前一个实例程序,用户每单击“启动Service”按钮一次,系统就会回调Service的onStart()方法一次;对于这个实例程序,不管用户单击“绑定Service”多少次,系统只会回调Service的onBind()方法一次。

    Service的生命周期

    随着应用程序启动Service方式的不同,Service的生命周期也略有差异。

    这里写图片描述

    Service生命周期

    如果觉得本文对您有帮助,请“打赏”,谢谢。
    您的鼓励,我的动力。
    微信 支付宝
  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/zongzhankui/p/5875321.html
Copyright © 2011-2022 走看看