Android Development Notes (117) app power saving strategy

Source: Internet
Author: User

Power Management Powermanagerpowermanager is a power management class for Android that manages power operations such as sleep, wake, restart, and adjust screen brightness.
The PowerManager object is obtained from the system service Power_service, and its main methods are as follows:
Gotosleep: Sleep, that is, lock screen.
WakeUp: Wake up, that is, unlock.
Reboot: Restart.
There are several other hidden methods:
Getminimumscreenbrightnesssetting: Gets the minimum value of the screen brightness.
Getmaximumscreenbrightnesssetting: Gets the maximum value of the screen brightness.
Getdefaultscreenbrightnesssetting: Gets the default value of the screen brightness.
Setbacklightbrightness: Sets the screen brightness.


But for most developers, PowerManager is useless in real-world development, because once the method of that class is called, your app will crash and see the log Error "Java.lang.SecurityException:Neither user 10150 Nor current process had android.permission.DEVICE_POWER. " This error message is easy to understand, OK, then I will add Device_power in the Androidmanifest.xml. However, after adding the permissions, ADT also prompted the error "Permission is only granted to system apps." This under the dumbfounded, how can say "authority only grant System application"? But this is hard for me, I clean the app project, the error is gone, and then run again, the result of the console bar appears red text "Installation Error:install_failed_shared_user_ Incompatible ", or not.
Find a large amount of information, only to find that this is because the power management permissions, only the System program (signed by the system) can be obtained, the user program cannot get this permission. We are basically helpless on this issue, only the big God on stack overflow gave a solution, mainly to do three changes:
1, in the Androidmanifest.xml add Device_power, REBOOT, shutdown permissions.
2. Add the attribute description "android:shareduserid=" Android.uid.system "" in the manifest node of androidmanifest.xml, which means the UID of the system user is used.
3, in order to be able to share the UID of the system user, your app has to use the system signature package, that is, first find the target Android system platform.pk8 and Platform.x509.pem key file, and then use Signapk.jar to sign the APK to the specified key.
This solution is theoretically feasible, but the system signature is different for each model of each brand in terms of the real machine. So, even if you do make a system application, it only applies to the signed version of the Android system, but not to other signed Android systems, so PowerManager can only be used by the handset manufacturers inside.


Below is a sample code for several uses of PowerManager (generally not available, for informational purposes only):
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;//Note, PowerManager only system application can operate, Normal application cannot operate, so the code below is for reference only public class Powerutil {private final static String TAG = "Powerutil";p rivate static int GetValue (Conte XT 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 = 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);} Sets the screen brightness. Light value 0-255 public static void SetLight (Context ctx, int. light) {PowerManager pm = (powermanager) ctx.getsystemservice        (Context.power_service);            try {class<?> Pmclass = Class.forName (Pm.getclass (). GetName ()); Get member Mservice (Mservice for Powermanagerservice type) in the PowerManager class field field = Pmclass.getdeclaredfield ("Mservice            ");            Field.setaccessible (TRUE);            Instantiate mservice Object IPM = field.get (PM);           Get powermanagerservice corresponding Class object class<?> ipmclass = Class.forName (Ipm.getclass (). GetName ()); /* * Get Powermanagerservice function setbacklightbrightness corresponding Method object, * PowerManager function Setbacklightbrig Htness implemented in Powermanagerservice * * method = Ipmclass.getdeclaredmethod ("setbacklightbrightness            ", Int.class);            Method.setaccessible (TRUE);        Call implement Powermanagerservice setbacklightbrightness 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 = Getstub.getmethod ("Asinterface", new class[] {ibinder.class});//of this Class? Method Asinterface = Stub.getmetHod ("Asinterface", new class[] {ibinder.class});            of this class? IBinder IBinder = (ibinder) getservice.invoke (null, new object[] {context.power_service});//POWER = ASINTERFAC E.invoke (null,ibinder);//or Call constructor stub?//Method setbacklightbrightness = Power.getclass (). GetMethod             ("Setbacklightbrightness", New Class[]{int.class});        Setbacklightbrightness.invoke (Power, New object[]{light});        } catch (Exception e) {e.printstacktrace (); }}//Lock screen public static void Lockscreen (Context ctx) {powermanager pm = (powermanager) ctx.getsystemservice (Co ntext.        Power_service);    Pm.gotosleep (Systemclock.uptimemillis ()); }//Unlock @TargetApi (build.version_codes. JELLY_BEAN_MR1) public static void Unlockscreen (Context ctx) {powermanager pm = (powermanager) ctx.getsystemservice (        Context.power_service);    Pm.wakeup (Systemclock.uptimemillis ()); }//Restart public static void reboot (Context ctx) {PoWermanager pm = (powermanager) ctx.getsystemservice (Context.power_service);    Pm.reboot (NULL); }//Shutdown public static void ShutDown (Context ctx) {Intent Intent = new Intent ("Android.intent.action.ACTION_RE        Quest_shutdown ");        Intent.putextra ("Android.intent.extra.KEY_CONFIRM", false);        Intent.setflags (Intent.flag_activity_new_task);    Popup system built-in dialog box, choose OK Shutdown or cancel shutdown ctx.startactivity (intent); }    }


