動(dòng)態(tài)更換桌標(biāo) Activity-alias

前言

動(dòng)態(tài)更換App圖標(biāo),網(wǎng)上可以收搜到很多,這里也是參考前人經(jīng)驗(yàn),讀完本文可以得到,如何動(dòng)態(tài)更換桌標(biāo)(非網(wǎng)絡(luò)獲取桌標(biāo)圖片),標(biāo)志位的闡述,更加透徹的理解.

用到的知識(shí)

activity-alias并不是代表一個(gè)Activity过吻,而是代表一個(gè)已經(jīng)存在的Activity的別名虏肾。
它使用在清單文件中,類似Activity標(biāo)簽赂弓。它可用來設(shè)置某個(gè)Activity的快捷入口

activity-alias基本用法

<activity-alias android:enabled=["true" | "false"]
                android:exported=["true" | "false"]
                android:icon="drawable resource"
                android:label="string resource"
                android:name="string"
                android:permission="string"
                android:targetActivity="string" >
    ...
</activity-alias>

屬性解釋:

屬性 含義
enabled 是否生效。配置多個(gè)activity-alias時(shí)撼短,如果只想一個(gè)生效踩寇,就設(shè)置一個(gè)為true
exported 是否可以被其他應(yīng)用調(diào)起际起,配置intent-filter時(shí)默認(rèn)為true滓鸠,未配置intent-filter時(shí)默認(rèn)為false雁乡,只能被應(yīng)用自身調(diào)起
icon 自定義生效時(shí)的icon
label 作用同Activity標(biāo)簽中的label屬性第喳,主要表現(xiàn)為桌面上的app名稱和activity的title的名稱
name 該activity-alias的名字
permission 指明通過別名聲明調(diào)起目標(biāo)Activity所必需的權(quán)限
targetActivity 指明目標(biāo)Activity糜俗,類似于Activity標(biāo)簽中的name屬性,需寫明包類路徑曲饱。表明通過activity-alias調(diào)起的是哪個(gè)Activity

使用

  • 首先配置AndroidManifest.xml,設(shè)置別名
        <activity
            android:name=".activitys.WelcomeActivity"
            android:configChanges="keyboard|keyboardHidden|orientation"
            android:hardwareAccelerated="true"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/Acrivity_Fullscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 動(dòng)態(tài)更換app圖片的方案-->
        <activity-alias
            android:name=".changeLauncherIconActivity"
            android:configChanges="keyboard|keyboardHidden|orientation"
            android:enabled="false"
            android:icon="@drawable/yishijie_logo"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:targetActivity=".activitys.WelcomeActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>

這里要注意的是

android:name 標(biāo)識(shí):主要用于在代碼中獲取此組件enable的狀態(tài);
android:targetActivity標(biāo)識(shí),targetActivity標(biāo)識(shí)就是點(diǎn)擊后跳轉(zhuǎn)的Activity;
icon和lable分別是啟動(dòng)圖標(biāo)和桌面名稱

  • 代碼配置

思路是首先獲取服務(wù)端下發(fā)接口,緩存到本地,等用戶退出主頁的時(shí)候執(zhí)行更換圖標(biāo)的邏輯

  1. 獲取服務(wù)端接口,接口提示更換節(jié)日?qǐng)D標(biāo)
  2. 判斷要顯示組件的狀態(tài)是否為顯示狀態(tài)COMPONENT_ENABLED_STATE_ENABLED
 private boolean isComponentState(ComponentName componentName) {
      
    return mPackageManager.getComponentEnabledSetting(componentName) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
}

注意:這里的標(biāo)示位

屬性 含義
COMPONENT_ENABLED_STATE_DEFAULT 默認(rèn)狀態(tài),xml預(yù)設(shè)的狀態(tài)
COMPONENT_ENABLED_STATE_ENABLED 此組件或應(yīng)用程序已明確啟用悠抹,無論其清單中指定了什么。
COMPONENT_ENABLED_STATE_DISABLED 此組件或應(yīng)用程序已明確禁用扩淀,無論其清單中指定了什么楔敌。
COMPONENT_ENABLED_STATE_DISABLED_USER 用戶已明確禁用該應(yīng)用程序,無論其在清單中指定了什么驻谆。
COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED his application should be considered, until the point where the user actually wants to use it. (這個(gè)不清楚怎么翻才好,沒有使用過)
  1. 如果不是則設(shè)置其可見,否則不變

