《SytemUI》利用SystemUI拉起3方应用

简介

最近做一个需求需要在Android版本8.1手机上启动一个3方服务.在SystemUI这类应用中启动3方应用,一定要在开机广播中启动.

思路

客户提供了3应用,没有源码,apk形式,文档上提供的调用方式.
步骤很少:检查对应的service是否存在,如果存在就启动服务

    public void startGupshupServiceIfNeeded() {
        Intent implicitIntent = new Intent("xxxx");
        Intent explicitIntent = convertImplicitIntentToExplicitIntent(implicitIntent);
        if (explicitIntent != null) {
           mContext.startForegroundService(explicitIntent);
        }
    }

   //查找服务是否存在
    public Intent convertImplicitIntentToExplicitIntent(Intent implicitIntent) {
        PackageManager pm = mContext.getPackageManager();
        List resolveInfoList = pm.queryIntentServices(implicitIntent, 0);
        if (resolveInfoList == null || resolveInfoList.size() != 1) {//1
             Log.v(TAG,"staring service failed");
            return null;
        }

        ResolveInfo serviceInfo = resolveInfoList.get(0);
        ComponentName component = new ComponentName(serviceInfo.serviceInfo.packageName,serviceInfo.serviceInfo.name);
        Intent explicitIntent = new Intent(implicitIntent);
        explicitIntent.setComponent(component);
        return explicitIntent;
    }

无法检测到服务存在

需要开机启动,但是客户给的这个应用本身没有监听开机广播,需要由一个开机启动的应用把它调起来.打算就在SystemUI里面启动,开始的时候在SystemUIApplication的onCreate里面调用startGupshupServiceIfNeeded,发现在查找这个service的时候为空(上面1处),打印"staring service failed",但是如果使用adb方式和测试应用就能够检查到.

adb shell am start-foreground-service包名/服务名

说明SystemUI刚启动的时候,PMS还没有准备好,导致 pm.queryIntentServices无法查到对应的Service,我们需要在系统完全启动之后启动这个服务器

利用SystemUI类

SystemIU应用的各个模块都是通过SystemUI的子类管理的,SystemUI有一个onBootCompleted方法,他会在监听到开机广播的时候调用,而此时也是系统完全起来的时候.如果系统完全启动了,就不会有查找不到应用的问题.

    private final Class[] SERVICES = new Class[] {
            Dependency.class,
            NotificationChannels.class,
            CommandQueue.CommandQueueStart.class,
            KeyguardViewMediator.class,
            Recents.class,
            VolumeUI.class,
            Divider.class,
            SystemBars.class,
            StorageNotification.class,
            PowerUI.class,
            RingtonePlayer.class,
            KeyboardUI.class,
            PipUI.class,
            ShortcutKeyDispatcher.class,
            VendorServices.class,
            GarbageMonitor.Service.class,
            LatencyTester.class,
            GlobalActionsComponent.class,
            RoundedCorners.class,
            GupshupService.class,
    };

GupshupService.class,这个新建的类,用于启动3方应用

具体实现

SystemUIApplication.java

--- base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java ---
 public class SystemUIApplication extends Application implements SysUiServiceProvider {

     /**
      * The classes of the stuff to start.
      */
     private final Class[] SERVICES = new Class[] {
             Dependency.class,
             NotificationChannels.class,
             ....
             RoundedCorners.class,
+            GupshupService.class,
     };
 

GupshupService继承SystemUI

package com.android.systemui;
import java.util.ArrayList;
import java.util.List;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.Context;
import android.content.Intent;
import android.content.ComponentName;
public class GupshupService extends SystemUI {
    @Override
    public void start() {
    }

    @Override
    protected void onBootCompleted() {
        startGupshupServiceIfNeeded();
    }
    /*  start gupshup if need @{ */
    public void startGupshupServiceIfNeeded() {
        Intent implicitIntent = new Intent("xxxxxx");
        Intent explicitIntent = convertImplicitIntentToExplicitIntent(implicitIntent);
        if (explicitIntent != null) {
           mContext.startForegroundService(explicitIntent);
        }
    }
    public Intent convertImplicitIntentToExplicitIntent(Intent implicitIntent) {
        PackageManager pm = mContext.getPackageManager();
        List resolveInfoList = pm.queryIntentServices(implicitIntent, 0);
        if (resolveInfoList == null || resolveInfoList.size() != 1) {
            return null;
        }
        ResolveInfo serviceInfo = resolveInfoList.get(0);
        ComponentName component = new ComponentName(serviceInfo.serviceInfo.packageName,serviceInfo.serviceInfo.name);
        Intent explicitIntent = new Intent(implicitIntent);
        explicitIntent.setComponent(component);
        return explicitIntent;
    }
}

这样启动3方应用就像其他SystemUI模块一样启动了.SystemUI是在AMS ready之后启动,比同在AMS ready的launcher还早,这个时候PMS还没有完成对整个系统apk的遍历,如果等待遍历完开机时候就太长了,所有出现这个问题是可以理解的

之所以我会在继承SystemIU上写这个,是为了统一管理这些需要开机启动的3方App,实际上就在开机广播里面处理也是没有问题的.

你可能感兴趣的:(SystemUI详解)