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