一、背景

近日,微博官网公布了一项新性能,即能够在App设置中动静更换微博的显示图标款式。依据微博官网的说法,除了最原始的图标外,微博还推出了另外10种不同的款式,既有3D微博、炫彩微博等保留了眼睛造型的新款式,也有奶酪甜馨、巧克力等以食物命名的“新口味”,还有梦幻紫、空想星空等抽象派新造型,给了微博用户多种抉择的自在。

不过须要留神的是,这一性能并不是面对所有人凋谢的,只有微博年费会员能力享受。此外,iOS 10.3及以上和Android 10及以上零碎版本反对该性能,然而iPad与一加8Pro手机无奈应用该性能。因局部手机存在零碎差别,会导致该性能不可用,微博方面后续还会对该性能进行进一步优化。

二、技术实现

其实,说到底,上述性能用到的是动静更换桌面图标的技术。如果说多年以前,实现图标的切换还是一种时尚的技术,那么,咱们能够间接应用PackageManager就能够实现动静更换桌面图标。

实现的细节是,在Manifest文件中应用标签筹备多个Activity入口,没个activity都指向入口Activity,并且为每个领有标签的activity设置独自的icon和利用名,最初调用SystemService 服务kill掉launcher,并执行launcher的重启操作。

首先,咱们在AndroidManifest.xml文件中增加如下代码:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    package="com.xzh.demo">        <!-- 权限-->    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>        <application        android:allowBackup="true"        android:icon="@mipmap/wb_default_logo"        android:label="@string/app_name"        android:roundIcon="@mipmap/wb_default_logo"        android:supportsRtl="true"        android:theme="@style/Theme.AndroidDemo">                ...//省略其余代码                <!-- 默认微博-->        <activity-alias            android:name="com.xzh.demo.default"            android:targetActivity=".MainActivity"            android:label="@string/app_name"            android:enabled="false"            android:icon="@mipmap/wb_default_logo"            android:exported="true">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity-alias>                <!-- 3D微博-->        <activity-alias            android:name=".threedweibo"            android:targetActivity=".MainActivity"            android:label="@string/wb_3d"            android:enabled="false"            android:icon="@mipmap/wb_3dweibo"            android:exported="true">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity-alias>                ... //省略其余            </application></manifest>

下面配置中波及到的属性如下:

  • android:name:注册的组件名字,启动组件的名称。
  • android:enabled:是否启用这个组件,也就是是否显示这个入口。
  • android:icon:图标
  • android:label:名称
  • android:targetActivity:默认的activity没有这个属性,指定指标activity,与默认的activity中的name属性是一样的,须要有相应的java类文件。

接着,咱们在MainActivity触发Logo图标更换逻辑,代码如下:

class MainActivity : AppCompatActivity() {    var list: List<LogoBean> = ArrayList()    var recyclerView: RecyclerView? = null    var adapter: LogoAdapter? = null    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        initView()        initData()        initRecycle()    }    private fun initView() {        recyclerView = findViewById(R.id.recycle_view)    }    private fun initData() {        list = Arrays.asList(            LogoBean(R.mipmap.wb_default_logo, "默认图标", true),            LogoBean(R.mipmap.wb_3dweibo, "3D微博", false),            LogoBean(R.mipmap.wb_cheese_sweetheart, "奶酪甜心", false),            LogoBean(R.mipmap.wb_chocolate_sweetheart, "巧克力", false),            LogoBean(R.mipmap.wb_clear_colorful, "清透七彩", false),            LogoBean(R.mipmap.wb_colorful_sunset, "多彩日落", false),            LogoBean(R.mipmap.wb_colorful_weibo, "炫彩微博", false),            LogoBean(R.mipmap.wb_cool_pool, "清凉泳池", false),            LogoBean(R.mipmap.wb_fantasy_purple, "梦幻紫", false),            LogoBean(R.mipmap.wb_fantasy_starry_sky, "空想星空", false),            LogoBean(R.mipmap.wb_hot_weibo, "热感微博", false),        )    }    private fun initRecycle() {        adapter =LogoAdapter(this,list);        val layoutManager = GridLayoutManager(this, 3)        recyclerView?.layoutManager = layoutManager        recyclerView?.adapter = adapter        adapter?.setOnItemClickListener(object : OnItemClickListener {            override fun onItemClick(view: View?, position: Int) {                 if(position==1){                     changeLogo("com.xzh.demo.threedweibo")                 }else if (position==2){                     changeLogo("com.xzh.demo.cheese")                 }else if (position==3){                     changeLogo("com.xzh.demo.chocolate")                 }else {                     changeLogo("com.xzh.demo.default")                 }            }        })    }    fun changeLogo(name: String) {        val pm = packageManager        pm.setComponentEnabledSetting(            componentName,            PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP        )        pm.setComponentEnabledSetting(            ComponentName(this, name),            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP        )        reStartApp(pm)    }    fun reStartApp(pm: PackageManager) {        val am = getSystemService(ACTIVITY_SERVICE) as ActivityManager        val intent = Intent(Intent.ACTION_MAIN)        intent.addCategory(Intent.CATEGORY_HOME)        intent.addCategory(Intent.CATEGORY_DEFAULT)        val resolveInfos = pm.queryIntentActivities(intent, 0)        for (resolveInfo in resolveInfos) {            if (resolveInfo.activityInfo != null) {                am.killBackgroundProcesses(resolveInfo.activityInfo.packageName)            }        }    }}

留神下面的changeLogo()办法中的字符串须要和AndroidManifest.xml文件中的<activity-alias>的name绝对应。运行下面的代码,而后点击利用中的某个图标,就能够更换利用的桌面图标,如下图所示。

不过,测试的时候也遇到一些适配问题:

  • 小米9:版本升级时,新版本在AndroidManifest中删除A3,老版本切换图标到A3,为卸载间接笼罩装置新版本,手机桌面图标隐没。
  • magic 4:版本升级时,新版本在AndroidManifest中删除A3,老版本切换图标到A3,为卸载间接笼罩装置新版本,手机桌面图标切换到默认图标,但点击之后未能关上APP。