Estimate remaining battery time in android - android

I am trying to estimate the approx. remaining battery time in Android using below method, but it is not accurate in all the times. Please provide any suggestion to improve the accuracy,
Below method will save current time stamp in preference when battery reach 20%, 15%
It will calculate approx estimation from above 2 saved times
Thanks
public static String getBatteryEstimation(Context context){
String contentText = "";
try{
//timestamp recorded when battery reach 20%
long time1 = PreferencesUtil.getInstance().getLong(PreferencesUtil.KEY_BATTERY_THERESHOLD_TIME_1);
//timestamp recorded when battery reach 15%
long time2 = PreferencesUtil.getInstance().getLong(PreferencesUtil.KEY_BATTERY_THERESHOLD_TIME_2);
long timeDiffInMillis = time2 - time1;
long timeTakenFor1Percentage = Math.round(timeDiffInMillis/5);
long timeLastForNext15Percentage = timeTakenFor1Percentage * 15;
long hoursLast = Math.abs(TimeUnit.MILLISECONDS.toHours(timeLastForNext15Percentage));
long minutesLast = Math.abs(TimeUnit.MILLISECONDS.toMinutes(timeLastForNext15Percentage)- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLastForNext15Percentage)));
String timeLastMessage = "";
if(hoursLast > 0){
timeLastMessage = String.valueOf(minutesLast)+" hour(s) "+String.valueOf(minutesLast) + " min(s)";
} else {
timeLastMessage = String.valueOf(minutesLast) + " min(s)";
}
DateFormat dateFormat = new SimpleDateFormat("HH:mm dd MMM");
Date date = new Date();
contentText = String.format(context.getString(R.string.battery_low_content_1), timeLastMessage, dateFormat.format(date));
} catch (Exception e){
e.printStackTrace();
}
return contentText;
}

Estimating the remaining battery life is based on analytics. As the other people said you have to listen for battery level changes and in addition you have to keep track of them. After some time you will have enough data to calculate what is the average time the battery lasts. In addition you know when the battery drains fast and when drains slow so you can improve your estimation based on this. Also you will know in what time the user charges the devices. There are a lot of events that can be tracked and using the battery level. In addition you can also track when the screen is on or off. The algorithm of calculating the remaining battery life depends on you :)
You can try this :
Collect all information from the battery statistics, and count the usage in total. Then calculate the usage per second, how much the battery was drained per second.
Get the battery capacity in mAh, and calculate the remaining live with this formula: total capacity per speed of the usage
I hope this explains (at least a bit).

Related

I'm trying to get а real traffic stats data. But, When i count `TrafficStats.getMobileTxBytes()` for whole day its more than my data pack?

eg. I have a 1.5 GB data pack. It gives the total sum of 2.0 GB or more than that .
any idea about how to get correct speed every second.
TrafficStats.getTotalRxBytes() does not return your data pack value. It refers to the total received bytes (either wifi/mobile) since the last boot (turning ON phone). For mobile data, it will be TrafficStats.getMobileRxBytes(). More importantly, these values get reset in every reboot of device.
I have a 1.5 GB data pack. It gives the total sum of 2.0 GB or more
than that .
The android system does not know anything about your data pack. You are adding it again and again. When you call TrafficStats.getMobileRxBytes() at a moment, it returns total mobile data received upto this moment since last boot. Following is an explanation. Hope this helps.
// Suppose, you have just rebooted your device, then received 400 bytes and transmitted 300 bytes of mobile data
// After reboot, so far 'totalReceiveCount' bytes have been received by your device over mobile data.
// After reboot, so far 'totalTransmitCount' bytes have been sent from your device over mobile data.
// Hence after reboot, so far 'totalDataUsed' bytes used actually.
long totalReceiveCount = TrafficStats.getMobileRxBytes();
long totalTransmitCount = TrafficStats.getMobileTxBytes();
long totalDataUsed = totalReceiveCount + totalTransmitCount;
Log.d("Data Used", "" + totalDataUsed + " bytes"); // This will log 700 bytes
// After sometime passed, another 200 bytes have been transmitted from your device over mobile data.
totalDataUsed = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
Log.d("Data Used", "" + totalDataUsed + " bytes"); // Now this will log 900 bytes
any idea about how to get correct speed every second.
You cannot get actual speed this way. You can only calculate and show how much bytes have been received/transmitted in a second. All the speed meters in android do the same I think. Something like the following:
class SpeedMeter {
private long uptoNow = 0;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private ScheduledFuture futureHandle;
public void startMeter() {
final Runnable meter = new Runnable() {
public void run() {
long now = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
System.out.println("Speed=" + (now - uptoNow)); // Prints value for current second
uptoNow = now;
}
};
uptoNow = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
futureHandle = scheduler.scheduleAtFixedRate(meter, 1, 1, SECONDS);
}
public void stopMeter() {
futureHandle.cancel(true);
}
}
And use like this:
SpeedMeter meter = new SpeedMeter();
meter.startMeter();
Although this code is not perfect, however it will suit your needs.

Android CPU usage of each function

