ITPub博客

首页 > 应用开发 > IT综合 > 动态切换app图标,直播源码网站可以实现吗

动态切换app图标,直播源码网站可以实现吗

IT综合 作者:云豹科技阿星 时间:2021-10-13 17:10:47 0 删除 编辑

动态切换应用图标

产品需求

市面上很多直播源码网站能根据特定活动,动态切换应用图标达到宣传目的。那么我们怎样才能在不发直播源码网站新版本的情况下,动态切换应用图标呢?

具体方案

1.图标更换:在AndroidManifest设置应用入口Activity的别名,然后通过setComponentEnabledSetting动态启用或禁用别名进行图标切换

2.控制图标显示:冷启动直播源码网站时,调用接口判断是否需要切换icon

3.触发时机:监听直播源码网站前后台切换,当App处于后台时切换图标,使得用户无感知。

代码实现

在AndroidManifest.xml中给入口Activity设置activity-alias

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.SwitchIcon">
        <!-- 原MainActivity -->
        <activity android:name=".MainActivity" />
        <!-- 固定设置一个默认的别名,用来替代原MainActivity -->
        <activity-alias
            android:name=".DefaultAliasActivity"
            android:enabled="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:targetActivity=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>
        <!-- 别名1,特定活动需要的图标如:双11,国庆节等 -->
        <activity-alias
            android:name=".Alias1Activity"
            android:enabled="false"
            android:icon="@mipmap/ic_launcher_show"
            android:label="@string/app_name"
            android:targetActivity=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity-alias>
        
    </application>

activity-alias标签中的属性如下

标签 作用
android:name 别名,命名规则同Actively
android:enabled 是否启用别名,这里的主要作用的控制显示应用图标
android:icon 应用图标
android:label 应用名
android:targetActivity 必须指向原入口Activity

在MainActivity中,通过启用或禁用别名进行直播源码网站图标切换

/**
 * 设置默认的别名为启动入口
 */
