locked
getting the battery level in windows mobile 5.0 RRS feed

  • Question

  • hi ,
    how to get the battery level . for example i had created a event for the incoming call as follows :
    Microsoft.WindowsMobile.Status.SystemProperty systemProperty = Microsoft.WindowsMobile.Status.SystemProperty.PhoneIncomingCall;
                Microsoft.WindowsMobile.Status.SystemState systemState = new Microsoft.WindowsMobile.Status.SystemState(systemProperty);
                systemState.Changed += new Microsoft.WindowsMobile.Status.ChangeEventHandler(systemState_Changed);
    -------------------------------------------------------------------------------------------------------------------
    void systemState_Changed(object sender, Microsoft.WindowsMobile.Status.ChangeEventArgs args)
             {
                 //throw new Exception("The method or operation is not implemented.");

                 switch (state)
                 {
                     case STATE_GETSUMS:
                     case STATE_GAMESCREEN:
                     case STATE_ARCHIEVEPICK:
                         gameWidget.pauseTimer();
                         break;
                 }
             }

    so how to create a event for battery life as i did for the incoming call :


    thanks
    sadiq
    Wednesday, May 9, 2007 9:06 AM

Answers

  • Hi sadiq,

     

    You can use the same technique, just use the SystemProperty.PowerBatteryStrength property which will return the current battery life expressed as a percentange range (one of the Microsoft.WindowsMobile.Status.BatteryLevel enum values).

     

    The following example demonstrates how to utilise this API:

     

    Code Snippet
    SystemState batterySystemState;
     
    public Init()
    {
         batterySystemState= new SystemState(SystemProperty.PowerBatteryStrength);
         batterySystemState.Changed += new ChangeEventHandler(PowerBatteryStrength_Changed);
    }
     
    void PowerBatteryStrength_Changed(object sender, ChangeEventArgs args)
    {
         MesssageBox.Show("Current battery strength is " + SystemState.PowerBatteryStrength.ToString());
    }

     

     Note: Jim Wilson documents a potential trap when doing this on his blog here http://pluralsight.com/blogs/jimw/archive/2007/04/27/47037.aspx.

     

    Hope it helps,

    Christopher Fairbairn

    Wednesday, May 9, 2007 12:11 PM

