从图片中我们可以看到,这里在语义上有一定的重复,当然这是谷歌的原始设计。这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,不过由于Android4.3在锁屏功能上比起老版本做了很大的改动,而且通过常规方法(Strings.xml中字符串)对该问题的定位会有很大的难度,拿这个界面来说,EMERGENCY CALL并不是Strings中值,而是  <string name="lockscreen_emergency_call">Emergency call</string>,只是在显示的时候进行了大小写的转换。而且例如字符”-“在String.xml中是unicode编码表示的。例如:    <string name="kg_text_message_separator" product="default">" \u2014 "</string>。接下来我们对当前锁屏界面相关代码的定位进行一个简单的了解:

在Android4.3当中当前的锁屏界面不是一个Activity而是一个View,该View位于/frameworks/base/policy/src/com/android/internal/policy/impl/keyguard目录下的KeyguardPatternView.java,其所对应的布局文件为keyguard_pattern_view.xml.

<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->

<!-- This is the screen that shows the 9 circle unlock widget and instructs
     the user how to unlock their device, or make an emergency call.  This
     is the portrait layout.  -->
<com.android.internal.policy.impl.keyguard.KeyguardPatternView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyguard_pattern_view"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_maxWidth="@dimen/keyguard_security_width"
    android:layout_maxHeight="@dimen/keyguard_security_height"
    android:gravity="center_horizontal"
    android:contentDescription="@string/keyguard_accessibility_pattern_unlock">

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

<LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:orientation="vertical"
            android:layout_gravity="center">

<include layout="@layout/keyguard_message_area"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
               />

<FrameLayout
             android:id="@+id/keyguard_bouncer_frame"
             android:background="@*android:drawable/kg_bouncer_bg_white"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1"
             >
            <com.android.internal.widget.LockPatternView
                android:id="@+id/lockPatternView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:layout_marginEnd="8dip"
                android:layout_marginBottom="4dip"
                android:layout_marginStart="8dip"
                android:layout_gravity="center_horizontal"
                android:gravity="center"
                android:contentDescription="@string/keyguard_accessibility_pattern_area" />
          </FrameLayout>
          <include layout="@layout/keyguard_eca"
              android:id="@+id/keyguard_selector_fade_container"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:layout_gravity="bottom|center_horizontal"
              android:gravity="center_horizontal" />
        </LinearLayout>
    </FrameLayout>

</com.android.internal.policy.impl.keyguard.KeyguardPatternView>

而keyguard_eca即使我们需要修改的锁屏界面下的紧急拨号按钮所对应的布局Alias.xml中的keyguard_emergency_carrier_area.xml布局。

Alias.xml:

<resources>
    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
    <item type="layout" name="keyguard_eca">@android:layout/keyguard_emergency_carrier_area</item>
</resources>
keyguard_emergency_carrier_area.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2012, The Android Open Source Project
** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
** Not a Contribution.
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->

<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
<com.android.internal.policy.impl.keyguard.EmergencyCarrierArea
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_gravity="center_horizontal"
    android:layout_alignParentBottom="true"
    android:clickable="true">

<!-- Used only for Multi Sim case -->
    <ViewStub android:id="@+id/stub_msim_carrier_text"
        android:inflatedId="@+id/msim_keyguard_carrier_area"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/msim_keyguard_carrier_area" />

  <com.android.internal.policy.impl.keyguard.CarrierText
        android:id="@+id/carrier_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="@dimen/kg_status_line_font_size"
        android:textColor="?android:attr/textColorSecondary"/>

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="-10dip"
        style="?android:attr/buttonBarStyle"
        android:orientation="horizontal"
        android:gravity="center"
        android:weightSum="2">

<com.android.internal.policy.impl.keyguard.EmergencyButton
            android:id="@+id/emergency_call_button"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
            android:text="@string/kg_emergency_call_label"
            style="?android:attr/buttonBarButtonStyle"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textSize="@dimen/kg_status_line_font_size"
            android:textColor="?android:attr/textColorSecondary"
            android:drawablePadding="8dip" />

<Button android:id="@+id/forgot_password_button"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:drawableLeft="@*android:drawable/lockscreen_forgot_password_button"
            style="?android:attr/buttonBarButtonStyle"
            android:textSize="@dimen/kg_status_line_font_size"
            android:textColor="?android:attr/textColorSecondary"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:drawablePadding="8dip"
            android:visibility="gone"/>
    </LinearLayout>

</com.android.internal.policy.impl.keyguard.EmergencyCarrierArea>
上述代码中的CarrierText即是我们需要着的控件,它继承自TextView。

package com.android.internal.policy.impl.keyguard;

import android.content.Context;
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

import com.android.internal.R;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;