public void setDefaultAlias() {
    PackageManager packageManager = getPackageManager();
    
    ComponentName name1 = new ComponentName(this, "com.fengfeibiao.switchicon.DefaultAliasActivity");
    packageManager.setComponentEnabledSetting(name1, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    
    ComponentName name2 = new ComponentName(this, "com.fengfeibiao.switchicon.Alias1Activity");
    packageManager.setComponentEnabledSetting(name2, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    }
/**
 * 设置别名1为启动入口
 */
public void setAlias1() {
    PackageManager packageManager = getPackageManager();
    ComponentName name1 = new ComponentName(this, "com.fengfeibiao.switchicon.DefaultAliasActivity");
    packageManager.setComponentEnabledSetting(name1, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    ComponentName name2 = new ComponentName(this, "com.fengfeibiao.switchicon.Alias1Activity");
    packageManager.setComponentEnabledSetting(name2, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}

ForegroundCallbacks监听直播源码网站前后台切换

/**
 * 监听App前后台切换
 */
public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks {
    public static final long CHECK_DELAY = 500;
    public static final String TAG = ForegroundCallbacks.class.getName();
    public interface Listener {
        void onForeground();
        void onBackground();
    }
    private static ForegroundCallbacks instance;
    private boolean foreground = false, paused = true;
    private Handler handler = new Handler();
    private List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
    private Runnable check;
    public static ForegroundCallbacks init(Application application) {
        if (instance == null) {
            instance = new ForegroundCallbacks();
            application.registerActivityLifecycleCallbacks(instance);
        }
        return instance;
    }
    public static ForegroundCallbacks get(Application application) {
        if (instance == null) {
            init(application);
        }
        return instance;
    }
    public static ForegroundCallbacks get(Context ctx) {
        if (instance == null) {
            Context appCtx = ctx.getApplicationContext();
            if (appCtx instanceof Application) {
                init((Application) appCtx);
            }
            throw new IllegalStateException(
                    "Foreground is not initialised and " +
                            "cannot obtain the Application object");
        }
        return instance;
    }
    public static ForegroundCallbacks get() {
        if (instance == null) {
            throw new IllegalStateException(
                    "Foreground is not initialised - invoke " +
                            "at least once with parameterised init/get");
        }
        return instance;
    }
    public boolean isForeground() {
        return foreground;
    }
    public boolean isBackground() {
        return !foreground;
    }
    public void addListener(Listener listener) {
        listeners.add(listener);
    }
    public void removeListener(Listener listener) {
        listeners.remove(listener);
    }
    @Override
    public void onActivityResumed(Activity activity) {
        paused = false;
        boolean wasBackground = !foreground;
        foreground = true;
        if (check != null)
            handler.removeCallbacks(check);
        if (wasBackground) {
            Log.d(TAG, "went foreground");
            for (Listener l : listeners) {
                try {
                    l.onForeground();
                } catch (Exception exc) {
                    Log.d(TAG, "Listener threw exception!:" + exc.toString());
                }
            }
        } else {
            Log.d(TAG, "still foreground");
        }
    }
    @Override
    public void onActivityPaused(Activity activity) {
        paused = true;
        if (check != null)
            handler.removeCallbacks(check);
        handler.postDelayed(check = new Runnable() {
            @Override
            public void run() {
                if (foreground && paused) {
                    foreground = false;
                    Log.d(TAG, "went background");
                    for (Listener l : listeners) {
                        try {
                            l.onBackground();
                        } catch (Exception exc) {
                            Log.d(TAG, "Listener threw exception!:" + exc.toString());
                        }
                    }
                } else {
                    Log.d(TAG, "still foreground");
                }
            }
        }, CHECK_DELAY);
    }
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }
    @Override
    public void onActivityStarted(Activity activity) {
    }
    @Override
    public void onActivityStopped(Activity activity) {
    }
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }
    @Override
    public void onActivityDestroyed(Activity activity) {
    }
}

需要在Application中调用ForegroundCallbacks.init(this)进行初始化

在MainActivity中实现ForegroundCallbacks.Listener对App进行监听,当处于后台判断是否切换直播源码网站应用图标

完整的MainActivity代码:

public class MainActivity extends AppCompatActivity implements ForegroundCallbacks.Listener {
    private int position = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //添加app前后台监听
        ForegroundCallbacks.get(this).addListener(this);
        findViewById(R.id.tv_default).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                position = 0;
            }
        });
        findViewById(R.id.tv_alias1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                position = 1;
            }
        });
    }
    @Override
    protected void onDestroy() {
        // 移除app前后台监听
        ForegroundCallbacks.get(this).removeListener(this);
        super.onDestroy();
    }
    @Override
    public void onForeground() {
    }
    @Override
    public void onBackground() {
        //根据具体业务需求设置切换条件,我公司采用接口控制icon切换
        if (position == 0) {
            setDefaultAlias();
        } else {
            setAlias1();
        }
    }
    /**
     * 设置默认的别名为启动入口
     */
    public void setDefaultAlias() {
        PackageManager packageManager = getPackageManager();
        ComponentName name1 = new ComponentName(this, "com.fengfeibiao.switchicon.DefaultAliasActivity");
        packageManager.setComponentEnabledSetting(name1, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
        ComponentName name2 = new ComponentName(this, "com.fengfeibiao.switchicon.Alias1Activity");
        packageManager.setComponentEnabledSetting(name2, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
    }
    /**
     * 设置别名1为启动入口
     */
    public void setAlias1() {
        PackageManager packageManager = getPackageManager();
        ComponentName name1 = new ComponentName(this, "com.fengfeibiao.switchicon.DefaultAliasActivity");
        packageManager.setComponentEnabledSetting(name1, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
        ComponentName name2 = new ComponentName(this, "com.fengfeibiao.switchicon.Alias1Activity");
        packageManager.setComponentEnabledSetting(name2, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
    }
}

具体缺陷如下:

  1. 切换icon会关闭直播源码网站应用进程,不是崩溃所以不会上报bugly
  2. 切换icon需要时间,部分华为机型要10s左右,之后能正常打开
  3. 切换icon过程中,部分机型点击直播源码网站图标无法打开应用,提示应用未安装

声明:本文由云豹科技转发自下午吃早餐同学博客,如有侵权请联系作者删除

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69982461/viewspace-2795803/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2020-08-24

  • 博文量
    229
  • 访问量
    77516