All replies

  • Hi sadiq,

     

    You can use the same technique, just use the SystemProperty.PowerBatteryStrength property which will return the current battery life expressed as a percentange range (one of the Microsoft.WindowsMobile.Status.BatteryLevel enum values).

     

    The following example demonstrates how to utilise this API:

     

    Code Snippet
    SystemState batterySystemState;
     
    public Init()
    {
         batterySystemState= new SystemState(SystemProperty.PowerBatteryStrength);
         batterySystemState.Changed += new ChangeEventHandler(PowerBatteryStrength_Changed);
    }
     
    void PowerBatteryStrength_Changed(object sender, ChangeEventArgs args)
    {
         MesssageBox.Show("Current battery strength is " + SystemState.PowerBatteryStrength.ToString());
    }

     

     Note: Jim Wilson documents a potential trap when doing this on his blog here http://pluralsight.com/blogs/jimw/archive/2007/04/27/47037.aspx.

     

    Hope it helps,

    Christopher Fairbairn

    Wednesday, May 9, 2007 12:11 PM
  • Hello,

    I'm trying to do a simple thing (or at least I think so). In my application I want to be notified when the smartphone battery power is below a certain value (20% for example).

    The code I have is simple:

    Code Snippet

    private SystemState power = new SystemState(SystemProperty.PowerBatteryStrength);

    private void xpto()
    {
    this.power.ComparisonType = StatusComparisonType.Less;
    this.power.ComparisonValue = 20;
    this.power.Changed += new ChangeEventHandler(PowerStatusChanged);
    }

    private void PowerStatusChanged(object sender, ChangeEventArgs args)
    {
    Test t = new Test( args.NewValue );
    t.ShowDialog();
    }

    What am I doing wrong? I want that form Test to appear and alert me that the battery is low, but unfortunately it's not working.

    Thanks in advance,
    Paulo
    Wednesday, September 12, 2007 3:13 PM
  • Hi,

    I would like to get the real battery status. If I use this code:

    SystemState ss = new SystemState(SystemProperty.PowerBatteryState);

    object obj = ss.CurrentValue;

    Int32 bat = (Int32) obj;

    Int32 lev = bat >>16;

    Int32 state = (0x0000ffff & bat) ;

    even if the phone battery is higher than 81% the varible lev is 81.

    Is there any way to get the exactly value?

    Thanks

    Akvo

    Monday, September 17, 2007 6:28 PM
  • Hi prlPT and Akvo,

     

    The PowerBatteryStrength SystemState property is an enumerated value. I.e. it has a descrete set of values to choose from (High, Low, Medium, VeryLow, VeryHigh) which each correspond to a range of battery charge percentages. It is not an integer indicating the current percentage of charge. This explains why the comparision event handler fails to fire since '20' isn't a valid enumeration value for this property.

     

    The current battery charge percentage isn't directly accessible via the State and Notification Broker API. For this you might like to investigate PInvoking a native API called GetSystemPowerStatusEx as described in the MSDN article "HOWTO: Get the Device Power Status" on MSDN at http://msdn2.microsoft.com/en-us/library/aa457088.aspx

     

    Documentation for GetSystemPowerStatusEx itself can be found on MSDN at http://msdn2.microsoft.com/en-us/library/aa453172.aspx

     

    A small example of this technique follows:

     

    Code Snippet

    public class SYSTEM_POWER_STATUS_EX

    {

      public byte ACLineStatus;

      public byte BatteryFlag;

      public byte BatteryLifePercent;

      public byte Reserved1;

      public uint BatteryLifeTime;

      public uint BatteryFullLifeTime;

      public byte Reserved2;

      public byte BackupBatteryFlag;

      public byte BackupBatteryLifePercent;

      public byte Reserved3;

      public uint BackupBatteryLifeTime;

      public uint BackupBatteryFullLifeTime;

    }

     

    [DllImport("coredll")]

    private static extern uint GetSystemPowerStatusEx(SYSTEM_POWER_STATUS_EX lpSystemPowerStatus, bool fUpdate);

     

    private void timer1_Tick(object sender, EventArgs e)

    {

      // In response to a timer tick, update a label

      // displaying the current battery charge

      SYSTEM_POWER_STATUS_EX status = new SYSTEM_POWER_STATUS_EX();

     

      if (GetSystemPowerStatusEx(status, false) == 1)

      {

        label1.Text = String.Format("{0}%", status.BatteryLifePercent);

      }

    }

     

    Be aware that if you are using this technique to obtain the current battery life percentage to display some kind of alert to the user that you may need to provide a little bit of hysteresis or dampening. The values reported tend to jump up and down slightly, potentially leading to a series of prompts/alerts for the user to contend with in short succession, if such short term changes are not filtered out.

     

    Hope this helps,

    Christopher Fairbairn

     

    Tuesday, September 18, 2007 11:32 PM
  • Hello Christopher,

    Thanks for your answer. I realized that after a little investigation on the MSDN pages Smile

    I now have another problem. I want my application to be "always on top". I want to catch certain events and show the user the respective warnings. For example, I do this for the Incoming Call event; when a call arrives I never show the user the Windows Mobile Incoming Call interface, only my application interface. Unfortunately I'm having problems doing this with the Low Battery event. When the battery level reaches "Very Low", I show the user a warning. The problem is that when I close the dialog I use to show the warning, the Windows Mobile Low Battery warning is over my application, which is a problem for me.

    The code I'm using when the main form of my application is initialized is this:

    Code Snippet

    this.Enabled = true;
    this.Visible = true;
    this.TopMost = true;



    and then, for the low battery event handler:

    Code Snippet

    public static SystemState _batteryPower = new SystemState(SystemProperty.PowerBatteryStrength);

    _batteryPower.Changed += new ChangeEventHandler(_batteryPower_Changed);

    public static void _batteryPower_Changed(object sender, ChangeEventArgs args)
    {

    if ( ((int)SystemState.GetValue(SystemProperty.PowerBatteryStrength) <= (int)BatteryLevel.VeryLow) &&
    ((int)SystemState.GetValue(SystemProperty.PowerBatteryState) != (int)BatteryState.Charging) )
    {
    LowBattery lowBattery = new LowBattery();
    lowBattery.TopMost = true;
    lowBattery.ShowDialog();
    }
    }



    So, am I doing anything wrong? Can anyone help me with this?

    Thanks in advance,
    Paulo
    Wednesday, September 19, 2007 5:08 PM
  •  

    Dear Christopher Fairbairn,

    Thank you very much. It helps a lot.

    Best Regards akvo

    Thursday, September 20, 2007 12:02 AM
  • Hi,

    I am using SYSTEM_POWER_STATUS_EX2 to get the BatteryLifePercent, BatteryVoltage and BatteryCurrent.

    SYSTEM_POWER_STATUS_EX2 is instantiated at a timer event method that is called repeatedly.

    However the values of BatteryLifePercent, BatteryVoltage and BatteryCurrent are always equal to the first one. I.e., they don't change. Each time I initiate  the program the values change, but never inside the program.

    I am playing a video, so it is not possible that all this values really don't change, like the eletric current.

    Is there something that should be done (enable something) ?

    Thanks in advance

    akvo
    Wednesday, October 3, 2007 10:03 PM
  • Hi,

     

     akvo wrote:
    I am using SYSTEM_POWER_STATUS_EX2 to get the BatteryLifePercent, BatteryVoltage and BatteryCurrent.

    SYSTEM_POWER_STATUS_EX2 is instantiated at a timer event method that is called repeatedly.

    However the values of BatteryLifePercent, BatteryVoltage and BatteryCurrent are always equal to the first one. I.e., they don't change. Each time I initiate  the program the values change, but never inside the program.

     

    Are you able to share some of your source code? Perhaps the code within your timer event and the code which is displaying the returned values?

     

    This would help us understand what is possibly happening.

     

    Thanks,

    Christopher Fairbairn

    Thursday, October 4, 2007 12:46 AM
  • Dear Mr. Fairbairn,

    I am sending my class full code. The timer event method is timerCallBack_Tick.

    The problem is that the values written at file are the same each time
    timerCallBack_Tick is called.

    Thanks for the help.

    Akvo


    using System;
    using System.Runtime.InteropServices;
    using System.IO;
    using System.Diagnostics;
    using System.Windows.Forms;

    //BATTMETER CLASS

    public class BattMeter
    {

        public class SYSTEM_POWER_STATUS_EX2
        {
            public byte ACLineStatus;
            public byte BatteryFlag;
            public byte BatteryLifePercent;
            public byte Reserved1;
            public uint BatteryLifeTime;
            public uint BatteryFullLifeTime;
            public byte Reserved2;
            public byte BackupBatteryFlag;
            public byte BackupBatteryLifePercent;
            public byte Reserved3;
            public uint BackupBatteryLifeTime;
            public uint BackupBatteryFullLifeTime;
            public uint BatteryVoltage;
            public uint BatteryCurrent;
            public uint BatteryAverageCurrent;
            public uint BatteryAverageInterval;
            public uint BatterymAHourConsumed;
            public uint BatteryTemperature;
            public uint BackupBatteryVoltage;
            public byte BatteryChemistry;
        }

        [DllImport("coredll")]
        private static extern uint GetSystemPowerStatusEx2(SYSTEM_POWER_STATUS_EX2 lpSystemPowerStatus,uint dwLen, bool fUpdate);

        private static String PATH = @"BattMeter\Log\";//path where the file should be created

        private string fileName;//file name that receive the batery level
        private StreamWriter file;//file that receive the batery level
        private Timer timerCallBack;//timer for writing the battery level at file

        //CONSTRUCTOR
        //Parameters:
        //Boolean enable -> true => enable the call back timer for write at the file; false => disable
        //int time -> timer interval (miliseconds)
        //String fileName -> fileName
        public BattMeter (Boolean enable, int time, String fileName)
        {
            this.fileName = fileName;

           // this.status = new SYSTEM_POWER_STATUS_EX2();

            if (enable)//create the file
            {
                try//if path was not found will not enable the callback
                {
                    this.file = System.IO.File.CreateText(this.fileName);
                    this.file.Write("period = " + time + "\n");//first thing that is written at file is the period time
                    this.file.Close();

                    //timerCallBack
                    this.timerCallBack = new Timer();
                    this.timerCallBack.Tick += new EventHandler(timerCallBack_Tick);
                    this.timerCallBack.Interval = time;
                    this.timerCallBack.Enabled = enable;
                }
                catch (System.IO.DirectoryNotFoundException)
                {
                    Debug.Write("Path not found!\n");
                    throw new System.IO.DirectoryNotFoundException();
                }

            }

        }
        //overload constructor
        //String fileName is set with the actual date (get at getDate())
        public BattMeter(Boolean enable, int time):this(enable, time, PATH + getDate() + ".txt"){}

        //called through the timer event
        //write at the file the result of getLevel();
        private void timerCallBack_Tick(Object myObject, EventArgs myEventArgs)
        {
            Debug.Write("call back\n");
            this.file = System.IO.File.AppendText(this.fileName);
            SYSTEM_POWER_STATUS_EX2 status = new SYSTEM_POWER_STATUS_EX2();

            if (GetSystemPowerStatusEx2(status, (uint)Marshal.SizeOf(status), true) == (uint)Marshal.SizeOf(status))
            {
                file.Write("% = " + Convert.ToInt32(status.BatteryLifePercent) + " ");
                file.Write("V = " + Convert.ToInt32(status.BatteryVoltage) + "mV ");
                file.Write("I = " + Convert.ToInt32(status.BatteryCurrent) + "mA ");
                file.Write("C = " + Convert.ToInt32(status.BatterymAHourConsumed) + "mAH ");
                file.Write("T = " + Convert.ToInt32(status.BatteryTemperature) + "oC\n");
            }
            this.file.Close();

        }

        public void exit()
        {
            if (this.timerCallBack != null)
            {
                this.timerCallBack.Enabled = false;
            }
            if (this.file != null)
            {
                this.file.Close();
            }
           
        }

        //return a string filled with the actual date
        private static String getDate()
        {
            DateTime time = DateTime.Now;
            String date = time.Year + "y" + time.Month + "m" + time.Day + "d" + time.Hour + "h" + time.Minute + "mim" + time.Second + "s";
            Debug.Write(date+"\n");
            return date;
        }


    }

    Thursday, October 4, 2007 6:16 PM
  • Dear Mr. Fairbairn,

     

    I've found some new info. If I wait a lot of time, the BatteryLifePercent chage. On that time the BatteryCurrent and BatteryVoltage also change and keep its values.

    I hope it help to find a solution.

     

    Thanks, Akvo

     

    Friday, October 12, 2007 1:50 PM