Battery management Batterymanagerbatterymanager is called battery management, however looking at the source code of the class, there are only a few constant definitions, not the real sense of battery management. In fact, developers are not able to manage the battery directly, to get information about the battery, you have to listen to the power Change event to know.


The battery's power change event, whose action name is intent.action_battery_changed, because accepting the event requires the app to be active, Therefore, the broadcast receivers used for listening cannot be registered statically in Androidmanifest.xml, but can only be dynamically registered in the app code through the Registerreceiver method. The following is the parameter information that is carried in the battery change event:
Batterymanager.extra_scale: Power scale, obtained by Getintextra. It's usually 100.
Batterymanager.extra_level: Current charge, obtained by Getintextra.
Batterymanager.extra_status: The current state, obtained through Getintextra.
--battery_status_unknown = 1; Indicates unknown
--battery_status_charging = 2; Indicates charging is in progress
--battery_status_discharging = 3; means power is being powered off
--battery_status_not_charging = 4; Indicates not charging
--battery_status_full = 5; Indicates full
Batterymanager.extra_health: Health level, obtained through Getintextra.
--battery_health_unknown = 1; Indicates unknown
--battery_health_good = 2; Represents good
--battery_health_overheat = 3; Indicates overheating
--battery_health_dead = 4; That's bad.
--battery_health_over_voltage = 5; Indicates a short circuit
--battery_health_unspecified_failure = 6; Indicates an unknown error
--battery_health_cold = 7; Indicates cooling
Batterymanager.extra_voltage: Current voltage, obtained by Getintextra.
Batterymanager.extra_plugged: Current power supply, obtained through Getintextra.
--0 means battery
--battery_plugged_ac = 1; Indicates charger
--BATTERY_PLUGGED_USB = 2; Represents a USB
--battery_plugged_wireless = 4; Represents a wireless
Batterymanager.extra_technology: Current technology, obtained through Getstringextra. Return Li-ion, for example, represents a lithium battery.
Batterymanager.extra_temperature: Current temperature, obtained by Getintextra.
Batterymanager.extra_present: Whether to provide battery, obtained through Getbooleanextra.


In addition to the power change event, there are several events related to the battery, as shown below
Intent.action_battery_low: Battery low, use Android.intent.action.BATTERY_LOW at static registration
Intent.action_battery_okay: Battery power recovery, static registration using Android.intent.action.BATTERY_OKAY
intent.action_power_connected: Connect to external power, use Android.intent.action.ACTION_POWER_CONNECTED when registering statically
intent.action_power_disconnected: Disconnect external power, use Android.intent.action.ACTION_POWER_DISCONNECTED at static registration


The following is the monitoring of battery events:



