Android App Bundle 应用内区域设置更改
Android App Bundle with in-app locale change
当我需要从应用程序本身更改应用程序区域设置(即应用程序内部的语言更改设置)时,我遇到了 AAB 问题,问题是 AAB 只给我我的设备语言资源,例如:
我的设备安装了英语和法语,所以 AAb 只给我英语和法语的资源,
但在应用程序内部,可以选择在英语、法语和印度尼西亚语之间切换语言,
在这种情况下,将语言更改为英语或法语时一切正常,但将其更改为印度尼西亚语时,应用程序只是进入崩溃循环,因为它一直在寻找印度尼西亚语但找不到。
这里的问题是,即使我重启了应用程序,由于应用程序仍在寻找丢失的语言资源,它再次进入崩溃循环,这里唯一的解决方案是清除现金或重新安装这是解决方案普通用户不会通过。
顺便提一下,这就是我通过应用程序更改语言环境的方式:
// get resources
Resources res = context.getResources();
// create the corresponding locale
Locale locale = new Locale(language); // for example "en"
// Change locale settings in the app.
android.content.res.Configuration conf = res.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
conf.setLocale(locale);
conf.setLayoutDirection(locale);
} else {
conf.locale = locale;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.getApplicationContext().createConfigurationContext(conf);
}
res.updateConfiguration(conf, null);
P.S。该应用程序在构建为 APK 时运行完美。
应用包无法做到这一点:Google Play 仅在设备选择的语言发生变化时下载资源。
如果您想拥有应用内语言选择器,则必须使用 APK。
编辑:
PlayCore API 现在支持按需下载另一种语言的字符串:
https://developer.android.com/guide/playcore/feature-delivery/on-demand#lang_resources
备选方案(气馁):
您可以通过在 build.gradle
中添加以下配置来禁用按语言拆分
android {
bundle {
language {
// Specifies that the app bundle should not support
// configuration APKs for language resources. These
// resources are instead packaged with each base and
// dynamic feature APK.
enableSplit = false
}
}
}
后一种解决方案会增加应用程序的大小。
可在此处找到按需下载语言的详细信息
https://android-developers.googleblog.com/2019/03/the-latest-android-app-bundle-updates.html
在您应用的 build.gradle
文件中:
dependencies {
// This dependency is downloaded from the Google’s Maven repository.
// So, make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.play:core:1.10.0'
// For Kotlin users also add the Kotlin extensions library for Play Core:
implementation 'com.google.android.play:core-ktx:1.8.1'
...
}
获取已安装语言的列表
val splitInstallManager = SplitInstallManagerFactory.create(context)
val langs: Set<String> = splitInstallManager.installedLanguages
请求其他语言
val installRequestBuilder = SplitInstallRequest.newBuilder()
installRequestBuilder.addLanguage(Locale.forLanguageTag("pl"))
splitInstallManager.startInstall(installRequestBuilder.build())
查看上方 link 了解完整详情
几个小时后,我终于能够在新的 PlayCore API 中使用 on-demand 语言。
步骤1.)当用户更改语言时,您需要先检查该语言是否已经可用,如果没有则下载该语言
private void changeLocale(final String languageSelected){
SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(PlayAgainstComputer.this);
final Set<String> installedLangs = splitInstallManager.getInstalledLanguages();
if(installedLangs.contains(languageSelected)){ // checking if lang already available
Toast.makeText(PlayAgainstComputer.this,"Done! The language settings will take effect, once you restart the app!").show();
}
else{
SplitInstallRequest request =
SplitInstallRequest.newBuilder()
.addLanguage(Locale.forLanguageTag(languageSelected))
.build();
splitInstallManager.startInstall(request);
splitInstallManager.registerListener(new SplitInstallStateUpdatedListener() {
@Override
public void onStateUpdate(@NonNull SplitInstallSessionState splitInstallSessionState) {
if(splitInstallSessionState.status() == SplitInstallSessionStatus.INSTALLED){
Toast.makeText(PlayAgainstComputer.this,"Download complete! The language settings will take effect, once you restart the app!").show();
}
}
});
}}
Step2.) 用户启动应用程序时必须安装下载的语言。这是在 attchBaseContext()
方法
中完成的
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
SplitCompat.install(this); // It will install all the downloaded langauges into the app
}
步骤 3.) 您需要告诉 Activity 使用所选的语言。以下代码应放在 activity
的 setContentView(R.layout.layout);
之前
String selectedLanguage = getFromPrefernceOrWhereEverYouSavedIt(); // should be 2 letters. like "de", "es"
Locale locale = new Locale(selectedLanguage);
Locale.setDefault(locale);
Resources resources = getResources();
Configuration config = new Configuration(resources.getConfiguration());
config.locale = locale;
resources.updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
完成!
请注意
当用户(选择 non-default/downloaded 语言)更新应用程序时,需要将该语言再次下载到应用程序中,因此请务必在代码中进行处理。
当我在下载完成后使用 activity.recreate();
(为新语言自动刷新应用程序)时遇到了一些问题,这就是为什么我使用 Toast
要求用户手动重启应用程序。但你可以尝试其他方法
我还注意到此方法存在其他一些不一致之处(甚至有时会因为 SplitCompat.install(this);
而面临内存泄漏),因此请确保根据您的代码对其进行测试和优化。
当我需要从应用程序本身更改应用程序区域设置(即应用程序内部的语言更改设置)时,我遇到了 AAB 问题,问题是 AAB 只给我我的设备语言资源,例如:
我的设备安装了英语和法语,所以 AAb 只给我英语和法语的资源,
但在应用程序内部,可以选择在英语、法语和印度尼西亚语之间切换语言,
在这种情况下,将语言更改为英语或法语时一切正常,但将其更改为印度尼西亚语时,应用程序只是进入崩溃循环,因为它一直在寻找印度尼西亚语但找不到。
这里的问题是,即使我重启了应用程序,由于应用程序仍在寻找丢失的语言资源,它再次进入崩溃循环,这里唯一的解决方案是清除现金或重新安装这是解决方案普通用户不会通过。
顺便提一下,这就是我通过应用程序更改语言环境的方式:
// get resources
Resources res = context.getResources();
// create the corresponding locale
Locale locale = new Locale(language); // for example "en"
// Change locale settings in the app.
android.content.res.Configuration conf = res.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
conf.setLocale(locale);
conf.setLayoutDirection(locale);
} else {
conf.locale = locale;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.getApplicationContext().createConfigurationContext(conf);
}
res.updateConfiguration(conf, null);
P.S。该应用程序在构建为 APK 时运行完美。
应用包无法做到这一点:Google Play 仅在设备选择的语言发生变化时下载资源。
如果您想拥有应用内语言选择器,则必须使用 APK。
编辑:
PlayCore API 现在支持按需下载另一种语言的字符串: https://developer.android.com/guide/playcore/feature-delivery/on-demand#lang_resources
备选方案(气馁):
您可以通过在 build.gradle
中添加以下配置来禁用按语言拆分android {
bundle {
language {
// Specifies that the app bundle should not support
// configuration APKs for language resources. These
// resources are instead packaged with each base and
// dynamic feature APK.
enableSplit = false
}
}
}
后一种解决方案会增加应用程序的大小。
可在此处找到按需下载语言的详细信息
https://android-developers.googleblog.com/2019/03/the-latest-android-app-bundle-updates.html
在您应用的 build.gradle
文件中:
dependencies {
// This dependency is downloaded from the Google’s Maven repository.
// So, make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.play:core:1.10.0'
// For Kotlin users also add the Kotlin extensions library for Play Core:
implementation 'com.google.android.play:core-ktx:1.8.1'
...
}
获取已安装语言的列表
val splitInstallManager = SplitInstallManagerFactory.create(context)
val langs: Set<String> = splitInstallManager.installedLanguages
请求其他语言
val installRequestBuilder = SplitInstallRequest.newBuilder()
installRequestBuilder.addLanguage(Locale.forLanguageTag("pl"))
splitInstallManager.startInstall(installRequestBuilder.build())
查看上方 link 了解完整详情
几个小时后,我终于能够在新的 PlayCore API 中使用 on-demand 语言。
步骤1.)当用户更改语言时,您需要先检查该语言是否已经可用,如果没有则下载该语言
private void changeLocale(final String languageSelected){
SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(PlayAgainstComputer.this);
final Set<String> installedLangs = splitInstallManager.getInstalledLanguages();
if(installedLangs.contains(languageSelected)){ // checking if lang already available
Toast.makeText(PlayAgainstComputer.this,"Done! The language settings will take effect, once you restart the app!").show();
}
else{
SplitInstallRequest request =
SplitInstallRequest.newBuilder()
.addLanguage(Locale.forLanguageTag(languageSelected))
.build();
splitInstallManager.startInstall(request);
splitInstallManager.registerListener(new SplitInstallStateUpdatedListener() {
@Override
public void onStateUpdate(@NonNull SplitInstallSessionState splitInstallSessionState) {
if(splitInstallSessionState.status() == SplitInstallSessionStatus.INSTALLED){
Toast.makeText(PlayAgainstComputer.this,"Download complete! The language settings will take effect, once you restart the app!").show();
}
}
});
}}
Step2.) 用户启动应用程序时必须安装下载的语言。这是在 attchBaseContext()
方法
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
SplitCompat.install(this); // It will install all the downloaded langauges into the app
}
步骤 3.) 您需要告诉 Activity 使用所选的语言。以下代码应放在 activity
的setContentView(R.layout.layout);
之前
String selectedLanguage = getFromPrefernceOrWhereEverYouSavedIt(); // should be 2 letters. like "de", "es"
Locale locale = new Locale(selectedLanguage);
Locale.setDefault(locale);
Resources resources = getResources();
Configuration config = new Configuration(resources.getConfiguration());
config.locale = locale;
resources.updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
完成!
请注意
当用户(选择 non-default/downloaded 语言)更新应用程序时,需要将该语言再次下载到应用程序中,因此请务必在代码中进行处理。
当我在下载完成后使用 activity.recreate();
(为新语言自动刷新应用程序)时遇到了一些问题,这就是为什么我使用 Toast
要求用户手动重启应用程序。但你可以尝试其他方法
我还注意到此方法存在其他一些不一致之处(甚至有时会因为 SplitCompat.install(this);
而面临内存泄漏),因此请确保根据您的代码对其进行测试和优化。