zoukankan      html  css  js  c++  java
  • 解决:Android4.3锁屏界面Emergency calls only


            从图片中我们能够看到,这里在语义上有一定的反复,当然这是谷歌的原始设计。这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,只是因为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);
        }
    上述加粗标红的代码就是我们须要作出改动的位置。














  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6883876.html
Copyright © 2011-2022 走看看