Aandroid 应用icon动态加载到launcher方法及framework分析

来源:互联网 发布:二手淘宝手机店 编辑:程序博客网 时间:2024/06/03 15:50

Android launcher动态加载应用icon的方法


在android 应用开发中,我们会遇到应用icon需要动态加载到launcher中的问题。
实现的方法是:

private PackageManager pm;pm = context.getPackageManager();pm.setComponentEnabledSetting(new ComponentName(context,"com.uid.pid.New1MainActivity"),PackageManager.COMPONENT_ENABLED_STATE_ENABLED,        PackageManager.DONT_KILL_APP);//加载到launcher中pm.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,        PackageManager.DONT_KILL_APP);//从launcher中remove

这个setComponentEnabledSetting 具体是怎么工作的,我们通过framework源码可以知道:

PackageManagerService.java

@Overridepublic void setComponentEnabledSetting(ComponentName componentName,        int newState, int flags, int userId) {    if (!sUserManager.exists(userId)) return;    /* SPRD: update label and icon for app @{ */    String packege = componentName.getPackageName();    Log.w(TAG, packege+" == "+newState+" == "+flags+" "+userId);    if(packege.startsWith("com.android.stk")){        isOpen = true;    }    /* @} */    Log.d(TAG, "kings:packageName=" + componentName.getPackageName()            + ", className=" + componentName.getClassName());    setEnabledSetting(componentName.getPackageName(),            componentName.getClassName(), newState, flags, userId, null);}

>

    private void setEnabledSetting(final String packageName, String className, int newState,        final int flags, int userId, String callingPackage) {    if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT          || newState == COMPONENT_ENABLED_STATE_ENABLED          || newState == COMPONENT_ENABLED_STATE_DISABLED          || newState == COMPONENT_ENABLED_STATE_DISABLED_USER          || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {        throw new IllegalArgumentException("Invalid new component state: "                + newState);    }        ...        scheduleWritePackageRestrictionsLocked(userId);        ...    }    void scheduleWritePackageRestrictionsLocked(int userId) {        if (!sUserManager.exists(userId)) return;        mDirtyUsers.add(userId);        if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {            mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);        }    }    case WRITE_PACKAGE_RESTRICTIONS: {        Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);        synchronized (mPackages) {            removeMessages(WRITE_PACKAGE_RESTRICTIONS);            for (int userId : mDirtyUsers) {                mSettings.writePackageRestrictionsLPr(userId);            }            mDirtyUsers.clear();        }        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);    } break;

从上面可以知道最终调用Settings.java中的writePackageRestrictionsLPr()来实现。

SettingS.java

