转载请注明出处: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_APPadded in API level 1int DONT_KILL_APPFlag 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都是没有 ,这两个属性都放在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() {            @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.LAUNCHERStarting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=demo.lgx.com.multipleicondemo/.IconAlias }Error type 3Error: Activity class {demo.lgx.com.multipleicondemo/demo.lgx.com.multipleicondemo.IconAlias} does not exist.Error while Launching activity

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

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

更多相关文章

  1. android 启动 service 的两种方法
  2. Android属性动画之ObjectAnimator控制
  3. Android(安卓)的 Application 初始化
  4. delphi xe5 android iny绿色版+最新SDK/NDK安装方法
  5. layout_weight属性图解
  6. 阿拉伯语系处理方法
  7. 给 Android(安卓)开发者的 Flutter 指南
  8. Android的APK文件的反编译方法
  9. APP字体大小,不随系统的字体大小变化而变化的方法

随机推荐

  1. Android(安卓)的属性系统
  2. Android(安卓)Handler机制8之消息的取出
  3. padding和margin的区别及其属性
  4. Android源码博文集锦2
  5. andirons studio五大布局简介
  6. [Android][设置最小(大)宽高]
  7. Android(安卓)面试经验 - Android(安卓)
  8. listview android:cacheColorHint,listSe
  9. android系统定制从听说到入门二
  10. Android的源代码结构