public class CarrierText extends TextView {
    private static final String TAG = "CarrierText";
    private static CharSequence mSeparator;

private LockPatternUtils mLockPatternUtils;

protected boolean mAirplaneMode;

// For prop key to show carrier.
    static final String PROP_KEY_SHOW_CARRIER = "persist.env.sys.SHOW_CARRIER";
    static final String PROP_ENV_SPEC = SystemProperties.get("persist.env.spec");

static final int ORIGIN_CARRIER_NAME_ID = R.array.origin_carrier_names;
    static final int LOCALE_CARRIER_NAME_ID = R.array.locale_carrier_names;
    static final int LOCKSCREEN_CARRIER_DEFAULT_ID =
            R.string.lockscreen_carrier_default;

private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
        private CharSequence mPlmn;
        private CharSequence mSpn;
        private State mSimState;

@Override
        public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
            mPlmn = plmn;
            mSpn = spn;
            updateCarrierText(mSimState, mPlmn, mSpn);
        }

@Override
        public void onSimStateChanged(IccCardConstants.State simState) {
            mSimState = simState;
            updateCarrierText(mSimState, mPlmn, mSpn);
        }

@Override
        void onAirplaneModeChanged(boolean on) {
            mAirplaneMode = on;
            updateCarrierText(mSimState, mPlmn, mSpn);
        }
    };
    /**
     * The status of this lock screen. Primarily used for widgets on LockScreen.
     */
    private static enum StatusMode {
        Normal, // Normal case (sim card present, it's not locked)
        PersoLocked, // SIM card is 'perso locked'.
        SimMissing, // SIM card is missing.
        SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
        SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
        SimLocked, // SIM card is currently locked
        SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
        SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
        SimIOError; //The sim card is faulty
    }

public CarrierText(Context context) {
        this(context, null);
    }

public CarrierText(Context context, AttributeSet attrs) {
        super(context, attrs);
        mLockPatternUtils = new LockPatternUtils(mContext);
        try {
            mAirplaneMode = Settings.System.getInt(mContext.getContentResolver(),
                    Settings.System.AIRPLANE_MODE_ON) == 1;
        } catch (SettingNotFoundException snfe) {
            Log.e(TAG, "get airplane mode exception");
        }
    }

protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) {
        CharSequence text = "";

if (mAirplaneMode) {
            // if airplane mode is on, show "airplane mode"
            text = getContext().getText(R.string.lockscreen_airplane_mode_on);
        } else {
            text = getCarrierTextForSimState(simState, plmn, spn);
        }

setText(text);
    }

@Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mSeparator = getResources().getString(R.string.kg_text_message_separator);
        setSelected(true); // Allow marquee to work.
    }

@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (KeyguardUpdateMonitor.sIsMultiSimEnabled) {
            return;
        }
        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback);
    }

@Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
    }

/**
     * Top-level function for creating carrier text. Makes text based on simState, PLMN
     * and SPN as well as device capabilities, such as being emergency call capable.
     *
     * @param simState
     * @param plmn
     * @param spn
     * @return
     */
    protected CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
            CharSequence plmn, CharSequence spn) {
        CharSequence carrierText = null;
        StatusMode status = getStatusForIccState(simState);

Log.d(TAG, "getCarrierTextForSimState, plmn: " + plmn + ", spn: " + spn);
        String localPlmn = null;
        if (plmn != null) {
            localPlmn= mContext.getLocalString(plmn.toString(),
                com.android.internal.R.array.origin_carrier_names,
                com.android.internal.R.array.locale_carrier_names);
        }
        String localSpn = null;
        if (spn != null) {
            localSpn= mContext.getLocalString(spn.toString(),
                com.android.internal.R.array.origin_carrier_names,
                com.android.internal.R.array.locale_carrier_names);
        }
        Log.d(TAG, "getCarrierTextForSimState, localPlmn: "
            + localPlmn + ", localSpn: " + localSpn);

int resTextIdOfNoSimCard = R.string.lockscreen_missing_sim_message_short;
        if (PROP_ENV_SPEC.equalsIgnoreCase("ChinaTelecom")) {
            resTextIdOfNoSimCard = R.string.lockscreen_missing_uim_message_short;
        }

// For CMCC requirement to show 3G in plmn if camping in TD_SCDMA.
        TelephonyManager tm =  (TelephonyManager)getContext()
                .getSystemService(Context.TELEPHONY_SERVICE);
        boolean show3G = !mAirplaneMode && tm != null && plmn != null &&
                tm.getVoiceNetworkType() == TelephonyManager.NETWORK_TYPE_TD_SCDMA;
        if (show3G && localPlmn != null) {
            localPlmn = localPlmn + " 3G";
        }

switch (status) {
            case Normal:
                carrierText = concatenate(localPlmn, localSpn);
                break;

case SimNotReady:
                carrierText = null; // nothing to display yet.
                break;

case PersoLocked:
                carrierText = makeCarrierStringOnEmergencyCapable(
                        getContext().getText(R.string.lockscreen_perso_locked_message),
                        plmn);
                break;

case SimMissing:
                // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
                // This depends on mPlmn containing the text "Emergency calls only" when the radio
                // has some connectivity. Otherwise, it should be null or empty and just show
                // "No SIM card"
                carrierText =  makeCarrierStringOnEmergencyCapable(
                        getContext().getText(resTextIdOfNoSimCard),
                        plmn);
                break;

case SimPermDisabled:
                carrierText = getContext().getText(
                        R.string.lockscreen_permanent_disabled_sim_message_short);
                break;

case SimMissingLocked:
                carrierText =  makeCarrierStringOnEmergencyCapable(
                        getContext().getText(resTextIdOfNoSimCard),
                        plmn);
                break;

case SimLocked:
                carrierText = makeCarrierStringOnEmergencyCapable(
                        getContext().getText(R.string.lockscreen_sim_locked_message),
                        plmn);
                break;

case SimPukLocked:
                carrierText = makeCarrierStringOnEmergencyCapable(
                        getContext().getText(R.string.lockscreen_sim_puk_locked_message),
                        plmn);
                break;

case SimIOError:
                carrierText = makeCarrierStringOnEmergencyCapable(
                        getContext().getText(R.string.lockscreen_sim_error_message_short),
                        plmn);
                break;
        }

return carrierText;
    }