Currently in my Android code what I am doing to calculate each function CPU Usage is -
double start = System.currentTimeMillis();
double start1 = Debug.threadCpuTimeNanos();
foo();
double end = System.currentTimeMillis();
double end1 = Debug.threadCpuTimeNanos();
double t = (end - start);
double t1 = (end1 - start1)/1000000;
double CPUusage;
if(t==0){
CPUusage = 0;
}else{
CPUusage = (t1/t) * 100;
}
I am doing t1/t to calculate CPU Usage. Is this a correct way of calculating CPU usage of each function in my Android code or is it conceptually wrong? Request someone to guide me in this.
From documentation:
static long currentTimeMillis()
Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC.
Please, replace the double(s) you are using, with long(s).
While long(s) have precision issues, they are almost irrelevant for the variables used, also, the rounding will likely be close enough, that the returned value can be used in relation with each other
Also, you are comparing two independent values. Try either the current thread, or the full thread time.
From the Debug documentation:
public static long threadCpuTimeNanos()
Added in API level 1
Get an indication of thread CPU usage. The value returned indicates the amount of time that the current thread has spent executing code or waiting for certain types of I/O. The time is expressed in nanoseconds, and is only meaningful when compared to the result from an earlier call. Note that nanosecond resolution does not imply nanosecond accuracy. On system which don't support this operation, the call returns -1.
Try using, in the same Runnable (sequentially placed method calls):
long start = Debug.threadCpuTimeNanos();
foo();
long finish = Debug.threadCpuTimeNanos();
long outputValue = finish - start ;
System.out.println("foo() took " + outputValue + " ns.");

Android BLE: Convert ScanResult timestampNanos to System nanoTime

When scanning for Bluetooth Low Energy packets I receive ScanCallback with ScanResult being set. I can get "Device timestamp when the scan result was observed" with result.getTimestampNanos() but this time is not aligned with the Systems.nanoTime(). Is there a way to convert from one to the other?
Use the following code to convert the getTimestampNanos() to system millis by using SystemClock.elapsedRealtime():
long rxTimestampMillis = System.currentTimeMillis() -
SystemClock.elapsedRealtime() +
scanResult.getTimestampNanos() / 1000000;
This can be converted easily to a Date object:
Date rxDate = new Date(rxTimestampMillis);
Then you then get the time as a string:
String sDate = new SimpleDateFormat("HH:mm:ss.SSS").format(rxDate);
More elegant way to do that
long actualTime = System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(SystemClock.elapsedRealtimeNanos() - scanResult.getTimestampNanos(), TimeUnit.NANOSECONDS)```

Android milliseconds with zone offset to Date

I current have (from server) a date stamp returned as ticks (.NET Date).
In general I managed to convert the above by subtracting by 10000 to produce secs and offset accordingly to get EPOC ms.
Now, the issue is that the ms passed from server include the zone offset and what I needed to do is get a TimeZone object for the zone (always the same) and subtract the ms offset (depending on DST) from the original value to produce a new object to properly get a Date.
Any better way of doing this without so many conversion?
private static long netEpocTicksConv = 621355968000000000L;
public static Date dateTimeLongToDate(long ticks) {
TimeZone greeceTz = TimeZone.getTimeZone("Europe/Athens");
Calendar cal0 = new GregorianCalendar(greeceTz);
long time = (ticks - netEpocTicksConv)/ 10000;
time -= greeceTz.getOffset(time);
cal0.setTimeInMillis(time);
Date res = cal0.getTime();
return res;
}
Here's some code which doesn't quite do the right thing near DST transitions:
private static final long DOTNET_TICKS_AT_UNIX_EPOCH = 621355968000000000L;
private static final TimeZone GREECE = TimeZone.getTimeZone("Europe/Athens");
public static Date dateTimeLongToDate(long ticks) {
long localMillis = (ticks - DOTNET_TICKS_AT_UNIX_EPOCH) / 10000L;
// Note: this does the wrong thing near DST transitions
long offset = GREECE.getOffset(localMillis - GREECE.getRawOffset());
long utcMillis = localMillis - offset;
return new Date(utcMillis);
}
There's no need to use a Calendar here.
You can get it to be accurate around DST transitions unless it's actually ambiguous, in which case you could make it either always return the earlier version or always return the later version. It's fiddly to do that, but it can be done.
By subtracting the offset for standard time, we're already reducing the amount of time during which it will be incorrect. Basically this code now says, "Subtract the standard time (no daylight savings) offset from the local time, to get an approximation to the UTC time. Now work out the offset at that UTC time."

check current time between time interval android

I want to create an app that will allow the user to check whether or not the current time falls between a specified time interval. More specifically, I created a sql table using sqllite program, with the table specifying an end time and a start time for each record. The problem is that the type of data each field can be is limited to text, number, and other type other than a datetime type. So, how would I be able to check if the current time is between the start and end time since the format of time is in h:mm and not just an integer value that I could just do less than or greater than? Do I have to convert the current time to minutes?
You should be able to do the comparison even if time is not stored in the datetime type, here is a link that explains the conversion from string to time.
If that doesn't work, convert the time to seconds (int) and calculate the difference.
Try this. You can save and retrieve your time as String:
String to long: String.valueOf()
long to String: Long.valueOf()
Then, you use this procedure to check time:
//Time checker
private boolean timeCheck(long startTimeInput, long endTimeInput) {
long currentTime = System.currentTimeMillis();
if ((currentTime > startTimeInput) && (currentTime < endTimeInput)) {
return true;
} else {
return false;
}
}
And in your main program check it like this:
//You kept the times as String
if (timeCheck(Long.valueOf(start), Long.valueOf(end))) {
//it is in the interval
} else {
//not in the interval
}
I hope it helps.

Categories

Resources