Android四大组件——Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务

Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务


本篇文章包括以下内容:

  • 前言
  • Service的简介
  • 后台服务
    • 不可交互的后台服务
    • 可交互的后台服务
    • 混合性交互的后台服务
  • 前台服务
  • IntentService
  • AIDL跨进程服务
  • AccessibilityService无障碍服务
  • 系统服务
  • 部分源码下载

前言

作为四大组件之一的Service类,是面试和笔试的必备关卡,我把我所学到的东西总结了一遍,相信你看了之后你会对Service娓娓道来,在以后遇到Service的问题胸有成竹,废话不多说,开车啦

Service简介

Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作

Service的运行不依赖于任何用户界面,即使程序被切换到后台或者用户打开另一个应用程序,Service仍然能够保持正常运行,这也正是Service的使用场景。当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行

后台服务

后台服务可交互性主要是体现在不同的启动服务方式,startService()和bindService()。bindService()可以返回一个代理对象,可调用Service中的方法和获取返回结果等操作,而startService()不行

不可交互的后台服务

不可交互的后台服务即是普通的Service,Service的生命周期很简单,分别为onCreate、onStartCommand、onDestroy这三个。当我们startService()的时候,首次创建Service会回调onCreate()方法,然后回调onStartCommand()方法,再次startService()的时候,就只会执行一次onStartCommand()。服务一旦开启后,我们就需要通过stopService()方法或者stopSelf()方法,就能把服务关闭,这时就会回调onDestroy()

一、创建服务类

创建一个服务非常简单,只要继承Service,并实现onBind()方法

public class BackGroupService extends Service {

    /**
     * 綁定服务时调用
     *
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("Service", "onBind");
        return null;
    }

    /**
     * 服务创建时调用
     */
    @Override
    public void onCreate() {
        Log.e("Service", "onCreate");
        super.onCreate();
    }

    /**
     * 执行startService时调用
     *
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("Service", "onStartCommand");
        //这里执行耗时操作
        new Thread() {
            @Override
            public void run() {
                while (true){
                    try {
                        Log.e("Service", "doSomething");
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 服务被销毁时调用
     */
    @Override
    public void onDestroy() {
        Log.e("Service", "onDestroy");
        super.onDestroy();
    }
}

二、配置服务

Service也是四大组件之一,所以必须在manifests中配置

<service android:name=".Service.BackGroupService"/>

三、启动服务和停止服务

我们通过两个按钮分别演示启动服务和停止服务,通过startService()开启服务,通过stopService()停止服务

public class MainActivity extends AppCompatActivity {

    Button bt_open, bt_close;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bt_open = (Button) findViewById(R.id.open);
        bt_close = (Button) findViewById(R.id.close);

        final Intent intent = new Intent(this, BackGroupService.class);

        bt_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //启动服务
                startService(intent);
            }
        });

        bt_close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //停止服务
                stopService(intent);
            }
        });
    }
}

当你开启服务后,还有一种方法可以关闭服务,在设置中,通过应用->找到自己应用->停止

四、运行代码

运行程序后,我们点击开始服务,然后一段时间后关闭服务。我们以Log信息来验证普通Service的生命周期:onCreate->onStartCommand->onDestroy

11-24 00:19:51.483 16407-16407/com.handsome.boke2 E/Service: onCreate
11-24 00:19:51.483 16407-16407/com.handsome.boke2 E/Service: onStartCommand
11-24 00:19:51.485 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:19:53.490 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:19:55.491 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:19:57.491 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:19:58.056 16407-16407/com.handsome.boke2 E/Service: onDestroy
11-24 00:19:59.492 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:20:01.494 16407-16613/com.handsome.boke2 E/Service: doSomething
11-24 00:20:03.495 16407-16613/com.handsome.boke2 E/Service: doSomething

其中你会发现我们的子线程进行的耗时操作是一直存在的,而我们Service已经被关闭了,关闭该子线程的方法需要直接通过Home键关闭该应用程序

可交互的后台服务

可交互的后台服务是指前台页面可以调用后台服务的方法,可交互的后台服务实现步骤是和不可交互的后台服务实现步骤是一样的,区别在于启动的方式和获得Service的代理对象

一、创建服务类

和普通Service不同在于这里返回一个代理对象,返回给前台进行获取,即前台可以获取该代理对象执行后台服务的方法

public class BackGroupService extends Service {

    /**
     * 綁定服务时调用
     *
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("Service", "onBind");
        //返回代理对象
        return new MyBinder();
    }

    /**
     * 代理类
     */
    class MyBinder extends Binder {
        public void showToast() {
            Log.e("Service", "showToast");
        }

        public void showList() {
            Log.e("Service", "showList");
        }
    }

