从图片中我们能够看到,这里在语义上有一定的反复,当然这是谷歌的原始设计。这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,只是因为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即使我们须要改动的锁屏界面下的紧急拨号button所相应的布局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.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义重复

    从图片中我们可以看到,这里在语义上有一定的重复,当然这是谷歌的原始设计.这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,不过由于Android4.3在锁屏功能上比起老版本做了很大的改动,而 ...

  2. Android4.0+锁屏程序开发——设置锁屏页面篇

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

  3. iOS开发--QQ音乐练习,后台播放和锁屏界面

    一.设置后台播放 首先允许程序后台播放 代码实现 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...

  4. win10锁屏界面无法更新

    win10的锁屏界面都是巨硬公司推送过来的,质量还不错,最近锁屏界面无法更新,解决方案如下: 以管理员身份运行cmd,分别运行如下两个命令 del /f /s /q /a "%userpro ...

  5. android------锁屏(手机启动出现锁屏界面)

    以前用过一个红包锁屏的软件,第一次打开手机出现锁屏,滑动领取收益,当时觉得这功能不错,就查阅资料,写了一个案例, apk运行流程: 进入软件--->启动服务--->关闭手机(可先退出应用) ...

  6. Android 7.1.1 锁屏界面启动流程

    前几天遇到一个低概率复现锁屏界面不显示,仅仅显示状态栏的问题,跟了下锁屏界面启动显示的流程,在这分享下,也方便以后自己查看.前面简介了下Zygote启动流程, Zygote进程启动后会首先创建一个Sy ...

  7. Android4.0+锁屏程序开发——按键屏蔽篇

    开发锁屏程序的时候我们要面临的重要问题无疑是如何屏蔽三个按键,Back,Home,Menu  看似简单的功能,实现起来却并不是那么容易. [屏蔽Back按键] 相对来说,屏蔽Back键是比较简单的,只 ...

  8. Qt - 锁屏界面加虚拟小键盘

    一.实现效果 鼠标点击"密码输入栏",弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,则会隐藏虚拟键盘,再点击登录,成功进入主界面. 二.虚拟键盘-程序设计 2.1 frmNu ...

  9. RK3399 删除开机锁屏界面

    CPU:RK3399 系统:Android 7.1 删除开机锁屏界面 diff --git a/frameworks/base/packages/SettingsProvider/res/values ...

随机推荐

  1. 原 jmeter中类似lr的场景设置

    有一天如果你们领导来一句给我测下这个首页到底能扛多少并发,并发量极限是多少,这时你不要慌不要忙,拿出jmeter神器,设置下场景,目标设置成1000,每10秒启动100个并发,等着看什么时候系统响应开 ...

  2. 【LeetCode】Reorder Log Files(重新排列日志文件)

    这道题是LeetCode里的第937道题. 题目描述: 你有一个日志数组 logs.每条日志都是以空格分隔的字串. 对于每条日志,其第一个字为字母数字标识符.然后,要么: 标识符后面的每个字将仅由小写 ...

  3. nginx的报错500

    500:服务器内部错误,也就是服务器遇到意外情况,而无法履行请求. 500错误一般有几种情况: 1. web脚本错误,如php语法错误,lua语法错误等. 2. 访问量大的时候,由于系统资源限制,而不 ...

  4. ICMP TYPE CODE

    TYPE CODE Description Query Error 0 0 Echo Reply——回显应答(Ping应答) x   3 0 Network Unreachable——网络不可达   ...

  5. [POJ1143]Number Game

    [POJ1143]Number Game 试题描述 Christine and Matt are playing an exciting game they just invented: the Nu ...

  6. URAL Formula 1 ——插头DP

    [题目分析] 一直听说这是插头DP入门题目. 难到爆炸. 写了2h,各种大常数,ural垫底. [代码] #include <cstdio> #include <cstring> ...

  7. BZOJ 3282 Tree ——Link-Cut Tree

    [题目分析] 明显的LCT维护连通性的题目. access的操作是比较巧妙的,可以把结点到根变成偏爱路径,而且保证了该点是链上深度最深的点. 而且需边的思想也很巧妙,保证了复杂度. 但是只能用于修改路 ...

  8. Wing IDE 6.0 算号器注册机代码

    我开发Python时喜欢用Wing IDE, 然后最近发现Wing IDE升级到6.0版本了, 但是之前能在5.1上用的算号器代码不能用在6.0上了, 所以就上网搜搜是否有相关算号器, 果然, 找到了 ...

  9. CentOS7下安装Docker-Compose No module named 'requests.packages.urllib3'

    在使用Docker的时候,有一个工具叫做  docker-compose,安装它的前提是要安装pip工具. 1.首先检查Linux有没有安装Python-pip包,直接执行 yum install p ...

  10. Spring JdbcTemplate 查询方法中的RowMapper实现汇总

    实现一.在内部建立内联类实现RowMapper接口 package hysteria.contact.dao.impl; import java.sql.ResultSet; import java. ...