Android N,O,P开机语言随SIM卡自适应

Android N 首次开机不随SIM卡自适应语言

Android N和Android M上一样默认设计首次开机不会随Sim卡自适应语言,如要修改为随Sim卡自适应,可参考如下修改(Android N上language与M上有较大变化,可以同时选择多种语言,所以修改方案与M上也有所不同)。

如果修改之后发现首次开机仍然无法自适应语言且版本是有安装GMS包, 请将下面的canUpdateLocale()函数中的“return !(userHasPersistedLocale() || isDeviceProvisioned(context));” 修改为"return !(userHasPersistedLocale() && isDeviceProvisioned(context));"

Android N修改方案

  1. /frameworks/opt/telephony/src/java/com/android/internal/telephony/MccTable.java
/**
 * Updates MCC and MNC device configuration information for application retrieving
 * correct version of resources.  If MCC is 0, MCC and MNC will be ignored (not set).
 * @param context Context to act on.
 * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
 * @param fromServiceState true if coming from the radio service state, false if from SIM
 */
public static void updateMccMncConfiguration(Context context, String mccmnc,
        boolean fromServiceState) {
    Slog.d(LOG_TAG, "updateMccMncConfiguration mccmnc='" + mccmnc + "' fromServiceState=" + fromServiceState);
    ...
        try {
            mcc = Integer.parseInt(mccmnc.substring(0,3));
            mnc = Integer.parseInt(mccmnc.substring(3));
        } catch (NumberFormatException e) {
            Slog.e(LOG_TAG, "Error parsing IMSI: " + mccmnc);
            return;
        }

        Slog.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
        Locale mccLocale = null; //添加这行
        if (mcc != 0) {
            setTimezoneFromMccIfNeeded(context, mcc);
            mccLocale = getLocaleFromMcc(context, mcc); //添加这行
        }
        if (fromServiceState) {
            setWifiCountryCodeFromMcc(context, mcc);
        } else {
            // from SIM
            try {
                Configuration config = new Configuration();
                boolean updateConfig = false;
                if (mcc != 0) {
                    config.mcc = mcc;
                    config.mnc = mnc == 0 ? Configuration.MNC_ZERO : mnc;
                    updateConfig = true;
                }
                if (mccLocale != null) { //添加这行
                    Configuration conLocale = new Configuration(); //添加这行
                    conLocale = ActivityManagerNative.getDefault().getConfiguration(); //添加这行
                    LocaleList userLocale = conLocale.getLocales(); //添加这行
                    LocaleList newUserLocale = new LocaleList(mccLocale,userLocale); //添加这行
                    config.setLocales(newUserLocale); //添加这行
                    updateConfig = true; //添加这行
                } //添加这行
                if (updateConfig) {
                    Slog.d(LOG_TAG, "updateMccMncConfiguration updateConfig config=" + config);
                    ActivityManagerNative.getDefault().updateConfiguration(config);
                } else {
                    Slog.d(LOG_TAG, "updateMccMncConfiguration nothing to update");
                }
            } catch (RemoteException e) {
                Slog.e(LOG_TAG, "Can't update configuration", e);
            }
        }
    } else {
        if (fromServiceState) {
            // an empty mccmnc means no signal - tell wifi we don't know
            setWifiCountryCodeFromMcc(context, 0);
        }
    }
}
//添加函数 begin
private static boolean canUpdateLocale(Context context) {
    return !(userHasPersistedLocale() || isDeviceProvisioned(context));
}

private static boolean userHasPersistedLocale() {
    String persistSysLanguage = SystemProperties.get("persist.sys.locale", "");
    String persistSysCountry = SystemProperties.get("persist.sys.country", "");
    return !(persistSysLanguage.isEmpty() && persistSysCountry.isEmpty());
}

private static boolean isDeviceProvisioned(Context context) {
    try {
        return Settings.Global.getInt(
            context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED) != 0;
    } catch (Settings.SettingNotFoundException e) {
        return false;
    }
}
// 添加函数 end

private static Locale getLocaleForLanguageCountry(Context context, String language,
        String country) {
    if (language == null) {
        Slog.d(LOG_TAG, "getLocaleForLanguageCountry: skipping no language");
        return null; // no match possible
    }
    if (country == null) {
        country = ""; // The Locale constructor throws if passed null.
    }
    if(!canUpdateLocale()){ //添加这行
        return null; //添加这行
    } //添加这行
    final Locale target = new Locale(language, country);
    ...
    return null;
}

  1. frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
            boolean initLocale, boolean persistent, int userId, boolean deferResume) {
    int changes = 0;
    ...
        if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) { // 删除这行
        if (!initLocale && !values.getLocales().isEmpty()) { //添加这行
            final LocaleList locales = values.getLocales();
            int bestLocaleIndex = 0;
            if (locales.size() > 1) {
                if (mSupportedSystemLocales == null) {
                    mSupportedSystemLocales =
                            Resources.getSystem().getAssets().getLocales();
                }
                bestLocaleIndex = Math.max(0,
                        locales.getFirstMatchIndex(mSupportedSystemLocales));
            }
            if(values.userSetLocale){ //添加这行
                SystemProperties.set("persist.sys.locale", //添加这行
                    locales.get(bestLocaleIndex).toLanguageTag()); //添加这行
            }else{ //添加这行
                SystemProperties.set("persist.sys.simLocale", //添加这行
                    locales.get(bestLocaleIndex).toLanguageTag()); //添加这行
            } //添加这行
            SystemProperties.set("persist.sys.locale", //删除这行
                    locales.get(bestLocaleIndex).toLanguageTag()); // 删除这行
            LocaleList.setDefault(locales, bestLocaleIndex);
            mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG,
                    locales.get(bestLocaleIndex)));
        }
    ...
  1. /frameworks/base/core/jni/AndroidRuntime.cpp
