android 如何修改系统语言

最近有需求需要去编程实现根据选择去修改系统语言, 根据查资料看setting源码有两种方式, 在这里记录一下. 修改系统语言或者控制系统开关机等操作即使声明了对应权限还是会报错, 这是因为这些操作需要系统权限,这里也会介绍如何使用android studio对应用进行系统签名.

一.如何查看系统的配置信息?

在终端使用adb shell getprop命令可以查看系统配置信息, 我们会得到类似下面的输出:

[persist.sys.language]: [en]
[persist.sys.localevar]: []
[persist.sys.operator]: [xxx]
[persist.sys.synctimetype]: [xxx]
[persist.sys.timezone]: [xxx]
[persist.sys.usb.config]: [xxx]
[ro.adb.secure]: [0]
[ro.allow.mock.location]: [0]
[ro.baseband]: [unknown]
[ro.board.platform]: [xxxxxxx]
[ro.boot.bootloader]: [xxxxxxxxx]

以ro开头的只能读取值,不能进行修改, 以 persist开头是保留值可以修改.
我们看到 persist.sys.language 的值标记了当前系统的语言.

那么如何去读取这个配置文件的信息呢?
在这里介绍两种方式:
(1)使用反射

    public static String getSystemProp(final String key, final String defaultValue) {
        try {
            if (getStringPropMethod == null) {
                getStringPropMethod = Class.forName("android.os.SystemProperties")
                        .getMethod("get", String.class, String.class);
            }

            return (String) getStringPropMethod.invoke(null, key, defaultValue);
        } catch (Exception e) {
            Log.e(TAG, Log.getStackTraceString(e));
            return defaultValue;
        }
    }

getSystemProp的第一个参数是属性文件的前面的字符串, 第二个参数为默认值, 例如如果想要获取系统当前语言:
getSystemProp(“persist.sys.language”, “zh”);

(2) 使用SystemProperties
SystemProperties 需要手动去引入它所依赖的jar包. 在 android studio中的配置步骤:
在工程的build.gradle中添加:
①在dependencies中添加引入函数:
dependencies {
……
provided files(getLayoutLibPath())
}
② 定义引入函数与引入的编码
tasks.withType(JavaCompile) {
options.encoding = “UTF-8”
}

def getLayoutLibPath() {
return “${android.getSdkDirectory().getAbsolutePath()}” + “/platforms/” + android.compileSdkVersion + “/data/layoutlib.jar”
}

配置成功后, 可以直接使用SystemProperties来获取系统配置文件中的信息.
获取系统语言:
SystemProperties.get(“persist.sys.language”, “zh”); //第二个参数为默认值

SystemProperties不但可以获取配置文件的信息, 而且可以去修改配置文件, 注意: 以ro开头的不能修改.
SystemProperties.set(“persist.sys.language”, “zh”); //将系统语言改成中文, 需要重启系统才能生效

如何不需要系统重启, 就能让改变语言生效?

(1) 网上提供的方式, 利用反射:

public static void setLanguage(Locale locale) {
        try {
            Object objIActMag;

            Class clzIActMag = Class.forName("android.app.IActivityManager");

            Class clzActMagNative = Class
                    .forName("android.app.ActivityManagerNative");

            Method mtdActMagNative$getDefault = clzActMagNative
                    .getDeclaredMethod("getDefault");

            objIActMag = mtdActMagNative$getDefault.invoke(clzActMagNative);

            Method mtdIActMag$getConfiguration = clzIActMag
                    .getDeclaredMethod("getConfiguration");

            Configuration config = (Configuration) mtdIActMag$getConfiguration
                    .invoke(objIActMag);

            config.locale = locale;

            Class clzConfig = Class
                    .forName("android.content.res.Configuration");
            java.lang.reflect.Field userSetLocale = clzConfig
                    .getField("userSetLocale");
            userSetLocale.set(config, true);

            Class[] clzParams = { Configuration.class };

            Method mtdIActMag$updateConfiguration = clzIActMag
                    .getDeclaredMethod("updateConfiguration", clzParams);

            mtdIActMag$updateConfiguration.invoke(objIActMag, config);

            BackupManager.dataChanged("com.android.providers.settings");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

需要添加权限: android.permission.CHANGE_CONFIGURATION
这种方式会重新进入onCreate方法.

(2) 系统源码提供的方式:

    public void updateLocale(Locale locale) {
        try {
            IActivityManager am = ActivityManagerNative.getDefault();
            Configuration config = am.getConfiguration();

            config.locale = locale;

            am.updateConfiguration(config);
            BackupManager.dataChanged("com.android.providers.settings");
        } catch (RemoteException e) {
        }
    }

这时系统会提示找不到IActivityManager与ActivityManagerNative, 我们需要引入layoutlib包, 如何导入?请参考上面如何使用SystemProperties中的介绍, 导入layoutlib包. 同样此方法同样需要权限:android.permission.CHANGE_CONFIGURATION
重新编译一下, 这时就可以正常使用.

使用方法将系统语言改为英文:
Locale locale = Locale.US;
setLanguage(locale);

或者:
Locale locale = Locale.US;
updateLocale(locale);

这两种方式都可以改变系统语言, 大家可以任选一种.

二. android studio 为应用添加系统权限(添加系统签名)

1.在AndroidManifest.xml中的manifest节点下添加:

android:sharedUserId="android.uid.system"

2.生成签名文件
点击build–>generate Signed APK进入下图:

android 如何修改系统语言_第1张图片

点击 Create new..按钮进入:

android 如何修改系统语言_第2张图片

填写完相应信息, 点击确定, 点击next会在你选择的路径下生成demo.jks文件.
在这里假设路径为 /home/downloads/share/

3.集成系统签名需要的文件
(1) 让Android Studio集成系统签名,需要用到一个工具keytool-importkeypair 下载地址
将压缩包下载下来, 解压到jks文件所在的路径 /home/downloads/share/下.
(2) platform.x509.pem、platform.pk8
这两个文件位于系统源码中, 路径为../build/target/product/security. 我是将系统源码下载下来得到.
将这两个文件同样copy到jks文件所在的路径下. 此时 keytool-importkeypair, platform.x509.pem, platform.pk8和demo.jks在同一目录下

4.生成系统签名文件
在终端进入上面文件所在的目录, 运行下面命令:

./keytool-importkeypair -k demo.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias demo

命令说明: ./keytool-importkeypair -k [jks文件名] -p [jks的密码] -pk8 platform.pk8 -cert platform.x509.pem -alias [jks的别名]

运行完这条命令, 我们就得到系统签名文件了. 注意: 在window系统中是不能使用上面的命令, 也就是说不能使用keytool-importkeypair工具, 你需要将上面的keytool-importkeypair, platform.x509.pem, platform.pk8和demo.jks文件copy到linux系统下运行上面命令生成系统签名文件再将签名文件copy出来.

5.配置gradle(app)
添加signingConfigs配置, 填写jks的路径,密码,别名

android 如何修改系统语言_第3张图片

还需要说一点, 生成的系统签名文件最好放到app的根目录下, 我这里在根目录下新建文件夹Signature, 将系统签名文件放到此目录下.

6.如果想直接Run app就是release版且带系统签名的apk,还需修改:
(1) 将app的编译模式改为release
(2) 修改buildTypes:

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        signingConfig signingConfigs.release
    }
}

至此给应用系统签名介绍完毕. 如有问题欢迎留言.

你可能感兴趣的:(android,应用)