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_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动态更新没什么卵用。
更多相关文章
- android 启动 service 的两种方法
- Android属性动画之ObjectAnimator控制
- Android(安卓)的 Application 初始化
- delphi xe5 android iny绿色版+最新SDK/NDK安装方法
- layout_weight属性图解
- 阿拉伯语系处理方法
- 给 Android(安卓)开发者的 Flutter 指南
- Android的APK文件的反编译方法
- APP字体大小,不随系统的字体大小变化而变化的方法