Reveal how the Taobao icon of the Double Eleven mobile phone is dynamically replaced

  • 2021-12-13 17:09:20
  • OfStack

Directory 1, Android How to dynamically change desktop icons 1.1 Usage Scenarios
1.2 Knowledge points
1.3 Using Activity-alias
2. Giant pit 2.1 Coverage of App
2.2 Two icons on the desktop
2.3 Disappearance of icons on the desktop
2.4 Summary
2.5 Final Scenario (Scenario 1)

1. How does Android dynamically change desktop icons

1.1 Usage Scenarios

APP, in China's e-commerce industry, a treasure and a certain east are the benchmarks of the industry. One of the curious points is that when the Double 101 approaches, their APP desktop icon suddenly becomes an icon with the word Double 101. It may be that the icon of Double 101 is built in, which is dynamically replaced when it is approaching Double 101, and then after the time of Double 101, the desktop icon of APP is changed into ordinary icon.

1.2 Knowledge points

Dynamic replacement of APP desktop icon quote;
activity Component and Definition "Alliance" Component activity-alias;
PackageManager class to enable/disable components;
Brief introduction of PackageInfo;
New noun record {PackageInfo: Androidmanifest. xml file description class}

1.3 Using Activity-alias


<activity
    android:name="com.aliasicon.MainActivity"
    android:enabled="false"
    android:exported="true"
    >
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>


<activity-alias
    android:name="com.zztzt.android.simple.activity.tztCommHeadPageGenearlActivity"
    android:configChanges="orientation|keyboardHidden|fontScale|screenSize"
    android:enabled="true"
    android:exported="true"
    android:icon="@drawable/tzt_icon"
    android:label="@string/app_general_name"
    android:screenOrientation="portrait"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>
<activity-alias
    android:name="com.zztzt.android.simple.activity.tztCommHeadPageLicaiActivity"
    android:configChanges="orientation|keyboardHidden|fontScale|screenSize"
    android:enabled="false"
    android:exported="true"
    android:icon="@drawable/tzt_icon_licai"
    android:label="@string/app_licai_name"
    android:screenOrientation="portrait"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

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

String systemPath = "com.aliasicon.MainActivity";
String springPath = "com.zztzt.android.simple.activity.tztCommHeadPageAliasActivity";
String licaiPath = "com.zztzt.android.simple.activity.tztCommHeadPageLicaiActivity";
String genearlPath = "com.zztzt.android.simple.activity.tztCommHeadPageGenearlActivity";
String finalPath = "";
ComponentName genearlComponent;
ComponentName licaiComponent;
ComponentName springComponent;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    genearlComponent = new ComponentName(getApplication(), genearlPath);
    licaiComponent = new ComponentName(getApplication(), licaiPath);
    springComponent = new ComponentName(getApplication(), springPath);

	// No. 1 1 Default buttons 
    Button btnDefault = (Button) findViewById(R.id.tztToDefault);
    btnDefault.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, licaiComponent);
            disableComponent(MainActivity.this, springComponent);
            enableComponent(MainActivity.this, genearlComponent);
        }
    });
    // Financial button 
    Button btnLiCai = (Button) findViewById(R.id.tztToLiCai);
    btnLiCai.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, genearlComponent);
            disableComponent(MainActivity.this, springComponent);
            enableComponent(MainActivity.this, licaiComponent);
        }
    });
    // Spring Festival button 
    Button btnSpring = (Button) findViewById(R.id.tztToSpring);
    btnSpring.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            disableComponent(MainActivity.this, genearlComponent);
            disableComponent(MainActivity.this, licaiComponent);
            enableComponent(MainActivity.this, springComponent);
        }
    });
}

/**
 *  Enable components  * 
 * @param componentName
 *  Important method 
 */
private void enableComponent(Activity activity, ComponentName componentName) {
    PackageManager pm = activity.getPackageManager();
    int state = pm.getComponentEnabledSetting(componentName);
    if (PackageManager.COMPONENT_ENABLED_STATE_ENABLED == state) {
        // Already enabled 
        return;
    }
    pm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
}

