Unity動態更換APP圖標及名稱

Unity動態更換APP圖標及名稱

參考鏈接:https://blog.csdn.net/fu908323236/article/details/78813136

本文環境:(本文爲安卓版)
Unity2017.4.29
AndroidStudio3.4.2

目標:

實現一個《非人學園》這種的在遊戲裏換遊戲icon的功能:

注意:
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代碼就夠了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章