void writePackageRestrictionsLPr(int userId) {    if (DEBUG_MU) {        Log.i(TAG, "Writing package restrictions for user=" + userId);    }    // Keep the old stopped packages around until we know the new ones have    // been successfully written.    File userPackagesStateFile = getUserPackagesStateFile(userId);    File backupFile = getUserPackagesStateBackupFile(userId);    new File(userPackagesStateFile.getParent()).mkdirs();    if (userPackagesStateFile.exists()) {        // Presence of backup settings file indicates that we failed        // to persist packages earlier. So preserve the older        // backup for future reference since the current packages        // might have been corrupted.        if (!backupFile.exists()) {            if (!userPackagesStateFile.renameTo(backupFile)) {                Slog.wtf(PackageManagerService.TAG,                        "Unable to backup user packages state file, "                        + "current changes will be lost at reboot");                return;            }        } else {            userPackagesStateFile.delete();            Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");        }    }    try {        final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);        final BufferedOutputStream str = new BufferedOutputStream(fstr);        final XmlSerializer serializer = new FastXmlSerializer();        serializer.setOutput(str, StandardCharsets.UTF_8.name());        serializer.startDocument(null, true);        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);        serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);        for (final PackageSetting pkg : mPackages.values()) {            PackageUserState ustate = pkg.readUserState(userId);            if (ustate.stopped || ustate.notLaunched || !ustate.installed                    || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT                    || ustate.hidden                    || (ustate.enabledComponents != null                            && ustate.enabledComponents.size() > 0)                    || (ustate.disabledComponents != null                            && ustate.disabledComponents.size() > 0)                    || ustate.blockUninstall                    || (ustate.domainVerificationStatus !=                        PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)) {                serializer.startTag(null, TAG_PACKAGE);                serializer.attribute(null, ATTR_NAME, pkg.name);                if (DEBUG_MU) Log.i(TAG, "  pkg=" + pkg.name + ", state=" + ustate.enabled);                if (!ustate.installed) {                    serializer.attribute(null, ATTR_INSTALLED, "false");                }                if (ustate.stopped) {                    serializer.attribute(null, ATTR_STOPPED, "true");                }                if (ustate.notLaunched) {                    serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");                }                if (ustate.hidden) {                    serializer.attribute(null, ATTR_HIDDEN, "true");                }                if (ustate.blockUninstall) {                    serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");                }                if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {                    serializer.attribute(null, ATTR_ENABLED,                            Integer.toString(ustate.enabled));                    if (ustate.lastDisableAppCaller != null) {                        serializer.attribute(null, ATTR_ENABLED_CALLER,                                ustate.lastDisableAppCaller);                    }                }                if (ustate.domainVerificationStatus !=                        PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {                    serializer.attribute(null, ATTR_DOMAIN_VERIFICATON_STATE,                            Integer.toString(ustate.domainVerificationStatus));                }                if (ustate.appLinkGeneration != 0) {                    serializer.attribute(null, ATTR_APP_LINK_GENERATION,                            Integer.toString(ustate.appLinkGeneration));                }                if (ustate.enabledComponents != null                        && ustate.enabledComponents.size() > 0) {                    serializer.startTag(null, TAG_ENABLED_COMPONENTS);                    for (final String name : ustate.enabledComponents) {                        serializer.startTag(null, TAG_ITEM);                        serializer.attribute(null, ATTR_NAME, name);                        serializer.endTag(null, TAG_ITEM);                    }                    serializer.endTag(null, TAG_ENABLED_COMPONENTS);                }                if (ustate.disabledComponents != null                        && ustate.disabledComponents.size() > 0) {                    serializer.startTag(null, TAG_DISABLED_COMPONENTS);                    for (final String name : ustate.disabledComponents) {                        serializer.startTag(null, TAG_ITEM);                        serializer.attribute(null, ATTR_NAME, name);                        serializer.endTag(null, TAG_ITEM);                    }                    serializer.endTag(null, TAG_DISABLED_COMPONENTS);                }                serializer.endTag(null, TAG_PACKAGE);            }        }        writePreferredActivitiesLPr(serializer, userId, true);        writePersistentPreferredActivitiesLPr(serializer, userId);        writeCrossProfileIntentFiltersLPr(serializer, userId);        writeDefaultAppsLPr(serializer, userId);        serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);        serializer.endDocument();        str.flush();        FileUtils.sync(fstr);        str.close();        // New settings successfully written, old ones are no longer        // needed.        backupFile.delete();        FileUtils.setPermissions(userPackagesStateFile.toString(),                FileUtils.S_IRUSR|FileUtils.S_IWUSR                |FileUtils.S_IRGRP|FileUtils.S_IWGRP,                -1, -1);        // Done, all is good!        return;    } catch(java.io.IOException e) {        Slog.wtf(PackageManagerService.TAG,                "Unable to write package manager user packages state, "                + " current changes will be lost at reboot", e);    }    // Clean up partially written files    if (userPackagesStateFile.exists()) {        if (!userPackagesStateFile.delete()) {            Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "                    + mStoppedPackagesFilename);        }    }}

通过上面接口发现,android最终将这些componame 保存到手机系统/data/system/users/0/package-restrictions.xml 中

    <pkg name="com.uid.pid">    <enabled-components>        <item name="com.uid.pid.New1MainActivity" />        <item name="com.uid.pid.SecondActivity" />    </enabled-components>    <disabled-components>        <item name="com.uid.pid.MainActivity" />        <item name="com.uid.pid.New2MainActivity" />    </disabled-components>    </pkg>
0 0
原创粉丝点击