The following is an example code that listens for battery events:
Import Com.example.exmbattery.util.dateutils;import Android.app.activity;import Android.content.BroadcastReceiver ; Import Android.content.context;import Android.content.intent;import Android.content.intentfilter;import Android.os.batterymanager;import Android.os.bundle;import Android.widget.textview;public class BatteryActivity Extends Activity {private TextView tv_battery_change;private static TextView tv_power_status; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_battery ); tv_battery_change = (TextView) Findviewbyid (r.id.tv_battery_change); tv_power_status = (TextView) Findviewbyid ( R.id.tv_power_status);} @Overrideprotected void OnStart () {Super.onstart (); batterychangereceiver = new Batterychangereceiver (); intentfilter Filter = new Intentfilter (intent.action_battery_changed); Registerreceiver (batterychangereceiver, filter);} @Overrideprotected void OnStop () {super.onstop (); Unregisterreceiver (batterychangereceIver);}    Private Batterychangereceiver Batterychangereceiver; Private class Batterychangereceiver extends Broadcastreceiver {@Override public void onreceive (Context cont Ext, Intent Intent) {if (Intent! = null) {int scale = Intent.getintextra (batterymanager.extra_scal            E,-1);            int level = Intent.getintextra (Batterymanager.extra_level,-1);            int status = Intent.getintextra (batterymanager.extra_status, 0);            int healthy = Intent.getintextra (batterymanager.extra_health, 0);            int voltage = Intent.getintextra (batterymanager.extra_voltage, 0);            int plugged = Intent.getintextra (batterymanager.extra_plugged, 3);            String technology = Intent.getstringextra (batterymanager.extra_technology);            int temperature = Intent.getintextra (batterymanager.extra_temperature, 0);            Boolean present = Intent.getbooleanextra (Batterymanager.extra_present, false); String desc = string.foRmat ("%s: Received broadcast:%s", Dateutils.getnowdatetime (), intent.getaction ());            desc = String.Format ("%s\n Power scale =%d", desc, scales);            desc = String.Format ("%s\n Current charge =%d", desc, level);            desc = String.Format ("%s\n Current state =%s", DESC, Mstatus[status]);            desc = String.Format ("%s\n Health degree =%s", DESC, mhealthy[healthy]);            desc = String.Format ("%s\n Current voltage =%d", desc, voltage);            desc = String.Format ("%s\n Current power =%s", DESC, mplugged[plugged]);            desc = String.Format ("%s\n Current technology =%s", DESC, technology);            desc = String.Format ("%s\n Current temperature =%d", desc, TEMPERATURE/10); desc = String.Format ("%s\n provides battery =%s", desc, present?)            is ":" No ");            Tv_battery_change.settext (DESC);    }}} private static string[] Mstatus = {"Does not exist", "unknown", "charging", "powering off", "not charging", "full"};    private static string[] Mhealthy = {"Does not exist", "unknown", "good", "overheated", "bad", "short circuit", "Unknown Error", "cooling"}; private static string[] mplugged = {"Battery", "charger", "USB", "Does not exist "," "Wireless"};     private static String Mchange = ""; public static class Powerchangereceiver extends Broadcastreceiver {@Override public void onreceive (Context             Context, Intent Intent) {if (Intent! = null) {Mchange = String.Format ("%s\n%s: Received broadcast:%s",            Mchange, Dateutils.getnowdatetime (), intent.getaction ());            Tv_power_status.settext (Mchange); }        }    }}


Power Saving method/Screen switch event before you say a lot of nonsense, hurry back to the topic of this article-save electricity. App Development and server program development, the app is a mobile device is very short of electricity, a few days will be charged once, so if your app special power consumption, a day or even a half-day of the user phone is not power, then usually escape the tragic fate of being unloaded. Therefore, for their own, developers are as far as possible to make the app run when the power saving, green low-carbon life, from the development of the app.


However, it is not possible to detect the power consumption of each application, generally rely on experience to judge, the basic principle is: the more resources consumed, the greater the power consumption. Specific to the code to write, mainly has the following power-saving measures:
1, can use the integer number calculation, do not use floating-point calculation.
2, can be parsed with JSON, without XML parsing.
3, can use the network positioning, do not use GPS positioning.
4, minimize the download of large files (such as compressing and then downloading, or caching the downloaded files).
5, use up the system resources, to timely recovery. Occupy the manger not to poop, the user cell phone will be very egg ache. See the Android Development Note (75) Handling of memory leaks for relevant examples
6, can use the thread processing, no process processing.
7, multi-use cache reuse object resources. If the screen size is only needed once, then can be read in the cache, global variable technology see Android Development Note (28) using application for memory read and write. Examples can also be found in the Android Development note (76) thread pool management, the Android Development Note (77) Image caching algorithm
8, can use the timer broadcast, do not have the backstage resident service.
9, can use memory storage, no file storage.


Although the power saving measures are many, how to know the power saving effect? In the actual development, the power consumption is in the background silently running service services, think about it, the phone when the standby, the screen is not lit, but there are some tireless service in the phone Yugong Yishan, the foolish public is also to eat ah. I have done an experiment, an app is still full blood service running when the system is standby, the phone consumes 4% after one hour; the same app after the transformation of the system when the machine does not run any service, an hour after the phone power consumption of 2%, an hour difference of 2%, 10 hours difference 20% Ah, It turns out that the power of our phone is consumed by 1.1 points.


That being the case, if we want to avoid the app still working hard when the phone is idle, we need to end the task when the screen is off and start specifying the task when the screen is lit. The following three screen switch events are used here:
INTENT.ACTION_SCREEN_ON: Screen lit Event
Intent.action_screen_off: Screen off event
Intent.action_user_present: User unlocked event, static registration using Android.intent.action.USER_PRESENT
There are a few points to note when using the three events above:
1. The On-screen light event and screen shutdown event must be dynamically registered in the code. If you register statically in Androidmanifest.xml, there is no effect.
2. When the screen is turned off, the system pauses all active pages before turning off the screen, and similarly, when the screen is lit, the system lights the screen before resuming the active page. Therefore, these events cannot be registered/unregistered in the activity, but can only be registered in the OnCreate method of the custom application and logged out in the Onterminate method.
3, the activity wants to obtain the screen switch event, must through the custom application class to obtain indirectly.


Here is the capture of the screen switch event:



The following is the code for the screen switch event:
Import Com.example.exmbattery.util.dateutils;import Android.content.broadcastreceiver;import Android.content.context;import Android.content.intent;import Android.util.log;public class LockScreenReceiver Extends Broadcastreceiver {private static final String TAG = "Lockscreenreceiver"; @Overridepublic void OnReceive (Context Context, Intent Intent) {if (Intent! = null) {String mchange = ""; Mchange = String.Format ("%s\n%s: Received broadcast:%s", mchange,date Utils.getnowdatetime (), Intent.getaction ()), if (Intent.getaction (). Equals (intent.action_screen_on)) {MChange = String.Format ("%s\n This is the screen lit event", mchange);} else if (intent.getaction () equals (Intent.action_screen_off)) {Mchange = String.Format ("%s\n This is a screen off event", Mchange);} else if (intent.getaction () equals (intent.action_user_present)) {Mchange = String.Format ("%s\n This is the user unlocking event", Mchange);} LOG.D (TAG, Mchange); Mainapplication.getinstance (). Setchangedesc (Mchange);}}


Here is the code for the custom application:
Import Android.app.application;import Android.content.intent;import Android.content.intentfilter;public class MainApplication extends Application {private static mainapplication mapp;private lockscreenreceiver mreceiver;private String Mchange = "";p ublic static MainApplication getinstance () {return mApp;} Public String Getchangedesc () {return mapp.mchange;} public void Setchangedesc (String change) {Mapp.mchange = Mapp.mchange + change;} @Overridepublic void OnCreate () {super.oncreate (); mApp = This;mreceiver = new Lockscreenreceiver (); Intentfilter filter = New Intentfilter (); filter.addaction (intent.action_screen_on); filter.addaction (Intent.action_screen_off); Filter.addaction (intent.action_user_present); Registerreceiver (mreceiver, filter);} @Overridepublic void Onterminate () {unregisterreceiver (mreceiver); Super.onterminate ();}}


Here is the page code that displays the screen switch event
Import Android.app.activity;import Android.os.bundle;import Android.widget.textview;public class ScreenActivity Extends Activity {private static TextView tv_screen; @Overrideprotected void OnCreate (Bundle savedinstancestate) { Super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_screen); tv_screen = (TextView) findViewById ( R.id.tv_screen);} @Overrideprotected void OnStart () {Super.onstart (); Tv_screen.settext (Mainapplication.getinstance (). Getchangedesc ( ));}}






Click here to view the full list of Android development notes

Android Development Notes (117) app power saving strategy

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.