const std::string readLocale()
{
    const std::string locale = getProperty("persist.sys.locale", "");
    if (!locale.empty()) {
        return locale;
    }

    const std::string language = getProperty("persist.sys.language", "");
    if (!language.empty()) {
        const std::string country = getProperty("persist.sys.country", "");
        const std::string variant = getProperty("persist.sys.localevar", "");

        std::string out = language;
        if (!country.empty()) {
            out = out + "-" + country;
        }

        if (!variant.empty()) {
            out = out + "-" + variant;
        }

        return out;
    }
    const std::string simLocale = getProperty("persist.sys.simLocale", ""); //添加这行
    if (!simLocale.empty()) { //添加这行
        return simLocale; //添加这行
    } //添加这行
    const std::string productLocale = getProperty("ro.product.locale", "");
    if (!productLocale.empty()) {
        return productLocale;
    }

    ...
}

Android O,P首次开机不随SIM卡自适应语言

Android O、P上的修改与Android N上一样,只是方法名不同

Android O修改方案

  1. /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
            boolean persistent, int userId, boolean deferResume) {
    ...
    // 要修改的代码完全一致
    
}

Android P修改方案

/** Update default (global) configuration and notify listeners about changes. */
private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
        boolean persistent, int userId, boolean deferResume) {
    mTempConfig.setTo(getGlobalConfiguration());
    final int changes = mTempConfig.updateFrom(values);
    // 要修改的代码完全一致
    ...
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要监听 Android 设备的 SIM 卡状态,可以使用 `PhoneStateListener` 类。以下是一个示例代码: ```java import android.content.Context; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; public class SimStateReceiver { private static final String TAG = "SimStateReceiver"; private Context mContext; private TelephonyManager mTelephonyManager; private PhoneStateListener mPhoneStateListener; public SimStateReceiver(Context context) { mContext = context; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mPhoneStateListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String phoneNumber) { super.onCallStateChanged(state, phoneNumber); Log.d(TAG, "onCallStateChanged: state = " + state + ", phoneNumber = " + phoneNumber); } @Override public void onServiceStateChanged(ServiceState serviceState) { super.onServiceStateChanged(serviceState); Log.d(TAG, "onServiceStateChanged: serviceState = " + serviceState); } @Override public void onSimStateChanged(int state) { super.onSimStateChanged(state); Log.d(TAG, "onSimStateChanged: state = " + state); switch (state) { case TelephonyManager.SIM_STATE_ABSENT: // SIM 卡不存在或未插入 break; case TelephonyManager.SIM_STATE_NETWORK_LOCKED: // SIM 卡已被网络锁定 break; case TelephonyManager.SIM_STATE_PIN_REQUIRED: // SIM 卡需要 PIN 解锁 break; case TelephonyManager.SIM_STATE_PUK_REQUIRED: // SIM 卡需要 PUK 解锁 break; case TelephonyManager.SIM_STATE_READY: // SIM 卡已准备好 break; case TelephonyManager.SIM_STATE_UNKNOWN: // SIM 卡状态未知 break; } } }; } public void start() { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE | PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIM_STATE); } public void stop() { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); } } ``` 在上面的代码中,我们创建了一个 `SimStateReceiver` 类,它有一个 `start()` 方法和一个 `stop()` 方法,用于开始和停止监听 SIM 卡状态。在 `SimStateReceiver` 的构造方法中,我们创建了一个 `PhoneStateListener` 对象,并重写了其中的 `onSimStateChanged()` 方法,用于监听 SIM 卡状态的变化。在 `onSimStateChanged()` 方法中,我们根据不同的 SIM 卡状态打印不同的日志信息。最后,在 `start()` 方法中,我们通过 `TelephonyManager` 的 `listen()` 方法注册了 `PhoneStateListener` 对象,开始监听 SIM 卡状态。在 `stop()` 方法中,我们通过 `TelephonyManager` 的 `listen()` 方法取消了 `PhoneStateListener` 对象的注册,停止监听 SIM 卡状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值