/*
     * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
     */
    private CharSequence makeCarrierStringOnEmergencyCapable(
            CharSequence simMessage, CharSequence emergencyCallMessage) {
        if (mLockPatternUtils.isEmergencyCallCapable()) {
            return concatenate(simMessage, emergencyCallMessage);
        }
        return simMessage;
    }

/**
     * Determine the current status of the lock screen given the SIM state and other stuff.
     */
    private StatusMode getStatusForIccState(IccCardConstants.State simState) {
        // Since reading the SIM may take a while, we assume it is present until told otherwise.
        if (simState == null) {
            return StatusMode.Normal;
        }

final boolean missingAndNotProvisioned =
                !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned()
                && (simState == IccCardConstants.State.ABSENT ||
                        simState == IccCardConstants.State.PERM_DISABLED);

// Assume we're PERSO_LOCKED if not provisioned
        simState = missingAndNotProvisioned ? IccCardConstants.State.PERSO_LOCKED : simState;
        switch (simState) {
            case ABSENT:
                return StatusMode.SimMissing;
            case PERSO_LOCKED:
                return StatusMode.PersoLocked;
            case NOT_READY:
                return StatusMode.SimNotReady;
            case PIN_REQUIRED:
                return StatusMode.SimLocked;
            case PUK_REQUIRED:
                return StatusMode.SimPukLocked;
            case READY:
                return StatusMode.Normal;
            case PERM_DISABLED:
                return StatusMode.SimPermDisabled;
            case UNKNOWN:
                return StatusMode.SimMissing;
            case CARD_IO_ERROR:
                return StatusMode.SimIOError;
        }
        return StatusMode.SimMissing;
    }

    private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
        final boolean plmnValid = !TextUtils.isEmpty(plmn);
        final boolean spnValid = !TextUtils.isEmpty(spn);
        /*if (plmnValid && spnValid) {
            return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
        } else if (plmnValid) {
            return plmn;
        } else if (spnValid) {
            return spn;
        } else {
            return "";
        }*/

if (spnValid) {
            return spn;
        } else {
            return "";
        }
    }

private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
            String plmn, String spn) {
        int carrierHelpTextId = 0;
        StatusMode status = getStatusForIccState(simState);
        switch (status) {
            case PersoLocked:
                carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
                break;

case SimMissing:
                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
                break;

case SimPermDisabled:
                carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
                break;

case SimMissingLocked:
                carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
                break;

case Normal:
            case SimLocked:
            case SimPukLocked:
                break;
        }

return mContext.getText(carrierHelpTextId);
    }
上述加粗标红的代码就是我们需要作出修改的位置。

