生活中我们会发现一个现象,手机到了某个电量的时候就会进行提醒(比如说我的手机到了15%和5%的电量时都会有电量提醒),这个功能能够告诉用户:“该充电了!”。但是我最经就遇到了一个问题,因为我做了一个小屏终端(比240*320还小的),所以有很多东西都显示不全,出这个提醒的时候不但会状态栏变空(因为有通知,而客户是不需要的),还会出现一个问题——会有三个横线把屏幕给遮挡了(因为发了通知之后显示不全),那这个问题就得改了。
根据经验,这个功能应该是在systemui下实现的,果不其然,在alps/frameworks/base/packages/SystemUI/src/com/android/systemui/power这个目录下有两个文件:PowerNotificationWarnings.java和PowerUI.java,里面就有关于该功能的实现。
首先在PowerUI.java中有一个广播接收器里面有关于各种状态的操作:
private final class Receiver extends BroadcastReceiver {
public void init() {
// Register for Intent broadcasts for...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.registerReceiver(this, filter, null, mHandler);
updateSaverMode();
}
private void updateSaverMode() {
setSaverMode(mPowerManager.isPowerSaveMode());
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
final int oldBatteryLevel = mBatteryLevel;
mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
final int oldBatteryStatus = mBatteryStatus;
mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
final int oldPlugType = mPlugType;
mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
final int oldInvalidCharger = mInvalidCharger;
mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
final boolean plugged = mPlugType != 0;
final boolean oldPlugged = oldPlugType != 0;
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
if (DEBUG) {
Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
}
mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
Slog.d(TAG, "showing invalid charger warning");
mWarnings.showInvalidChargerWarning();
return;
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
mWarnings.dismissInvalidChargerWarning();
} else if (mWarnings.isInvalidChargerWarningShowing()) {
// if invalid charger is showing, don't show low battery
return;
}
if (!plugged
&& (bucket < oldBucket || oldPlugged)
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& bucket < 0) {
// only play SFX when the dialog comes up or the bucket changes
final boolean playSound = bucket != oldBucket || oldPlugged;
mWarnings.showLowBatteryWarning(playSound);
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
mWarnings.dismissLowBatteryWarning();
} else {
mWarnings.updateLowBatteryWarning();
}
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mScreenOffTime = SystemClock.elapsedRealtime();
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenOffTime = -1;
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mWarnings.userSwitched();
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
updateSaverMode();
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGING.equals(action)) {
setSaverMode(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
} else {
Slog.w(TAG, "unknown intent: " + intent);
}
}
};
我们可以看到其中有一句:
mWarnings.showLowBatteryWarning(playSound);
这里就是发生警告的地方。
我们来看一下这个方法从何而来,在PowerUI.java类中有一个接口:
public interface WarningsUI {
void update(int batteryLevel, int bucket, long screenOffTime);
void showSaverMode(boolean mode);
void dismissLowBatteryWarning();
void showLowBatteryWarning(boolean playSound);
void dismissInvalidChargerWarning();
void showInvalidChargerWarning();
void updateLowBatteryWarning();
boolean isInvalidChargerWarningShowing();
void dump(PrintWriter pw);
void userSwitched();
}
showLowBatteryWarning方法就在其中,那哪个类有实现了该方法呢,就是该包中的另一个类PowerNotificationWarnings.java了:
public class PowerNotificationWarnings implements PowerUI.WarningsUI
在该类中也有具体功能的一些实现,比如15%电量的警告或者5%电量的警告等:
152 private void showInvalidChargerNotification() {
153 final Notification.Builder nb = new Notification.Builder(mContext)
154 .setSmallIcon(R.drawable.ic_power_low)
155 .setWhen(0)
156 .setShowWhen(false)
157 .setOngoing(true)
158 .setContentTitle(mContext.getString(R.string.invalid_charger_title))
159 .setContentText(mContext.getString(R.string.invalid_charger_text))
160 .setPriority(Notification.PRIORITY_MAX)
161 .setVisibility(Notification.VISIBILITY_PUBLIC)
162 .setColor(mContext.getColor(
163 com.android.internal.R.color.system_notification_accent_color));
164 final Notification n = nb.build();
165 if (n.headsUpContentView != null) {
166 n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
167 }
168 mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
169 }
170
171 private void showWarningNotification() {
172 final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started
173 : R.string.battery_low_percent_format;
174 final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0);
175 final Notification.Builder nb = new Notification.Builder(mContext)
176 .setSmallIcon(R.drawable.ic_power_low)
177 // Bump the notification when the bucket dropped.
178 .setWhen(mBucketDroppedNegativeTimeMs)
179 .setShowWhen(false)
180 .setContentTitle(mContext.getString(R.string.battery_low_title))
181 .setContentText(mContext.getString(textRes, percentage))
182 .setOnlyAlertOnce(true)
183 .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
184 .setPriority(Notification.PRIORITY_MAX)
185 .setVisibility(Notification.VISIBILITY_PUBLIC)
186 .setColor(mContext.getColor(
187 com.android.internal.R.color.battery_saver_mode_color));
188 if (hasBatterySettings()) {
189 nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
190 }
191 if (!mSaver) {
192 nb.addAction(0,
193 mContext.getString(R.string.battery_saver_start_action),
194 pendingBroadcast(ACTION_START_SAVER));
195 } else {
196 addStopSaverAction(nb);
197 }
198 if (mPlaySound) {
199 attachLowBatterySound(nb);
200 mPlaySound = false;
201 }
202 final Notification n = nb.build();
203 if (n.headsUpContentView != null) {
204 n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
205 }
206 mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
207 }
208
209 private void showSaverNotification() {
210 final Notification.Builder nb = new Notification.Builder(mContext)
211 .setSmallIcon(R.drawable.ic_power_saver)
212 .setContentTitle(mContext.getString(R.string.battery_saver_notification_title))
213 .setContentText(mContext.getString(R.string.battery_saver_notification_text))
214 .setOngoing(true)
215 .setShowWhen(false)
216 .setVisibility(Notification.VISIBILITY_PUBLIC)
217 .setColor(mContext.getColor(
218 com.android.internal.R.color.battery_saver_mode_color));
219 addStopSaverAction(nb);
220 if (hasSaverSettings()) {
221 nb.setContentIntent(pendingActivity(mOpenSaverSettings));
222 }
223 mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
224 }
找到位置了那修改起来就简单了,把mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);注释掉让它不能发通知就行了。
本文探讨了小屏终端设备遇到电量提醒导致界面显示问题的情况。通常,电量提醒功能在SystemUI下实现,通过分析alps/frameworks/base/packages/SystemUI源代码,发现PowerUI.java中的广播接收器处理电量警告。通过修改PowerNotificationWarnings.java中的showLowBatteryWarning方法,注释掉发送通知的代码,可以解决小屏设备因电量提醒遮挡屏幕的问题。

2218

被折叠的 条评论
为什么被折叠?



