解决:Android4.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义反复
从图片中我们能够看到,这里在语义上有一定的反复,当然这是谷歌的原始设计。这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,只是因为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语义反复的更多相关文章
- 解决:Android4.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义重复
从图片中我们可以看到,这里在语义上有一定的重复,当然这是谷歌的原始设计.这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,不过由于Android4.3在锁屏功能上比起老版本做了很大的改动,而 ...
- Android4.0+锁屏程序开发——设置锁屏页面篇
[如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...
- iOS开发--QQ音乐练习,后台播放和锁屏界面
一.设置后台播放 首先允许程序后台播放 代码实现 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOpti ...
- win10锁屏界面无法更新
win10的锁屏界面都是巨硬公司推送过来的,质量还不错,最近锁屏界面无法更新,解决方案如下: 以管理员身份运行cmd,分别运行如下两个命令 del /f /s /q /a "%userpro ...
- android------锁屏(手机启动出现锁屏界面)
以前用过一个红包锁屏的软件,第一次打开手机出现锁屏,滑动领取收益,当时觉得这功能不错,就查阅资料,写了一个案例, apk运行流程: 进入软件--->启动服务--->关闭手机(可先退出应用) ...
- Android 7.1.1 锁屏界面启动流程
前几天遇到一个低概率复现锁屏界面不显示,仅仅显示状态栏的问题,跟了下锁屏界面启动显示的流程,在这分享下,也方便以后自己查看.前面简介了下Zygote启动流程, Zygote进程启动后会首先创建一个Sy ...
- Android4.0+锁屏程序开发——按键屏蔽篇
开发锁屏程序的时候我们要面临的重要问题无疑是如何屏蔽三个按键,Back,Home,Menu 看似简单的功能,实现起来却并不是那么容易. [屏蔽Back按键] 相对来说,屏蔽Back键是比较简单的,只 ...
- Qt - 锁屏界面加虚拟小键盘
一.实现效果 鼠标点击"密码输入栏",弹出虚拟键盘,输入锁屏密码后,点击虚拟键盘外部区域,则会隐藏虚拟键盘,再点击登录,成功进入主界面. 二.虚拟键盘-程序设计 2.1 frmNu ...
- RK3399 删除开机锁屏界面
CPU:RK3399 系统:Android 7.1 删除开机锁屏界面 diff --git a/frameworks/base/packages/SettingsProvider/res/values ...
随机推荐
- 关于面试总结-python笔试题
关于面试总结4-python笔试题 前言 现在面试测试岗位,一般会要求熟悉一门语言(python/java),为了考验求职者的基本功,一般会出2个笔试题,这些题目一般不难,主要考察基本功. 要是给你一 ...
- mac osx下apache下的坑: you don’t have permission to access / on this server
在Mac下Apache修改默认站点的目录时,遇到403错误, you don’t have permission to access / on this server 首先按照google到教程: 修 ...
- 在LoadRunner中执行命令行程序之:popen()取代system()
我想大家应该都知道在LoadRunner可以使用函数system()来调用系统指令,结果同在批处理里执行一样. 但是system()有个缺陷:无法获取命令的返回结果. 也许你可以用`echo comm ...
- BZOJ 4753 [Jsoi2016]最佳团体 ——01分数规划 树形DP
要求比值最大,当然用分数规划. 二分答案,转化为选取一个最大的联通块使得它们的和大于0 然后我们直接DP. 复杂度$O(n^2\log {n})$ #include <map> #incl ...
- P1373 小a和uim之大逃离 (动态规划)
题目背景 小a和uim来到雨林中探险.突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声.刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个 ...
- request.getContextPath是为了解决相对路径的问题,可返回站点的根路径
假定你的web application 名称为news,你在浏览器中输入请求路径: http://localhost:8080/news/main/list.jsp 则执行下面向行代码后打印出如下结果 ...
- rest-assured 将log()中的信息打印到log日志中去的方法
rest-assured 将log()中的信息打印到log日志中去的方法: ============方法1============== PrintStream fileOutPutStream = n ...
- MongoDB_单机版环境搭建
linux上安装MogoDB http://www.runoob.com/mongodb/mongodb-linux-install.html 在https://www.mongodb.com/dow ...
- 在 Windows 下用 TDM-GCC(MinGW)开发 DLL 涉及到数据同步锁及 DLL 初始化终止化函数的问题
在 Windows 下用 TDM-GCC(MinGW)开发 DLL 如果要用到数据同步锁,理论上可以采用 Windows API 提供的临界区实现(需要用到的函数有 InitializeCritica ...
- 用“道”的思想解决费用流问题---取/不取皆是取 (有下界->有上界) / ACdreamoj 1171
题意: 给一个矩阵,给出约束:i(0<i<n)行至少去ai个数,j行至少取bi个数,要求取的数值之和最小. 开始一见,就直接建了二分图,但是,发现这是有下界无上界最小费用流问题,肿么办.. ...