解决:Android4.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义重复相关推荐

  1. 关于“android4.0中,在通话界面进入锁屏界面后出现两个电话图标”这一Bug的解决方法

    bug名称: android4.0中,在通话界面进入锁屏界面后出现两个电话图标          1. 问题出现的流程与原因:             在通话界面中熄屏后第一次点亮屏幕时会出现二个电话 ...

  2. 联想台式电脑开机时不显示主板logo直接黑屏进入锁屏界面因此无法进入bios模式解决方法

    问题:公司让我熟悉一下linux系统指令 因此我就打算在公司的机子上装上虚拟机,但是使用VMware软件时,可能会出现一些小问题,导致虚拟机无法打开,就像下图这样:  解决1:在网上查了很久,都说先重 ...

  3. 解决win10笔记本电脑开机要黑屏一段时间才显示锁屏界面的方案

    本人使用的电脑为华硕笔记本,核显+独显,全是英特尔平台 首先这个问题不大,但是每次开机动画后就黑屏需要等很久才能进入锁屏界面然后开启系统,赶时间的话真的让人心烦 我实在受不了了... 我查了几种方案全 ...

  4. android开发笔记之锁屏界面未读短信未接来电提醒(android 4.4)

    客户需求 最近在做一个项目,android 4.4系统,客户要求在锁屏界面有未读短信未接来电的提醒功能.而平台没有此功能,要自己实现.并且时间非常紧,---.(其实软件工程师基本上都是这样,坑,坑,坑 ...

  5. android开发 自定义锁屏界面,插件锁屏桌面自定义 “安卓4.0”界面美化教程

    距离Android4.0系统的正式发布已经过去一段时间,除了最先搭载该系统的三星Galaxy Nexus.华为荣耀Android4.0商用版以及小米手机MIUI4.0等,多数用户目前仍然处于观望阶段. ...

  6. Android 屏蔽锁屏界面上的通知显示

    一. 前言 [定制需求描述]:在插入SD后,  锁屏状态下, 去掉提示"SD卡可用于传输照片和媒体文件" 需求拆解:  要求正常显示在SystemUI下拉状态栏,  只需要屏蔽在锁 ...

  7. 联想拯救者y7000电脑开机一直是锁屏界面,点一下就黑屏,无法进入输密码界面

    开机时时锁屏界面,点一下就黑屏,一直循环,无法进入输密码的界面 解决办法:拔掉电源,按开机键20秒,在插上电源开机

  8. 【2022年】Win11修改锁屏界面、登录界面背景图片方法(亲测有效)

    最近想给自己的电脑换个壁纸,桌面壁纸自定义已经玩的很熟了,就想设置一个登录界面的壁纸.毕竟每次锁屏(win+L),或者是开机输密码的时候都是那个大蓝色背景(见图1),看久了也累了.故作此文. 起因 本 ...

  9. android锁屏快捷键设置,Android4.0+锁屏程序开发——设置锁屏页面篇

    [如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...

  10. 【设置一个类似手机的锁屏界面但又不知道如何操作——下载加速吧】

    对于很多公共办公场所来说,经常会需求临时离开一会,比如去喝水或者上厕所.如果这个时候,我们希望电脑上的东西部被他们动到或者看到该怎么办呢?这是今日有网友问到的一个类似问题,网友希望在离开的时候,可以设 ...

最新文章

  1. L1-047 装睡 (结构体解决)
  2. 逻辑结构图向关系转换规则3
  3. python语法笔记(一)
  4. SSH-KeyGen 的用法
  5. python判断一个或者多个字符串,是否出现在一段话中
  6. MATLAB之线性回归,逻辑回归,最小二乘法,梯度下降,贝叶斯,最大似然估计
  7. 贷款审批到底会考核哪些内容?
  8. ssm使用全注解实现增删改查案例——DeptMapperImpl
  9. 二分法求近似根c语言程序,求一C++风格程序,用二分法求f(x)=0的根
  10. php框架大全图解_PHP框架汇总 - 鱼煎的个人空间 - OSCHINA - 中文开源技术交流社区...
  11. tensorflow随笔——交叉熵公式推导
  12. struts2登录注册示例_Struts2资源包和本地化示例
  13. vant-ui的list
  14. Java的Appium自动化测试教程
  15. MATLAB绘制散点图
  16. 【面包板电子制作130例仿真】简单变调电子门铃
  17. ajax的Provisional headers are shown
  18. 拔丝芋头的Java学习日记---Day8
  19. 批量操作:ps怎么(如何)导入图片的方法
  20. 求负片灰度扩展幂律变换

热门文章

  1. 【复合五点高斯-勒让德公式】
  2. Edge浏览器设置网速限制
  3. 银河麒麟V10-sp1服务器操作系统桌面环境安装
  4. 独木舟上的旅行(贪心)C/C++
  5. 【中间件】pika安装及性能测试
  6. 社群裂变营销活动如何提升用户信任度?
  7. android手机碎片管理,android手机需要进行磁盘碎片整理么
  8. 博客群建,SEO多用户博客群建-skycc多用户博客群建系统
  9. Jeg lurer p? om vi skulle v?re ? parajumpers jakke tenke p? hva som kan
  10. ffmpeg生成裸眼3D、伪3D视频