    /**
     * 解除绑定服务时调用
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("Service", "onUnbind");
        return super.onUnbind(intent);
    }

    /**
     * 服务创建时调用
     */
    @Override
    public void onCreate() {
        Log.e("Service", "onCreate");
        super.onCreate();
    }

    /**
     * 服务被销毁时调用
     */
    @Override
    public void onDestroy() {
        Log.e("Service", "onDestroy");
        super.onDestroy();
    }
}

二、配置服务

<service android:name=".Service.BackGroupService"/>

三、绑定服务和解除绑定服务

我们通过两个按钮分别演示绑定服务和解除绑定服务,通过bindService()开启服务,通过unbindService()停止服务

public class MainActivity extends AppCompatActivity {

    Button bt_open, bt_close;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bt_open = (Button) findViewById(R.id.open);
        bt_close = (Button) findViewById(R.id.close);

        final Intent intent = new Intent(this, BackGroupService.class);

        bt_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService(intent, conn, BIND_AUTO_CREATE);
            }
        });

        bt_close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(conn);
            }
        });

    }

    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //拿到后台服务代理对象
            BackGroupService.MyBinder myBinder = (BackGroupService.MyBinder) service;
            //调用后台服务的方法
            myBinder.showToast();
            myBinder.showList();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}

这里和startService的区别在于多了一个ServiceConnection对象,该对象是用户绑定后台服务后,可获取后台服务代理对象的回调,我们可以通过该回调,拿到后台服务的代理对象,并调用后台服务定义的方法,也就实现了后台服务和前台的交互

四、运行代码

运行程序后,我们点击绑定服务,然后一段时间后解除绑定服务。我们以Log信息来验证Service的生命周期:onCreate->onBind->onUnBind->onDestroy,其中也可以看到我们调用后台服务的方法showToast和showList

11-24 00:55:32.775 15408-15408/com.handsome.boke2 E/Service: onCreate
11-24 00:55:32.775 15408-15408/com.handsome.boke2 E/Service: onBind
11-24 00:55:32.796 15408-15408/com.handsome.boke2 E/Service: showToast
11-24 00:55:32.796 15408-15408/com.handsome.boke2 E/Service: showList
11-24 00:55:34.290 15408-15408/com.handsome.boke2 E/Service: onUnbind
11-24 00:55:34.290 15408-15408/com.handsome.boke2 E/Service: onDestroy

混合性交互的后台服务

或许你会迷惑,startService和bindService之间有什么关系?其实简单的说两者之间是没有关联的,类似于你亲妈生了个双胞胎一样,只有纯粹的血缘关系。那么问题来了,这两个启动方式是否可以同时使用呢,答案是可以的

将上面两种启动方式结合起来就是混合性交互的后台服务了,即可以单独运行后台服务,也可以运行后台服务中提供的方法,其完整的生命周期是:onCreate->onStartCommand->onBind->onUnBind->onDestroy

前台服务

由于后台服务优先级相对比较低,当系统出现内存不足的情况下,它就有可能会被回收掉,所以前台服务就是来弥补这个缺点的,它可以一直保持运行状态而不被系统回收。例如:墨迹天气在状态栏中的天气预报

一、创建服务类

前台服务创建很简单,其实就在Service的基础上创建一个Notification,然后使用Service的startForeground()方法即可启动为前台服务

public class ForegroundService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        showNotification();
    }

    /**
     * 启动前台通知
     */
    private void showNotification() {
        //创建通知详细信息
        Notification.Builder mBuilder = new Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("2016年11月24日")
                .setContentText("今天天气阴天,8到14度");
        //创建点击跳转Intent
        Intent intent = new Intent(this, MainActivity.class);
        //创建任务栈Builder
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(intent);
        PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
        //设置跳转Intent到通知中
        mBuilder.setContentIntent(pendingIntent);
        //获取通知服务
        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //构建通知
        Notification notification = mBuilder.build();
        //显示通知
        nm.notify(0, notification);
        //启动为前台服务
        startForeground(0, notification);
    }
}

二、配置服务

<service android:name=".Service.ForegroundService"/>

三、启动前台服务

startService(new Intent(this, ForegroundService.class));

四、运行代码

我们可以看到状态栏确实增加了我们这条通知

当我们将该程序退出并杀掉的时候,通过设置->应用->选择正在运行中的应用,我们可以发现,我们的程序退出杀掉了,而服务还在进行着

IntentService

IntentService是专门用来解决Service中不能执行耗时操作这一问题的,创建一个IntentService也很简单,只要继承IntentService并覆写onHandlerIntent函数,在该函数中就可以执行耗时操作了

public class TheIntentService extends IntentService {

    public TheIntentService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //在这里执行耗时操作
    }
}

AIDL跨进程服务

