Android利用activity-alias动态更新图标icon,标题label

转载请注明出处:http://blog.csdn.net/harryweasley/article/details/73692467

网上已经有很多的介绍“Android动态修改桌面图标”的博客,无非就是用activity-alias,setComponentEnabledSetting方法,但是他们的博客都有一个问题(或许是我没找到正确的),就是当你在切换图标的时候,你的应用会被杀死,重启一次。

就拿下面的这个代码引入本篇博客吧:

  ComponentName oldCN = new ComponentName(getPackageName(), "demo.lgx.com.multipleicondemo.IconAlias");
  PackageManager pm = getPackageManager();
  pm.setComponentEnabledSetting(oldCN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

通常来隐藏一个桌面icon,都会调用这个方法,但是调用这个方法就会出现一个如下所示的问题:
由官方文档的描述可知:

DONT_KILL_APP

added in API level 1
int DONT_KILL_APP
Flag parameter for setComponentEnabledSetting(android.content.ComponentName, int, int) to indicate that you don't want to kill the app containing the component. Be careful when you set this since changing component states can make the containing application's behavior unpredictable.

当你用DONT_KILL_APP,会发生一些不可预料的问题,尤其是当前的activity尝试要要禁止自己。所以最好是,由一个activity禁止另个一activity。
由上可知,该app最好有一个跳转界面,这样关闭的就是那个跳转界面了:
看下应用效果图吧:
这里写图片描述

现在看代码,首先是AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="demo.lgx.com.multipleicondemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".SplashActivity"></activity>
        <activity android:name=".MainActivity">
        </activity>


        <activity-alias
            android:name=".IconAlias"
            android:enabled="true"
            android:icon="@mipmap/ic_launcher_old"
            android:label="@string/app_name"
            android:targetActivity=".SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

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

        </activity-alias>


        <activity-alias
            android:name=".IconAliaNew"
            android:enabled="false"
            android:icon="@mipmap/ic_launcher_new"
            android:label="@string/app_name_new"
            android:targetActivity=".SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

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

        </activity-alias>
    </application>

</manifest>

可以看到定义了两个activity-alias,一个android:enabled=”true”,一个android:enabled=”false”,android:enabled=”true”的activity-alias将会默认显示在桌面上,
其中android:targetActivity=”.SplashActivity”中的属性,就是真正要显示的activity
从这里可以看到,我们的activity都是没有 <action android:name="android.intent.action.MAIN"/><action android:name="android.intent.action.MAIN"/>,这两个属性都放在activity-alias里,这就是为了保证,在使用PackageManager.DONT_KILL_APP时,应用不会重启啊。
SplashActivity代码很简单,就是开启一个线程,过3s后,启动MainActivity,

SplashActivity中的代码如下所示:

package demo.lgx.com.multipleicondemo;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;

/**
 * Created by Harry on 2017/6/19.
 */

public class SplashActivity extends AppCompatActivity{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        Observable.timer(3, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
            @Override
            public void accept(@NonNull Long aLong) throws Exception {
                startActivity(new Intent(SplashActivity.this,MainActivity.class));
                finish();
            }
        });
    }
}

我这里的子线程等待3s,再跳转,用的是RxJava哈。

最后就是MainActivity的代码了,如下所示:

package demo.lgx.com.multipleicondemo;

import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void MyClick(View v) {
        PackageManager pm = getPackageManager();
        ComponentName oldCN = new ComponentName(getPackageName(), "demo.lgx.com.multipleicondemo.IconAlias");
        ComponentName newCN = new ComponentName(getPackageName(), "demo.lgx.com.multipleicondemo.IconAliaNew");
        switch (v.getId()) {
            case R.id.oldIcon:
                pm.setComponentEnabledSetting(oldCN, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
                pm.setComponentEnabledSetting(newCN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
                break;
            case R.id.newIcon:
                pm.setComponentEnabledSetting(newCN, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
                pm.setComponentEnabledSetting(oldCN, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
                break;
        }
    }
}

这就是动态改变icon和label的源码了。

下面我开始泼冷水了:

当你修改了icon后,你的app将不能够升级安装了,安装后,打开也会直接崩溃,这就意味着,你的app将一直维持这个版本。
不能安装的错误日志如下所示:

Error while executing: am start -n "demo.lgx.com.multipleicondemo/demo.lgx.com.multipleicondemo.IconAlias" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=demo.lgx.com.multipleicondemo/.IconAlias }
Error type 3
Error: Activity class {demo.lgx.com.multipleicondemo/demo.lgx.com.multipleicondemo.IconAlias} does not exist.

Error while Launching activity

解决这个办法,我目前想到了一个方法,就是你的app不放入各大应用市场(表打我,嘤嘤嘤~),只是自己应用内部实现更新,在更新之前,先变化自己的图标为默认图标,再安装更新。

如果哪个大神有更好的办法,请说一下哈。否则我总是觉得这个app动态更新没什么卵用。

猜你喜欢

转载自blog.csdn.net/HarryWeasley/article/details/73692467