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

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

说明

当进行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中注册使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值