关于AIDL跨进程服务的使用和原理分析,可以见我另一篇博客:Android基础——初学者必知的AIDL在应用层上的Binder机制

AccessibilityService无障碍服务

关于AccessibilityService无障碍服务的使用和实例,可以见我另一篇博客:Android进阶——学习AccessibilityService实现微信抢红包插件

系统服务

系统服务提供了很多便捷服务,可以查询Wifi、网络状态、查询电量、查询音量、查询包名、查询Application信息等等等相关多的服务,具体大家可以自信查询文档,这里举例几个常见的服务

1. 判断Wifi是否开启

WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
boolean enabled = wm.isWifiEnabled();

需要权限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

2. 获取系统最大音量

AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int max = am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);

3. 获取当前音量

AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int current = am.getStreamMaxVolume(AudioManager.STREAM_RING);

4. 判断网络是否有连接

ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
boolean isAvailable = info.isAvailable();

需要权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

部分源码下载

源码下载

时间: 2024-10-07 23:11:35

Android四大组件——Service后台服务、前台服务、IntentService、跨进程服务、无障碍服务、系统服务的相关文章

Android四大组件——Service

Service相关链接 Service初涉 Service进阶 Service精通 Service是Android系统中的一种组件,它跟Activity的级别差不多,但是它不能自己运行,只能后台运行,并且可以和其他组件进行交互.Service是没有界面的长生命周期的代码.Service是一种程序,它可以运行很长时间,但是它却没有用户界面.这么说有点枯燥,来看个例子,打开一个音乐播放器的程序,这个时候若想上网了,那么,我们打开Android浏览器,这个时候虽然我们已经进入了浏览器程序,但是,歌曲播

Android 四大组件 Service 服务

1.Service简介 按照使用范围分类: 类别 优点 缺点 区别 应用 本地服务 Local  Service 本地服务在一定程度上节约了资源,另外本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL.相应bindService会方便很多. 主进程被Kill后,服务便会终止. 本地服务依附在主进程上,而不是独立的进程,用于应用程序内部 . 音乐播放服务 远程服务 Remote Service 对应进程名格式为所在包名加上指定的android:process字符串.由于是独立的进程,因此

Android四大组件-Service

http://blog.csdn.net/guolin_blog/article/details/11952435 http://www.jianshu.com/p/eeb2bd59853f 概述 定义.特点: Service是可以在后台执行长时间(长生命周期)而又不与用户产生UI交互(没有用户界面)的操作 注意事项:1.只能在后台运行,即便用户切换了其他应用,启动的Service仍可在后台运行.2.可以和其他组件进行Service绑定并与之交互,甚至是跨进程通信(IPC).3.不能运行在一个独

Android四大组件service之Bound Service

html, body { font-size: 15px; } body { font-family: Helvetica, "Hiragino Sans GB", 微软雅黑, "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.6; color: ; background-color: ; margin: 0; padding: 16px 20px; } h1, h2, h

Android四大组件-Service并非详解

距离上篇文章竟然快一年了.这次是想明确service一些比较重要的点. 至于什么是service,我也不想多去讨论,我只想清晰确认这么几个问题: 1.service的生命周期到底如何? 2.Activity如何让service做事? 3.service与thread之间有没有关系? 4.远程service是什么东西? 5.AIDL的使用? 6.前台service? 一.生命周期 如果需要图,可以百度,好多.我这里直接运行代码打log. 1.startService()启动Service 操作顺序

Android成长日记-Android四大组件之Service组件的学习

1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它没有用户界面,所以绝不会到前台来.一旦Service被启动起来,它就与Activity一样.它完全具有自己的生命周期. A Service is an application component that can perform long-running operations in the back

Android 四大组件之Service详解

                   Android四大组件之Service详解    来这实习已经10多天了,今天整理整理学习时的Android笔记.正所谓好记性不如烂笔头,今天来说说service组件. service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的. Service是在一段不定的时间运行在后台,不和用户交互应用组件.每个

【Android的从零单排开发日记】之入门篇(五)——Android四大组件之Service

这几天忙着驾校考试,连电脑都碰不到了,今天总算告一段落了~~Service作为Android的服务组件,默默地在后台为整个程序服务,辅助应用与系统中的其他组件或系统服务进行沟通.它跟Activity的级别差不多,但不能自己运行只能后台运行.service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等, 总之服务总是藏在后台的. ps:Service运行在主线程中的,所

Android 四大组件之再论service

service常见的有2种方式,本地service以及remote service. 这2种的生命周期,同activity的通信方式等,都不相同. 关于这2种service如何使用,这里不做介绍,只是介绍一些被遗漏的地方 1.远程Service(AIDL方式) package com.joyfulmath.samples.basecontrol; import android.app.Activity; import android.content.ComponentName; import a