Unity动态更换APP图标及名称
本文环境:(本文为安卓版)
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:///Eam727/UnityChangeIcon,因demo资源可能有版权原因所以不对外了,有java代码就够了。