/**
 *  Disable components  * 
 * @param componentName
 *  Important method 
 */
private void disableComponent(Activity activity, ComponentName componentName) {
    PackageManager pm = activity.getPackageManager();
    int state = pm.getComponentEnabledSetting(componentName);
    if (PackageManager.COMPONENT_ENABLED_STATE_DISABLED == state) {
        // Disabled 
        return;
    }
    pm.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
}

public void saveData(String savePath) {
    SharedPreferences sp = getSharedPreferences("Icon", Context.MODE_PRIVATE);
    // Get to edit Object 
    SharedPreferences.Editor edit = sp.edit();
    // Pass editor Object writes data 
    edit.putString("Value", savePath);
    // Submit data to the xml In a file 
    edit.commit();
}

public String getData() {
    SharedPreferences sp = getSharedPreferences("Icon", Context.MODE_PRIVATE);
    return sp.getString("Value", "");
}

2. Giant pit

Through the above program, it can be realized but change icons; If the code is controlled by the time of holidays, the customer will automatically switch icons when opening app;

Isn't it amazing? Don't be too happy yet.

2.1 Coverage of App

Any App will be updated for overlay installation. Improper configuration of the overlay installed Manifest caused irreparable problems.

1. As can be seen from the configuration of xml above, the configuration of one Activity and two Activity-alisa:

android for Activity: enabled= "false"
android for 1st Activity-alias: enabled= "true"
android for 2nd Activity-alias: enabled= "false"

So when App is turned on, the default on the desktop is to use the name and icon of the first Activity-alias.

2. If the configuration of the new version is still in accordance with this configuration (even if a new alias is added, as long as the default Activity-alias does not change), there will be no errors.

3. We call it "Scheme 1"

2.2 Two icons on the desktop

1. If the new version sets enable of Activity to true (Scheme 2), the desktop has the icon of Activity in addition to the original Activity-alias, that is, there are two icons;

android for Activity: enabled = "true"
android for 1st Activity-alias: enabled= "false"
android for 2nd Activity-alias: enabled= "false"

3. If you try to use the disableComponent method in the above code or android: enabled= "false" to hide the displayed Activity-alias icon, both icons will disappear;

2.3 Disappearance of icons on the desktop

1. Two icons will appear in Scenario 2, and if you overwrite with Scenario 1, both icons will disappear.

2. If Scheme 2 is used for overwriting again, the icon can still be displayed again.

2.4 Summary

1. If scheme 1 is used for overlay installation, it is normal to use scheme 1 for overlay installation no matter how the icon is dynamically changed;

2. If you use Scheme 2 for overlay installation, it is normal to use Scheme 2 for overlay installation regardless of the configured icon;

3. If Scheme 1 is used for overlay installation, if the icon is not dynamically switched, it is normal to use Scheme 2 for overlay installation;

4. If scheme 1 is used for overlay installation, if the icon has been dynamically switched, and then scheme 2 is used for overlay installation, double icons will appear;

5. If scheme 1 is used for overlay installation, if the icon has been dynamically switched, and then scheme 2 is used for overlay installation, double icons will appear; If you are using code to try to hide one of them, both icons disappear;

6. If Scheme 1 is used for overlay installation, if the icon is not dynamically switched, it is normal to use Scheme 2 for overlay installation, and it is also normal to use Scheme 1 for overlay installation;

2.5 Final Scenario (Scenario 1)

Using the scheme of scheme 1, that is, dynamically changing icons through codes, 1 must pay attention to the following matters:

1. android for Activity: enabled = "false"

If it is set to true, double icons will appear;

2. The default items displayed in android: enabled= "true" of Activity-alias should not be changed halfway. If the new default value is really needed, the code should be used for dynamic transformation;

3. Do not set android of Activity-alias: enabled= "true" to multiple, otherwise multiple icons will appear. If you try to hide one or several of them through code, the icons may disappear.


Related articles: