Unity动态更换APP图标及名称


本文环境:(本文为安卓版)
Unity2017.4.29
AndroidStudio3.4.2

目标:

实现一个《非人学园》这种的在游戏里换游戏icon的功能:

android 动态修改app名称 android动态修改图标和名称_java

注意:
1/ 安卓机型更换图标需要重启游戏;
2/ 部分安卓机型的icon更换不能立即生效,需要等待10秒左右,期间点击图标可能会提示应用不存在。

基础原理:

多入口配置:activity-alias

alias是别名的意思,顾名思义,就是可以给Activity配置别名。在AndroidManifest.xml中,与基本的Activity的配置大体相似,如:

android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> //这个是unity接入安卓sdk要的
    </activity>

	//别名
    <activity-alias
        android:name=".eamhi1"
        android:enabled="false"
        android:icon="@mipmap/eamhi1"
        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>

上面的默认的,下面的是配置的别名,也就是另一个入口。

android:name:就是注册这个组件的名字,不需要去创建eamhi1.java这个类,就是个名字,我这里的这个名称是".eamhi1",或者为"包名.eamhi1";
android:enabled:是否启用这个组件,也就是是否显示这个入口。
android:icon:图标
android:label:名称
android:targetActivity:这个需要注意,默认的activity没有这个属性,这个属性就是指定目标activity,与默认的activity中的name属性是一样的,需要有相应的java类文件。
然后intent-filter是一样的。

我们把别名activity的android:enabled设为true,就是开启它,桌面上就有两个入口了。点击这两个图标效果是一样的,都是进入MainActivity。

如何动态改变图标:其实就启用不同的入口就行,然后每次就只有一个入口被启用就行了,在默认情况下,我们就让启动的默认组件,其他入口组件全部禁用,需要用哪个就启用哪个,并且把其他的关闭了,避免出现多个入口,那么如何通过代码动态的设置启动或禁用呢?

###如何动态设置是否启用?

那就需要packageManager,有一个这个方法:

packageManager.setComponentEnabledSetting(componentName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

第一个参数是组件,第二个参数就是是否启用,第三个参数一般就填不杀死APP。
然后组件通过自己定义的组件名字来获取到,如

//拿到我们注册的MainActivity组件
    defaultComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.MainActivity");  //拿到默认的组件
    //拿到我注册的别名test组件
    testComponent = new ComponentName(getBaseContext(), "com.fu.changeicondemo.test");

代码:

private HashMap<String, ComponentName> componentNameDic;
    private PackageManager packageManager;
    private ComponentName defaultComponent;
    private ComponentName curComponent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        componentNameDic = new HashMap<>();
        packageManager = getApplicationContext().getPackageManager();
        defaultComponent = new ComponentName(getBaseContext(),getPackageName()+".MainActivity" );  //拿到默认的组件
    }

	//unity调用初始化icon信息
    public String InitCurUseIconInfo(String icons){
        if(icons == null){
            Log.e("unity","InitCurUseIconInfo,icon config is null.");
            return "";
        }
        Log.i("unity","InitCurUseIconInfo,icon config:"+icons);
        String[] iconStrs = icons.split(",");
        if (iconStrs!=null && iconStrs.length > 0){
            for (int i=0;i<iconStrs.length;i++)
            {
                String tempStr = iconStrs[i];
                if(ComponentIsEnabled(tempStr)){
                    curComponent =GetComponentByName(tempStr);
                    Log.i("unity","cur using icon:"+tempStr);
                    return tempStr;
                }
            }
        }
        curComponent = defaultComponent;
        return "";
    }

	//unity调用换icon
    public boolean changeIcon(String iconName,boolean killApp){
        if(ComponentIsEnabled(iconName)){
            Log.i("unity","changeIcon,but icon is using:"+iconName);
            return false;
        }
        disableComponent(curComponent);
        curComponent = GetComponentByName(iconName);
        if(curComponent == null){
            Log.i("unity","changeIcon curComponent,iconName:"+iconName);
            curComponent = defaultComponent;
            enableComponent(curComponent,false);
            return false;
        }
        else{
            enableComponent(curComponent,killApp);
            return true;
        }
    }

    private ComponentName GetComponentByName(String componentName){
        ComponentName temp = null;
        if(componentName == null || componentName.equals("")|| componentName.equals("MainActivity")|| componentName.equals("default")){
            temp = defaultComponent;
        }
        else{
            if(componentNameDic.containsKey(componentName)){
                temp = componentNameDic.get(componentName);
            }
            else{
                temp = new ComponentName(getBaseContext(),getPackageName()+ "."+componentName );
                componentNameDic.put(componentName,temp);
            }
        }
        return temp;
    }
    //检测某个icon是否在用
    private boolean ComponentIsEnabled(String componentName){
        ComponentName temp = GetComponentByName(componentName);
        int state = packageManager.getComponentEnabledSetting(temp);
        if (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
            //已经启用
            return true;
        }
        return false;
    }
    //启用组件
    private void enableComponent(ComponentName componentName,boolean killApp){
        int state = packageManager.getComponentEnabledSetting(componentName);
        if (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
            //已经启用
            return;
        }
        if (killApp){
            Log.i("unity","killApp and packageManager.enable Setting:"+componentName.toString());
            packageManager.setComponentEnabledSetting(componentName,
                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,0);
        }
        else{
            Log.i("unity","not kill app and packageManager.enable Setting:"+componentName.toString());
            packageManager.setComponentEnabledSetting(componentName,
                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }
    }

    //禁用组件
    private void disableComponent(ComponentName componentName){
        int state = packageManager.getComponentEnabledSetting(componentName);
        if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
            //已经禁用
            return;
        }
        Log.i("unity","packageManager.disable Setting:"+componentName.toString());
        packageManager.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }

在Unity中可以在打开这个换icon功能界面的时候,调用InitCurUseIconInfo初始化icon信息并获取目前在用的icon,传给java的字符串为所有alias用逗号拼接而成;调用changeIcon传入对应的别名来设置对应的icon,默认的icon传入"default"就行了,java那边已经处理了。

个人源码工程:https://github.com/Eam727/UnityChangeIcon,因demo资源可能有版权原因所以不对外了,有java代码就够了。