Android - 以编程方式更改设备系统区域设置

时间:2014-08-18 01:44:07

标签: android locale

我想从我的应用程序更改设备区域设置(不仅仅是应用程序区域设置),就像用户可以在“设置”中那样做 - >语言与键盘 - >语言。

有人可以解释一下怎么做吗? 我一直在寻找几个小时,找不到办法。

3 个答案:

答案 0 :(得分:6)

这个程序确实想要你想要的 https://play.google.com/store/apps/details?id=org.gnvo.langpicker&hl=en

这是它的源代码 https://code.google.com/p/languagepickerwidget/

这是它的主要逻辑 http://bin-liu.blogspot.in/2012/05/how-to-change-system-locale-calling.html

修改

在4.2新的Jelly Bean之后,CHANGE_CONFIGURATION的保护级别定义已经更改,因此应用程序将无法在4.2以上工作,解决方案是http://droider.eu/2013/07/22/morelocale-2-not-working-on-4-2-2-without-su-or-pm/

答案 1 :(得分:4)

是的,您可以更改任何Android版本的设备区域设置,确保您的应用程序是系统应用程序。有代码可以帮助您。如果您喜欢,请给我的答案评分。

//getting the languages that are shown same as in our device settings
     String[] systemLocaleIetfLanguageTags = getAssets().getLocales();
            Arrays.sort(systemLocaleIetfLanguageTags);
            this.locale_data = new ArrayList();
            for (String ietfLanguageTag : systemLocaleIetfLanguageTags)
            {
                if (ietfLanguageTag != null && ietfLanguageTag.length() == 5)
                {
                    this.locale_data.add(new Loc(ietfLanguageTag));
                }
            }
            adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, android.R.id.text1, locale_data);
            // Assign adapter to ListView
            lv.setAdapter(adapter);
            lv.setOnItemClickListener(new OnItemClickListener()
            {
                @Override
                public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3)
                {
                    int itemPosition = position;
                    Loc loc = (Loc) ChangeLanguage.this.adapter.getItem(position);
                    Toast.makeText(ChangeLanguage.this, "language activated successfully !!", 0).show();
                    ChangeLanguage.change_setting(loc.getLocale());
                }
            });
        }
    //to change the locale
        public static void change_setting(Locale loc)
        {
            try
            {
                Class<?> activityManagerNative = Class.forName("android.app.ActivityManagerNative");
                Object am = activityManagerNative.getMethod("getDefault", new Class[0]).invoke(activityManagerNative, new Object[0]);
                Object config = am.getClass().getMethod("getConfiguration", new Class[0]).invoke(am, new Object[0]);
                config.getClass().getDeclaredField("locale").set(config, loc);
                config.getClass().getDeclaredField("userSetLocale").setBoolean(config, true);
                am.getClass().getMethod("updateConfiguration", new Class[] { Configuration.class }).invoke(am, new Object[] { config });
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

答案 2 :(得分:0)

还有其他方式。 与以前的方法一样,此请求权限:

y <- runif(500, min = 1, max = 100) # 1
sum(y) # 2

c <- runif(1000, min = 1, max = 100) # 3
sum(c) # 4

如果我们在设备上拥有管理员访问权限,则可能获得,本文https://snow.dog/blog/kiosk-mode-android确定了如何访问管理员访问权限(不需要root)。

如果我们允许写入设置:

    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>

要获得许可,我们应该运行:

if (!Settings.System.canWrite(this)) {
    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(Uri.parse("package:" + this.getPackageName()));
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivityForResult(intent, 12345);
}

接下来,当我有权更改配置时,我尝试以这种方式设置区域设置,但是这种方式不起作用。不知道为什么:

pm grant sk.lurity.defenqo android.permission.CHANGE_CONFIGURATION

具有:try { final String locale=(String)(Settings.System.class.getField("SYSTEM_LOCALES").get(null)); Settings.System.putString(getContentResolver(),locale,"en-US,ru-UA"); } catch (NoSuchFieldException | IllegalAccessException ex){ ex.printStackTrace(); } 我发现了这篇文章,https://www.fatalerrors.org/a/you-cannot-keep-your-settings-in-the-secure-settings.html 但实际上,此选项有以下来源:

You cannot change private secure settings.
/** * These are all public system settings * * @hide */ @UnsupportedAppUsage public static final Set<String> PUBLIC_SETTINGS = new ArraySet<>(); static { .... PUBLIC_SETTINGS.add(SYSTEM_LOCALES); 中的

所以我可以假设,这种方式在API25中开始起作用,但是我只有API24。 我也尝试授予权限:

/android/provider/Settings.java

但这根本解决不了任何事情。

但是,我在SYSTEM_LOCALES定义附近的源中找到了解决方案:

<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>

在这种情况下,我尝试通过反射将其称为内部类:

        /**
         * The serialized system locale value.
         *
         * Do not use this value directory.
         * To get system locale, use {@link LocaleList#getDefault} instead.
         * To update system locale, use {@link com.android.internal.app.LocalePicker#updateLocales}
         * instead.
         * @hide
         */
        public static final String SYSTEM_LOCALES = "system_locales";

这种工作方式几乎与@Nasrudeen答案相同。它应该从Android 7.0开始工作。是的,再次是骇客。不如我发现的许多解决方案那么糟糕,而且还很容易破解。