Android Launcher 应用的安装、更新、移除介绍--LauncherAppsCompat

  • 说明
  • 实现方法
    • LauncherAppsCompat
    • LauncherAppsCompatV16
    • LauncherAppsCompatVL
  • 总结

说明

当进行Laucher开发时,不可避免的需要对应用的安装、移除、更新等进行处理,此时我们用到了LauncherAppsCompat。由于Android 21前后对于应用更新操作的处理有所不同,所以LauncherAppsCompat只声明了抽像方法面由其子类来实现,子类为LauncherAppsCompatVL、LauncherAppsCompatV16。
LauncherAppsCompatVL针对Android 21 及以上版本的实现方法
LauncherAppsCompatV16 对于Android 16到21版本的实现方法

实现方法

LauncherAppsCompat

LauncherAppsCompat声明为单例模式,在取得单例的时候需要判断Android的版本号,当Android版本号>=21时直接声明返回 LauncherAppsCompatVL,否则返回LauncherAppsCompatV16代码如下:

public static LauncherAppsCompat getInstance(Context context) {    synchronized (sInstanceLock) {        if (sInstance == null) {            if (Utilities.ATLEAST_LOLLIPOP) {                sInstance = new LauncherAppsCompatVL(context.getApplicationContext());            } else {                sInstance = new LauncherAppsCompatV16(context.getApplicationContext());            }        }        return sInstance;    }}

在LauncherAppsCompat 中声明对于应用的处理

public interface OnAppsChangedCallbackCompat {
//应用移除
void onPackageRemoved(String packageName, UserHandleCompat user);
//应用添加
void onPackageAdded(String packageName, UserHandleCompat user);
//应用更新
void onPackageChanged(String packageName, UserHandleCompat user);
//应用移动
void onPackagesAvailable(String[] packageNames, UserHandleCompat user, boolean replacing);
//应用移动过程当中
void onPackagesUnavailable(String[] packageNames, UserHandleCompat user, boolean replacing);
}

说明:UserHandleCompat 是UserHandle的实现类,UserHandler是针对多用户的类。

LauncherAppsCompatV16

LauncherAppsCompatV16通过广播机制接收系统关于应用更新发送了来的广播,
LauncherAppsCompatV16 继承LauncherAppsCompat,在构造方法中注册广播并设置过滤条件接收应用更新广播,并调用父类的OnAppsChangedCallbackCompat接口。

广播注册代码如下:
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme(“package”);
mContext.registerReceiver(mPackageMonitor, filter);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mPackageMonitor, filter);

过滤条件说明:

Intent.ACTION_PACKAGE_REMOVED;
//成功的删除某个APK之后发出的广播
//一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)

Intent.ACTION_PACKAGE_CHANGED;
//一个已存在的应用程序包已经改变,包括包名

Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
////移动APP完成之后,发出的广播(移动是指:APP2SD)
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
//正在移动APP时,发出的广播(移动是指:APP2SD)

广播接收对于不现条件下的action分别处理,实现代码如下:
@Thunk
class PackageMonitor extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.d(TAG, "onReceive: " + action + " - " + intent.getData().toString());

        final UserHandleCompat user = UserHandleCompat.myUserHandle();        if (Intent.ACTION_PACKAGE_CHANGED.equals(action)                || Intent.ACTION_PACKAGE_REMOVED.equals(action)                || Intent.ACTION_PACKAGE_ADDED.equals(action)) {            final String packageName = intent.getData().getSchemeSpecificPart();            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);            if (packageName == null || packageName.length() == 0) {                // they sent us a bad intent                return;            }            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {                for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                    callback.onPackageChanged(packageName, user);                }            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {                if (!replacing) {                    for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                        callback.onPackageRemoved(packageName, user);                    }                }                // else, we are replacing the package, so a PACKAGE_ADDED will be sent                // later, we will update the package at this time            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {                if (!replacing) {                    for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                        callback.onPackageAdded(packageName, user);                    }                } else {                    for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                        callback.onPackageChanged(packageName, user);                    }                }            }        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {            // EXTRA_REPLACING is available Kitkat onwards. For lower devices, it is broadcasted            // when moving a package or mounting/un-mounting external storage. Assume that            // it is a replacing operation.            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING,                    !Utilities.ATLEAST_KITKAT);            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);            for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                callback.onPackagesAvailable(packages, user, replacing);            }        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {            // This intent is broadcasted when moving a package or mounting/un-mounting            // external storage.            // However on Kitkat this is also sent when a package is being updated, and            // contains an extra Intent.EXTRA_REPLACING=true for that case.            // Using false as default for Intent.EXTRA_REPLACING gives correct value on            // lower devices as the intent is not sent when the app is updating/replacing.            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);            for (OnAppsChangedCallbackCompat callback : getCallbacks()) {                callback.onPackagesUnavailable(packages, user, replacing);            }        }    }}

LauncherAppsCompatVL

LauncherAppsCompatVL继承LauncherAppsCompat并利用回调方法处理应用更新的消息
LauncherAppsCompatVL 在构造函数中获取系统服务"launcherapps",实现回调函数代码如下:
private static class WrappedCallback extends LauncherApps.Callback {
private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;

    public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {        mCallback = callback;    }    public void onPackageRemoved(String packageName, UserHandle user) {        mCallback.onPackageRemoved(packageName, UserHandleCompat.fromUser(user));    }    public void onPackageAdded(String packageName, UserHandle user) {        mCallback.onPackageAdded(packageName, UserHandleCompat.fromUser(user));    }    public void onPackageChanged(String packageName, UserHandle user) {        mCallback.onPackageChanged(packageName, UserHandleCompat.fromUser(user));    }    public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {        mCallback.onPackagesAvailable(packageNames, UserHandleCompat.fromUser(user), replacing);    }    public void onPackagesUnavailable(String[] packageNames, UserHandle user,                                      boolean replacing) {        mCallback.onPackagesUnavailable(packageNames, UserHandleCompat.fromUser(user),                replacing);    }}

总结

以上LauncherAppsCompat需要在LaucherMode中注册使用。

更多相关文章

  1. android onConfigurationChanged的那点事
  2. Android(安卓)和 前端的类似点(持续更新)
  3. Android(安卓)Lint
  4. android之在activity中控制另一个activity的UI更新_如何在activi
  5. 曾经的笔记——android的学习笔记(广播接收者)
  6. Android(安卓)MediaScannerConnection,Android(安卓)MediaScanner
  7. Android关于疑难bug处理方法之一(搜索不到相同bug解决方案)
  8. Android(安卓)view的移动和画布的移动原理 适用于制作各种效果
  9. Android(安卓)Local Service

随机推荐

  1. 手工安装android-sdk-windows
  2. Android滑动事件冲突解决 Touch事件处理
  3. Ionic2实现自定义Cordova插件-Android屏
  4. 【Android开发进阶系列,整理】Android与h5
  5. Android获取Cookies,持久化PHPSESSID (Ok
  6. 安卓中引用工程
  7. android 4.2 rtlSupport对UI性能的坑
  8. Android中使用"running services"查看ser
  9. Android和H5交互
  10. Android(安卓)回调机制举例及个人理解