Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/186.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:如何在不更改当前区域设置的情况下获取特定区域设置中的字符串_Android_Localization_Locale_Android Resources - Fatal编程技术网

Android:如何在不更改当前区域设置的情况下获取特定区域设置中的字符串

Android:如何在不更改当前区域设置的情况下获取特定区域设置中的字符串,android,localization,locale,android-resources,Android,Localization,Locale,Android Resources,用例:记录显示给用户的错误消息 但是,您不希望日志中的消息依赖于用户设备的区域设置。 另一方面,您不希望仅仅为了(技术)日志记录而更改用户设备的区域设置。 这能实现吗? 我在stackoverflow上找到了几个潜在的解决方案: 甚至可能 但是,它们都会导致更改设备的区域设置(直到下一次配置更改) 无论如何,我目前的解决办法是: public String getStringInDefaultLocale(int resId) { Resources currentResour

用例:记录显示给用户的错误消息

但是,您不希望日志中的消息依赖于用户设备的区域设置。 另一方面,您不希望仅仅为了(技术)日志记录而更改用户设备的区域设置。 这能实现吗? 我在stackoverflow上找到了几个潜在的解决方案:

  • 甚至可能
但是,它们都会导致更改设备的区域设置(直到下一次配置更改)

无论如何,我目前的解决办法是:

public String getStringInDefaultLocale(int resId) {
    Resources currentResources = getResources();
    AssetManager assets = currentResources.getAssets();
    DisplayMetrics metrics = currentResources.getDisplayMetrics();
    Configuration config = new Configuration(
            currentResources.getConfiguration());
    config.locale = DEFAULT_LOCALE;
    /*
     * Note: This (temporiarily) changes the devices locale! TODO find a
     * better way to get the string in the specific locale
     */
    Resources defaultLocaleResources = new Resources(assets, metrics,
            config);
    String string = defaultLocaleResources.getString(resId);
    // Restore device-specific locale
    new Resources(assets, metrics, currentResources.getConfiguration());
    return string;
}
老实说,我一点也不喜欢这种方法。它效率不高,而且——考虑到并发性和其他因素——它可能会导致某些视图出现在“错误”的区域设置中


有什么想法吗?也许这可以使用s实现,就像在标准Java中一样?

您可以将默认语言环境的所有字符串保存在全局类中的
映射中,如启动应用程序时执行的
应用程序

public class DualLocaleApplication extends Application {

    private static Map<Integer, String> defaultLocaleString;

    public void onCreate() {
        super.onCreate();
        Resources currentResources = getResources();
        AssetManager assets = currentResources.getAssets();
        DisplayMetrics metrics = currentResources.getDisplayMetrics();
        Configuration config = new Configuration(
                currentResources.getConfiguration());
        config.locale = Locale.ENGLISH;
        new Resources(assets, metrics, config);
        defaultLocaleString = new HashMap<Integer, String>();
        Class<?> stringResources = R.string.class;
        for (Field field : stringResources.getFields()) {
            String packageName = getPackageName();
            int resId = getResources().getIdentifier(field.getName(), "string", packageName);
            defaultLocaleString.put(resId, getString(resId));
        }
        // Restore device-specific locale
        new Resources(assets, metrics, currentResources.getConfiguration());
    }

    public static String getStringInDefaultLocale(int resId) {
        return defaultLocaleString.get(resId);
    }

}
公共类DualLocaleApplication扩展应用程序{
私有静态映射defaultLocaleString;
public void onCreate(){
super.onCreate();
Resources currentResources=getResources();
AssetManager资产=currentResources.getAssets();
DisplayMetrics=currentResources.getDisplayMetrics();
配置=新配置(
currentResources.getConfiguration());
config.locale=locale.ENGLISH;
新资源(资产、指标、配置);
defaultLocaleString=newHashMap();
Class stringResources=R.string.Class;
for(字段:stringResources.getFields()){
字符串packageName=getPackageName();
int resId=getResources().getIdentifier(field.getName(),“string”,packageName);
defaultLocaleString.put(resId,getString(resId));
}
//还原特定于设备的区域设置
新资源(资产、指标、currentResources.getConfiguration());
}
公共静态字符串getStringInDefaultLocale(int resId){
返回defaultLocaleString.get(resId);
}
}
此解决方案不是最佳解决方案,但不会出现并发问题。

尝试以下方法:

  Configuration conf = getResources().getConfiguration();
  conf.locale = new Locale("ar"); // locale I used here is Arabic

  Resources resources = new Resources(getAssets(), getResources().getDisplayMetrics(), conf);
  /* get localized string */
  String appName = resources.getString(R.string.app_name);

您可以将其用于
API+17

@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static String getStringByLocal(Activity context, int id, String locale) {
    Configuration configuration = new Configuration(context.getResources().getConfiguration());
    configuration.setLocale(new Locale(locale));
    return context.createConfigurationContext(configuration).getResources().getString(id);
}
更新(1):如何支持旧版本

@NonNull
public static String getStringByLocal(Activity context, int resId, String locale) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
        return getStringByLocalPlus17(context, resId, locale);
    else
        return getStringByLocalBefore17(context, resId, locale);
}

