1. 程式人生 > >安卓程式碼動態切換APP啟動圖示

安卓程式碼動態切換APP啟動圖示

目錄

前言

每當雙11時,手機中的“天貓”的圖示就會變成雙11主題的圖示。這是怎麼實現的呢?

有人說是更新App,沒錯,可以實現。但是有些大材小用了,畢竟更新一個版本。

個人猜測是在雙11前的某次更新版本時已將節日圖片資源打包入內,根據伺服器提供的資料動態改變。所以就有了本文

需要用到的知識:activity-alias

alias 英 [ˈeɪliəs] 美 [ˈeliəs, ˈeljəs]
n. 別名,化名;

顧名思義,activity-alias並不是代表一個Activity,而是代表一個已經存在的Activity的別名。
它使用在清單檔案中,類似Activity標籤。它可用來設定某個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 是否生效。配置多個activity-alias時,如果只想一個生效,就設定一個為true
exported 是否可以被其他應用調起,配置intent-filter時預設為true,未配置intent-filter時預設為false,只能被應用自身調起
icon 自定義生效時的icon
label 作用同Activity標籤中的label屬性,主要表現為桌面上的app名稱和activity的title的名稱
name 該activity-alias的名字
permission 指明通過別名宣告調起目標Activity所必需的許可權
targetActivity 指明目標Activity,類似於Activity標籤中的name屬性,需寫明包類路徑。表明通過activity-alias調起的是哪個Activity

程式碼範例:

  • AndroidManifest.xml
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Android ICON"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity-alias
            android:name=".MainAliasActivity"
            android:targetActivity=".MainActivity"
            android:label="UNIQLO ICON"
            android:icon="@mipmap/ic_launcher_change"
            android:enabled="false">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>
    </application>

這裡聲明瞭一個activity-alias,目標Activity為MainActivity,label為“UNIQLO ICON”,指定了一個與原icon不同的icon,目前未啟用
我們在MainActivity中增加兩個按鈕,用於切換icon

  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">
    <Button
        android:layout_margin="10dp"
        android:id="@+id/mChangeToAndroid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="安卓安卓" />
    <Button
        android:layout_margin="10dp"
        android:id="@+id/mChangeToUniQlo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="一庫一庫" />
</LinearLayout>

在MainActivity中對按鈕的點選事件進行處理,並進行相應的切換操作

  • MainActivity.class
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView() {
        Button mChangeToAndroid = (Button) findViewById(R.id.mChangeToAndroid);
        Button mChangeToUniQlo = (Button) findViewById(R.id.mChangeToUniQlo);
        mChangeToAndroid.setOnClickListener(this);
        mChangeToUniQlo.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.mChangeToAndroid:
                changeIcon("com.hansion.changelaunchericon.MainActivity");
                break;
            case R.id.mChangeToUniQlo:
                changeIcon("com.hansion.changelaunchericon.MainAliasActivity");
                break;
            default:
                break;
        }
    }
    public void changeIcon(String activityPath) {
        PackageManager pm = getPackageManager();
        pm.setComponentEnabledSetting(getComponentName(),
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
        pm.setComponentEnabledSetting(new ComponentName(this, activityPath),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
        //重啟桌面 加速顯示
//        restartSystemLauncher(pm);
    }
    public void restartSystemLauncher(PackageManager pm) {
        ActivityManager am = (ActivityManager) 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.killBackgroundProcesses(res.activityInfo.packageName);
            }
        }
    }
}
  • 通過以上程式碼切換icon後,需在桌面等待數秒鐘後生效。如下圖:

不重啟桌面的效果

  • 如果需要加速生效,則需要在更改icon後重啟一下系統桌面。解開第34行程式碼的註釋,增加許可權
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
  • 如下圖:
    重啟桌面的效果

  • 需要注意的是,更換icon會關閉App,所以切換icon要選擇一個合適的時機來進行操作。

個人認為本文中切換APP啟動方式一定不是最好的方式,圖片資源從伺服器動態獲取才更靈活。如果你有更好的實現方式,請留言給我,謝謝。

本文參考