一、背景

近日,微博官方发布了一项新功能,即可以在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。

到此这篇关于android动态更换应用图标详情的文章就介绍到这了,更多相关android更换图标内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

发表评论

后才能评论