@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static String getStringByLocalPlus17(Activity context, int resId, String locale) {
    Configuration configuration = new Configuration(context.getResources().getConfiguration());
    configuration.setLocale(new Locale(locale));
    return context.createConfigurationContext(configuration).getResources().getString(resId);
}

private static String getStringByLocalBefore17(Context context,int resId, String language) {
    Resources currentResources = context.getResources();
    AssetManager assets = currentResources.getAssets();
    DisplayMetrics metrics = currentResources.getDisplayMetrics();
    Configuration config = new Configuration(currentResources.getConfiguration());
    Locale locale = new Locale(language);
    Locale.setDefault(locale);
    config.locale = locale;
/*
 * Note: This (temporarily) changes the devices locale! TODO find a
 * better way to get the string in the specific locale
 */
    Resources defaultLocaleResources = new Resources(assets, metrics, config);
    String string = defaultLocaleResources.getString(resId);
    // Restore device-specific locale
    new Resources(assets, metrics, currentResources.getConfiguration());
    return string;
}

更新(2):对于api+17,我们可以使用以下内容:

public static String getDefaultString(Context context, @StringRes int stringId){
    Resources resources = context.getResources();
    Configuration configuration = new Configuration(resources.getConfiguration());
    Locale defaultLocale = new Locale("en");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        LocaleList localeList = new LocaleList(defaultLocale);
        configuration.setLocales(localeList);
        return context.createConfigurationContext(configuration).getString(stringId);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
        configuration.setLocale(defaultLocale);
        return context.createConfigurationContext(configuration).getString(stringId);
    }
    return context.getString(stringId);
}

多亏了@Khaled Lela的回答,我做了一个Kotlin扩展:

fun Context.getStringByLocale(@StringRes stringRes: Int, locale: Locale, vararg formatArgs: Any): String {
    val configuration = Configuration(resources.configuration)
    configuration.setLocale(locale)
    return createConfigurationContext(configuration).resources.getString(stringRes, *formatArgs)
}
我直接在
活动
片段
上下文
相关类中使用,只需调用:

getStringByLocale(R.string.my_text,Locale.UK)
或带有参数:


getStringByLocale(R.string.my_other_text,Locale.RU,arg1,arg2,arg3)

我是遗漏了什么,还是您的方法与问题中的方法没有区别?如果执行
新资源(getAssets(),getResources().getDisplayMetrics(),getResources().getConfiguration()).getString(R.string.app_name)
字符串仍将使用阿拉伯语,即使您的设备的语言与以前不同!我正在寻找以下用例的解决方案:您的设备是中文的,但日志应打印默认(如英文)消息。请小心调用
新资源
更改
AssetManager
的配置。这将在以后的代码的不相关部分中导致问题。看到这一点和它可能导致的问题。感谢您提出另一个解决方案!这是一个折衷方案:没有并发问题,内存使用率更高,应用程序启动速度较慢。然而,对于我的特定用例,我大部分时间不需要资源(只需要记录错误/异常)。因此,创建一个映射并在每次开始时将其保存在内存中似乎有点太费劲了。这将取决于您实际用于这些错误/异常的字符串资源数量。如果子集很小,也许你可以接受它。另一种方法(变通方法:D)是将这些资源临时保存在tmp文件中,并根据需要访问它们。这种方法不会占用额外的内存,我想它可以满足您的需要。在找到解决方法时,您真的很有创造力+(一)谢谢你的努力,不过,我还是希望有人能提出一个非变通解决方案嗨,你有什么解决方案吗?我也有几乎相同的用例。不,我仍然在使用问题中所述的解决方法,为什么不使用特定的基于英语的字符串来记录日志。R.string.dev\u错误\u单击按钮\u b。如果你不把它翻译成其他语言(也不需要翻译),默认情况下你会得到这个。@VincentD。谢谢你的想法,但是你怎么知道字符串没有被翻译呢?我正在寻找一种通用的机制来记录以某种方式显示给用户的所有内容。我可以在不更改当前区域设置的情况下验证这一点。终于解决了!至少对于API 17+@schnatterer,如果(build.version.SDK\u INT>=build.version\u CODES.JELLY\u BEAN\u MR1)返回getStringByLocal(上下文、剩余、区域设置),您可以确保检查生成版本以支持旧版本
;否则返回getStringByLocalBefore17(上下文、剩余、区域设置)通过此方法,我需要手动将文本设置为所有文本视图。有没有可能不进行这项繁忙的文本设置工作?此解决方案不适用于型号为SM-T285的Galaxy Tab A(2016)。此解决方案适用于我