注意這里設(shè)置標(biāo)志位是永久性的,即使App升級(jí)獲取此組件狀態(tài)時(shí),也是之前的值

  private void enableComponent(ComponentName componentName) {
        //此方法用以啟用和禁用組件卵凑,會(huì)覆蓋Androidmanifest文件下定義的屬性
        mPackageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

完整代碼


public class ChangeAppIconUtils {

    private PackageManager mPackageManager;
    //默認(rèn)桌標(biāo)
    private static final String DEFAULT_ICON = "com.x.x.activitys.WelcomeActivity";
    //活動(dòng)桌標(biāo)
    private static final String ANTHER_ICON = "com.x.x.changeLauncherIconActivity";
    //緩存文件鍵值
    public static final String KEY_LAUNCHER_ICON = "key_launcher_icon";

    public ChangeAppIconUtils(PackageManager mPackageManager) {
        this.mPackageManager = mPackageManager;
    }

    /**
     * 啟動(dòng)組件
     *
     * @param componentName 組件名
     */
    private void enableComponent(ComponentName componentName) {
        //此方法用以啟用和禁用組件,會(huì)覆蓋Androidmanifest文件下定義的屬性
        mPackageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    /**
     * 禁用組件
     *
     * @param componentName 組件名
     */
    private void disableComponent(ComponentName componentName) {
        mPackageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }


    /**
     * 當(dāng)前組件的狀態(tài),判斷當(dāng)前enable狀態(tài)
     * 即使xml里面設(shè)置enable=false 標(biāo)志位第一次獲取時(shí) 還是COMPONENT_ENABLED_STATE_DEFAULT
     * 所以這里判斷是否為enable
     *
     * @param componentName return true 未被應(yīng)用為可顯示
     */
    private boolean isComponentState(ComponentName componentName) {
        //默認(rèn)圖標(biāo)且為默認(rèn)狀態(tài)則返回false
        return !(DEFAULT_ICON.equals(componentName.getClassName()) && mPackageManager.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
                && mPackageManager.getComponentEnabledSetting(componentName) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
    }


  /**
     * 更換app 圖標(biāo)
     *
     * @param context    context
     * @param changeIcon changeIcon
     */
    private void changeIconState(Context context, String changeIcon) {
        ComponentName defaultIcon = new ComponentName(context, DEFAULT_ICON);
        ComponentName otherIcon = new ComponentName(context, ANTHER_ICON);
        //判斷狀態(tài)
        if (DEFAULT_ICON.equals(changeIcon)) {//設(shè)置默認(rèn)icon
            boolean componentState = isComponentState(defaultIcon);
            if (componentState) {//如果不一樣則設(shè)置
                enableComponent(defaultIcon);
                disableComponent(otherIcon);
//                restartSystemLauncher(context, mPackageManager);
            }
        } else {//其它icon
            boolean componentState = isComponentState(otherIcon);
            if (componentState) {
                enableComponent(otherIcon);
                disableComponent(defaultIcon);
//                restartSystemLauncher(context, mPackageManager);
            }
        }
    }

    /**
     * 沒啥用,有的rom不會(huì)讓你殺掉Launcher進(jìn)程胜臊,例如華為勺卢,VIVO
     * @param context
     * @param pm
     */
    private void restartSystemLauncher(Context context, PackageManager pm) {
        ActivityManager am = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
        Intent i = new Intent(Intent.ACTION_MAIN);
        i.addCategory(Intent.CATEGORY_HOME);
        i.addCategory(Intent.CATEGORY_DEFAULT);
        List<ResolveInfo> resolves = pm.queryIntentActivities(i, 0);
        for (ResolveInfo res : resolves) {
            if (res.activityInfo != null && am != null) {
                am.killBackgroundProcesses(res.activityInfo.packageName);
            }
        }
    }

    public void setAppLauncherIcon(Context context, String tagName) {
        if (!TextUtils.isEmpty(tagName)) {
            if ("icon2".equals(tagName)) {
                changeIconState(context, ANTHER_ICON);
            } else {
                changeIconState(context, DEFAULT_ICON);
            }
        }
    }
}

使用的時(shí)候只需要

new ChangeAppIconUtils(getPackageManager()).setAppLauncherIcon(getApplicationContext(), sharePreUtils.getStringValue(ChangeAppIconUtils.KEY_LAUNCHER_ICON, ""));

這里的sharepreUtils是工具類獲取接口中下發(fā)的狀態(tài)值,icon1默認(rèn)圖標(biāo),icon2為節(jié)日?qǐng)D標(biāo),因?yàn)橹坝腥苏f會(huì)導(dǎo)致app的重啟,所以這里的操作時(shí)放在主Activity onDestory里面執(zhí)行的.

問題

  • 目前已知的問題,當(dāng)改完圖標(biāo)之后,使用AS再次啟動(dòng)會(huì)無法啟動(dòng),把快速啟動(dòng)關(guān)掉就可以了
Error while executing: am start -n "in.myinnos.changeappiconandname/in.myinnos.changeappiconandname.MainActivity-settings" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=in.myinnos.changeappiconandname/.MainActivity-settings }
Error type 3
Error: Activity class {in.myinnos.changeappiconandname/in.myinnos.changeappiconandname.MainActivity-settings} does not exist.

