Android开发笔记(一百一十七)app省电方略
2019-07-14 01:54 发布
生成海报
电源管理PowerManager
PowerManager是Android的电源管理类,用于管理电源操作如睡眠、唤醒、重启以及调节屏幕亮度等等。
PowerManager的对象从系统服务POWER_SERVICE中获取,它的主要方法如下:
goToSleep : 睡眠,即锁屏。
wakeUp : 唤醒,即解锁。
reboot : 重启。
另有下列几个隐藏的方法:
getMinimumScreenBrightnessSetting : 获取屏幕亮度的最小值。
getMaximumScreenBrightnessSetting : 获取屏幕亮度的最大值。
getDefaultScreenBrightnessSetting : 获取屏幕亮度的默认值。
setBacklightBrightness : 设置屏幕亮度。
但对多数开发者来说,PowerManager在实际开发中毫无用处,因为一旦调用该类的方法,你的app运行时就会崩溃,查看日志报错“java.lang.SecurityException: Neither user 10150 nor current process has android.permission.DEVICE_POWER.”这个错误信息倒是容易看懂,好吧,那我便在AndroidManifest.xml中加上DEVICE_POWER的权限。可是加了权限之后,ADT又提示错误“Permission
is only granted to system apps”。这下傻眼了,怎么会说“权限只授予系统应用程序”呢?不过这难不倒我,咱把app工程clean一下,错误提示就不见了,然后重新Run之,结果Console栏出现红 {MOD}文字“Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE”,还是不行呀。
找了大量的资料,才发现这是因为电源管理的权限,只有系统程序(打了系统签名)才可以获得,用户程序无法获取这个权限。大伙对该问题基本是束手无策,只有Stack Overflow上的大神给了个解决方案,主要做三方面的修改:
1、在AndroidManifest.xml中加上DEVICE_POWER、REBOOT、SHUTDOWN的权限。
2、在AndroidManifest.xml的manifest节点中增加属性说明“android:sharedUserId="android.uid.system"”,这表示使用系统用户的uid。
3、为了能够共享系统用户的uid,你的app得采用系统签名打包,即先找到目标Android系统的platform.pk8和platform.x509.pem密钥文件,然后使用signapk.jar将apk签名到指定密钥。
这个解决方案理论上可行,但就真机来说,每个品牌每个型号的手机,其系统签名都是不一样的。因此,就算你真的搞出来一个系统应用,那也仅适用于该签名版本的Android系统,而不能用于其他签名的Android系统,所以PowerManager只能是手机厂商内部使用了。
下面是PowerManager几个用途的示例代码(一般用不到,仅供参考):
[java] view
plain copy
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;
public class PowerUtil {
private final static String TAG = "PowerUtil" ;
private static int getValue(Context ctx, String methodName, int defValue) {
int value = defValue;
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
try {
Class> pmClass = Class.forName(pm.getClass().getName());
Field field = pmClass.getDeclaredField("mService" );
field.setAccessible(true );
Object iPM = field.get(pm);
Class> iPMClass = Class.forName(iPM.getClass().getName());
Method method = iPMClass.getDeclaredMethod(methodName);
method.setAccessible(true );
value = (Integer) method.invoke(iPM);
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "methodName=" +methodName+ ", value=" +value);
return value;
}
public static int getMinLight(Context ctx) {
return getValue(ctx, "getMinimumScreenBrightnessSetting" , 0 );
}
public static int getMaxLight(Context ctx) {
return getValue(ctx, "getMaximumScreenBrightnessSetting" , 255 );
}
public static int getDefLight(Context ctx) {
return getValue(ctx, "getDefaultScreenBrightnessSetting" , 100 );
}
public static void setLight(Context ctx, int light) {
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
try {
Class> pmClass = Class.forName(pm.getClass().getName());
Field field = pmClass.getDeclaredField("mService" );
field.setAccessible(true );
Object iPM = field.get(pm);
Class> iPMClass = Class.forName(iPM.getClass().getName());
Method method = iPMClass.getDeclaredMethod("setBacklightBrightness" , int . class );
method.setAccessible(true );
method.invoke(iPM, light);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void resetLight(Context ctx, int light) {
try {
Object power;
Class > ServiceManager = Class.forName("android.os.ServiceManager" );
Class > Stub = Class.forName("android.os.IPowerManager$Stub" );
Method getService = ServiceManager.getMethod("getService" , new Class[] {String. class });
Method asInterface = Stub.getMethod("asInterface" , new Class[] {IBinder. class });
IBinder iBinder = (IBinder) getService.invoke(null , new Object[] {Context.POWER_SERVICE});
power = asInterface.invoke(null ,iBinder);
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