我目前正在实施一项功能,要求用户忽略应用程序的电池优化。这样做的原因是,应用程序的主要功能不幸受到省电模式的严重影响。
为了实现我的目标,我通过创建Intent
并将Action
设置为ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
来提示用户。
虽然在触发Intent
之前,我同时检查isPowerSaveMode()
和isIgnoringBatteryOptimizations()
,以确保在未启用省电模式时不提示用户;这是该功能的要求。我这样做的方式是:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean isPowerSaveMode = pm.isPowerSaveMode(); // always returns false for Huawei devices
这适用于大多数设备,但对于华为设备,isPowerSaveMode()
始终返回false
。因此,由于前提条件失败,因此永远不会显示提示。
还有其他人可能遇到过此问题吗?如果是这样,你做了什么来解决它?
请注意,Xamarin.Android
SDK中也存在同样的问题。
答案 0 :(得分:1)
每个oem都会修改SDK以满足他们的需求。华为设备不使用默认的省电功能,而是使用名为" 受保护的应用"。受保护的应用程序是一组应用程序,即使在屏幕关闭时也可以运行这些应用程序。这就是它总是返回false的原因。最好将意图投射到受保护的应用程序屏幕,但无法知道您的应用程序是否已添加到受保护的应用程序列表中。 What is protected apps ?
答案 1 :(得分:0)
在实现手持设备和可穿戴设备时,我遇到了同样的问题。 我找到的唯一解决方案是为所有应用禁用节电模式。 我建议在禁用所有应用程序的此类模式后检测方法的结果。此错误仅出现在华为上。可怕的供应商。
答案 2 :(得分:0)
IntentFilter
添加自定义操作来手动请求当前华为电源模式状态并接收 change 事件的方法:(注意仅在 Huawei P20 Lite(ANE-LX3)@ EMUI 8.0.0 上进行了测试)
// Manually request Power Save Mode:
public Boolean isPowerSaveMode(Context context) {
if (Build.MANUFACTURER.equalsIgnoreCase("Huawei")) {
return isPowerSaveModeHuawei(context);
} else {
return isPowerSaveModeAndroid(context);
}
}
@TargetApi(21)
private Boolean isPowerSaveModeAndroid(Context context) {
boolean isPowerSaveMode = false;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm != null) isPowerSaveMode = pm.isPowerSaveMode();
}
return isPowerSaveMode;
}
private Boolean isPowerSaveModeHuawei(Context context) {
try {
int value = android.provider.Settings.System.getInt(context.getContentResolver(), "SmartModeStatus");
return (value == 4);
} catch (Settings.SettingNotFoundException e) {
// Setting not found? Return standard android mechanism and hope for the best...
return isPowerSaveModeAndroid(context);
}
}
// Listening for changes in Power Save Mode
public void startMonitoringPowerSaveChanges(Context context) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mPowerSaveChangeReceiver != null) {
return;
}
// Register for PowerSaver change updates.
mPowerSaveChangeReceiver = new PowerSaveChangeReceiver();
// Registering the receiver
IntentFilter filter = new IntentFilter();
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
// Add custom huawei action
filter.addAction("huawei.intent.action.POWER_MODE_CHANGED_ACTION");
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filter.addAction(android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
}
context.registerReceiver(mPowerSaveChangeReceiver, filter);
}
}
@TargetApi(21)
class PowerSaveChangeReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
boolean isPowerSaveMode = false;
// Oh, Huawei...why don't you play by the same rules as everyone else?
if (intent.getAction().equals("huawei.intent.action.POWER_MODE_CHANGED_ACTION")) {
Bundle extras = intent.getExtras();
if ((extras != null) && extras.containsKey("state")) {
int state = intent.getExtras().getInt("state");
isPowerSaveMode = (state == 1); // ON=1; OFF=2
}
} else {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
isPowerSaveMode = pm.isPowerSaveMode();
}
Log.d("MyTag", "[powersavechange] isPowerSaveMode? " + isPowerSaveMode);
}
}
答案 3 :(得分:0)
一些中文 ROM 像 Huawei
或 Xiaomi
没有实现省电模式查询的标准 API。但与其他系统设置一样,当用户打开/关闭省电模式时,状态标志将保存到数据库中。
所以我们可以利用这个状态标志来解决兼容性问题。切换省电模式时系统也会发送一个特定的意图,我们可以监听这个意图动作来监控节能模式的变化。
以下是 Huawei
或 Xiaomi
设备的详细 kotlin 代码实现。
object PowerManagerCompat {
private const val TAG = "PowerManagerCompat"
interface PowerSaveModeChangeListener {
/**
* will be called when power save mode change, new state can be query via [PowerManagerCompat.isPowerSaveMode]
*/
fun onPowerSaveModeChanged()
}
private val POWER_SAVE_MODE_VALUES = mapOf(
"HUAWEI" to 4,
"XIAOMI" to 1
)
private val POWER_SAVE_MODE_SETTING_NAMES = arrayOf(
"SmartModeStatus", // huawei setting name
"POWER_SAVE_MODE_OPEN" // xiaomi setting name
)
private val POWER_SAVE_MODE_CHANGE_ACTIONS = arrayOf(
"huawei.intent.action.POWER_MODE_CHANGED_ACTION",
"miui.intent.action.POWER_SAVE_MODE_CHANGED"
)
private const val monitorViaBroadcast = true
/**
* Monitor power save mode change, only support following devices
* * Xiaomi
* * Huawei
*/
fun monitorPowerSaveModeChange(context: Context, powerSaveModeChangeListener: PowerSaveModeChangeListener) {
if (Build.MANUFACTURER.toUpperCase(Locale.getDefault()) !in POWER_SAVE_MODE_VALUES.keys) {
Log.w(TAG, "monitorPowerSaveModeChange: doesn't know how to monitor power save mode change for ${Build.MANUFACTURER}")
}
if (monitorViaBroadcast) {
context.registerReceiver(object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
powerSaveModeChangeListener.onPowerSaveModeChanged()
}
}, IntentFilter().also {
for (a in POWER_SAVE_MODE_CHANGE_ACTIONS) {
it.addAction(a)
}
})
} else {
val contentObserver = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
powerSaveModeChangeListener.onPowerSaveModeChanged()
}
}
for (name in POWER_SAVE_MODE_SETTING_NAMES) {
context.contentResolver.registerContentObserver(
Uri.parse("content://settings/system/${name}"), false, contentObserver)
}
}
}
/**
* Check the system is currently in power save mode
* @see [PowerManager.isPowerSaveMode]
*/
fun isPowerSaveMode(context: Context): Boolean {
if (Build.MANUFACTURER.toUpperCase(Locale.getDefault()) in POWER_SAVE_MODE_VALUES.keys) {
return isPowerSaveModeCompat(context)
}
val powerManager = context.getSystemService(Context.POWER_SERVICE) as? PowerManager
return powerManager?.isPowerSaveMode ?: false
}
private fun isPowerSaveModeCompat(context: Context): Boolean {
for (name in POWER_SAVE_MODE_SETTING_NAMES) {
val mode = Settings.System.getInt(context.contentResolver, name, -1)
if (mode != -1) {
return POWER_SAVE_MODE_VALUES[Build.MANUFACTURER.toUpperCase(Locale.getDefault())] == mode
}
}
return false
}
}
答案 4 :(得分:0)
private void isPowerSaveModeHuaweiXiaomi(){
if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
try {
int value = android.provider.Settings.System.getInt(getContext().getContentResolver(), "POWER_SAVE_MODE_OPEN");
} catch (Settings.SettingNotFoundException e) {
Log.d("Valor modo bateria:", "Error");
}
}else if (Build.MANUFACTURER.equalsIgnoreCase("Huawei")){
try {
int value = android.provider.Settings.System.getInt(getContext().getContentResolver(), "SmartModeStatus");
} catch (Settings.SettingNotFoundException e) {
Log.d("Valor modo bateria:", "Error");
}
}
}