Error while Launching activity

這里我使用打包的方式覆蓋安裝沒有出現(xiàn)這個(gè)問題

  • 改過圖標(biāo)后,會(huì)過一會(huì)兒圖標(biāo)才會(huì)改變象对,有的(華為)改變之前點(diǎn)擊會(huì)提示<該應(yīng)用未安裝>黑忱,但是桌面更新后就可以點(diǎn)進(jìn)去了
  • 使用重啟桌面的方法,加快圖標(biāo)的切換,1.會(huì)被系統(tǒng)禁用例如華為 Vivo Oppo則無法重啟桌面2.小米可以,但是還是會(huì)在1~3秒的時(shí)候關(guān)閉應(yīng)用一次
  • 僅僅修改的是啟動(dòng)圖標(biāo),如果有快捷方式那么快捷方式不會(huì)發(fā)生改變,當(dāng)然可以使用代碼動(dòng)態(tài)更新快捷方式
  • 無法動(dòng)態(tài)加載網(wǎng)絡(luò)圖片,還是僅僅是本地資源修改的桌標(biāo)

參考

安卓代碼動(dòng)態(tài)切換APP啟動(dòng)圖標(biāo)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勒魔,一起剝皮案震驚了整個(gè)濱河市甫煞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冠绢,老刑警劉巖抚吠,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弟胀,居然都是意外死亡楷力,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門邮利,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弥雹,“玉大人,你說我怎么就攤上這事延届〖粑穑” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵方庭,是天一觀的道長厕吉。 經(jīng)常有香客問我酱固,道長,這世上最難降的妖魔是什么头朱? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任运悲,我火速辦了婚禮,結(jié)果婚禮上项钮,老公的妹妹穿的比我還像新娘班眯。我一直安慰自己,他們只是感情好烁巫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布署隘。 她就那樣靜靜地躺著,像睡著了一般亚隙。 火紅的嫁衣襯著肌膚如雪磁餐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天阿弃,我揣著相機(jī)與錄音诊霹,去河邊找鬼。 笑死渣淳,一個(gè)胖子當(dāng)著我的面吹牛脾还,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播水由,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼荠呐,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了砂客?” 一聲冷哼從身側(cè)響起泥张,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鞠值,沒想到半個(gè)月后媚创,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彤恶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年钞钙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片声离。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芒炼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出术徊,到底是詐尸還是另有隱情本刽,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站子寓,受9級(jí)特大地震影響暗挑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斜友,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一炸裆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲜屏,春花似錦烹看、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至虹菲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掉瞳,已是汗流浹背毕源。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陕习,地道東北人霎褐。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像该镣,于是被迫代替她去往敵國和親冻璃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 【Android Activity】 什么是 Activity? 四大組件之一,通常一個(gè)用戶交互界面對(duì)應(yīng)一個(gè) ac...
    Rtia閱讀 3,810評(píng)論 3 18
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • 離別损合,不是從口中說出 也才變得緘默 默默的傷痛省艳,就算可以掩蓋,也偽裝不來 可送你走的時(shí)候嫁审,頭也沒回 白天是晴朗的 ...
    易落尋閱讀 108評(píng)論 2 1
  • 不曾愛過不知愛 直至聽起律适,缺什補(bǔ)什辐烂。。捂贿。才恍然大悟…… 原是如此缺愛纠修。 一直追逐,仰望的至始至終厂僧,于是它扣草。。 如此...
    錦說閱讀 157評(píng)論 0 0
  • 一、當(dāng)日春運(yùn)交通總體態(tài)勢(shì)良好德召,天氣多云白魂,無嚴(yán)重交通擁堵、事故等特殊情況上岗; 二福荸、無道路交通事故,道路交通安全暢通肴掷、有...
    規(guī)格劉閱讀 241評(píng)論 0 0