NetworkStatsManager - what is the earliest possible start time? - android

I'm using the NetworkStatsManager class to retrieve the data usage of the apps.
If I provide 01.01.2018 as start time, it shows that my phone has sent out 5,4 GB.
If I provide 01.01.2017, it still shows 5,4 GB.
This lets me assume that there is a limit somehow regarding the start time. The documentation unfortunately does not mention anything regarding this.
So, how much in time can we go back?
Code:
This is the code which retrieves the data using querySummary:
private long[] getBytesSummary(Context context, int networkType, Calendar calendar) {
NetworkStatsManager networkStatsManager = (NetworkStatsManager) context.getSystemService(Context.NETWORK_STATS_SERVICE);
NetworkStats networkStats = null;
try {
networkStats = networkStatsManager.querySummary(
networkType,
Util.getSubscriberId(context, networkType),
calendar.getTimeInMillis(),
System.currentTimeMillis());
} catch (RemoteException e) {
if (debug) Log.e(TAG, "getBytesSummary: " + e.toString());
}
long[] result = new long[2];
long totalRxBytes = 0;
long totalTxBytes = 0;
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
if (networkStats != null) {
while (networkStats.hasNextBucket()) {
networkStats.getNextBucket(bucket);
int uid = bucket.getUid();
long uidRxBytes = bucket.getRxBytes();
long uidTxBytes = bucket.getTxBytes();
if (uidsWithNetworkUsageMap.indexOfKey(uid) < 0) {
long[] uidBytes = new long[2];
uidBytes[0] = uidRxBytes;
uidBytes[1] = uidTxBytes;
uidsWithNetworkUsageMap.put(uid, uidBytes);
} else {
long[] value = uidsWithNetworkUsageMap.get(uid);
value[0] = value[0] + uidRxBytes;
value[1] = value[1] + uidTxBytes;
uidsWithNetworkUsageMap.put(uid, value);
}
totalRxBytes += bucket.getRxBytes();
totalTxBytes += bucket.getTxBytes();
}
networkStats.close();
}
result[0] = totalRxBytes;
result[1] = totalTxBytes;
return result;
}
As you can see above, I give a calendar object to the method.
This is how I get the calendar for the current year:
public static Calendar getCalendarCurrentYear() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_YEAR, 1);
// for 0-12 clocks
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.AM_PM, Calendar.AM);
// for 0-24 clocks
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// calendar.set(Calendar.YEAR, 2017);
Log.i("DataUsage", "getCalendarCurrentYear: " + calendar.getTime());
return calendar;
}
This returns Mon Jan 01 00:00:00 GMT+01:00 2018.
If I set it now to 2017, the result is the same as for 2018.
Am I doing something wrong?
EDIT:
I just did some testing, the limit seems to be 3 months somehow.
Anything greater than 3 months as start time results in the same value.
Can anyone confirm that managed to get it working for more than 3 months from current time?
Or is there any official documentation addressing this?

It shows the data usage since last factory reset of your device.
May be the date that you are providing is older than your factory reset of your device.
hope i was helpful.

Related

Android Calendar.getInstance() does not get today after midnight

I have the following code:
Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
Calendar cal = Calendar.getInstance();
long diff = nextSchedule.getTimeInMillis() - cal.getTimeInMillis();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
As expected, around 11am it gave me 13/12hours but when doing the following in a widget:
Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextSchedule.getTimeInMillis(), pendingIntent);
Around 1:30am, it was still not updated. Only somewhen between 2am and 9am (I was asleep) it got updated.
A similar strange thing happens elsewhere. I have a calendar view (applandeo) with the following code: cvCalendar.setOnDayClickListener(eventDay -> showDateItems(eventDay,lvCalendar));
private void showDateItems(EventDay eventDay, ListView lvCalendar) {
Calendar cal = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),eventDay.getCalendar().get(Calendar.DATE));
cal2.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),1);
cal2.add(Calendar.MONTH, -1);
ArrayList<String> items = new ArrayList<>();
String line;
for (ItemsHistoryItem item: Utils.getInstance().itemsHistory) {
if (item.getxDay() < Utils.getInstance().calenderToEpoch(cal2) && item.getyDay() < Utils.getInstance().calenderToEpoch(cal2)) break;
if (item.getxDay() != Utils.getInstance().calenderToEpoch(cal) && item.getyDay() != Utils.getInstance().calenderToEpoch(cal)) continue;
line = item.getItemId() + ": $" + item.getAmount();
if (item.getxDay() == Utils.getInstance().calenderToEpoch(cal))
line += " (x day)";
else
line += " (y day)";
items.add(line);
}
ArrayAdapter<String> lcAdapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_list_item_1, items);
lvCalendar.setAdapter(lcAdapter);
}
long calenderToEpoch(Calendar cal2) {
return TimeUnit.MILLISECONDS.toDays(cal2.getTimeInMillis());
}
Basically, the above code scans dates of items and when the user select a certain date, he gets a list of items which dates (x and y) are of that date. When doing so during the day, it works. When doing so in 1:30am (for example), it shifts one day ahead so if the user clicks on 12-oct, he gets the items of 11-oct. Somwhen between 2am and 9am it "shifts" back and works as expected.
Any idea what's wrong here?
I have a suggestion for using alarmmanager properly if you want it to fire exactly at the time you want else it does not fire on time when device is in deep sleep mode and gets delayed:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// use setAlarmClock function of AlarmManager
// but this function will show an alarm icon on statusbar
// if you dont want to show that icon you can use
// setExactAndAllowWhileIdle function but that will not be
// perfectly exact
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// use setExact function of AlarmManager
}
else {
// use set function of AlarmManager
}
Apparently the default timezone for Calendar.getInstance() in my case was GMT+3 so at 3am the items were shown for their dates and the widget was updated. to fix it, I simply did the following:
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));

how to find difference between to dates in text view and show the number of days in some other textview [duplicate]

I want to compare two dates for my Android application, but I got a really weird issue.
For example:
If I set the back in the past date to 127 days ago:
this.dateEvent = System.currentTimeMillis() - (127 * 24 * 3600 * 1000)
And then compare it to the current date (Days between)
Calendar sDate = getDatePart(new Date(this.dateEvent));
Calendar eDate = getDatePart(new Date(System.currentTimeMillis()));
int daysBetween = 0;
while (sDate.before(eDate))
{
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
while (sDate.after(eDate))
{
eDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween ++;
}
return daysBetween;
It will return 22 which is not at all what was expected.
Did I make something wrong or is that an issue with the Calendar class ?
Here's a two line solution:
long msDiff = Calendar.getInstance().getTimeInMillis() - testCalendar.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
In this example it gets the number of days between date "testCalendar" and the current date.
Please refer this code, this may help you.
public String getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());
Date createdConvertedDate = null, expireCovertedDate = null, todayWithZeroTime = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
Date today = new Date();
todayWithZeroTime = dateFormat.parse(dateFormat.format(today));
} catch (ParseException e) {
e.printStackTrace();
}
int cYear = 0, cMonth = 0, cDay = 0;
if (createdConvertedDate.after(todayWithZeroTime)) {
Calendar cCal = Calendar.getInstance();
cCal.setTime(createdConvertedDate);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
} else {
Calendar cCal = Calendar.getInstance();
cCal.setTime(todayWithZeroTime);
cYear = cCal.get(Calendar.YEAR);
cMonth = cCal.get(Calendar.MONTH);
cDay = cCal.get(Calendar.DAY_OF_MONTH);
}
/*Calendar todayCal = Calendar.getInstance();
int todayYear = todayCal.get(Calendar.YEAR);
int today = todayCal.get(Calendar.MONTH);
int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
*/
Calendar eCal = Calendar.getInstance();
eCal.setTime(expireCovertedDate);
int eYear = eCal.get(Calendar.YEAR);
int eMonth = eCal.get(Calendar.MONTH);
int eDay = eCal.get(Calendar.DAY_OF_MONTH);
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
date1.clear();
date1.set(cYear, cMonth, cDay);
date2.clear();
date2.set(eYear, eMonth, eDay);
long diff = date2.getTimeInMillis() - date1.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return ("" + (int) dayCount + " Days");
}
I've finally found the easiest way to deal with that. Here is my code:
public int getTimeRemaining()
{
Calendar sDate = toCalendar(this.dateEvent);
Calendar eDate = toCalendar(System.currentTimeMillis());
// Get the represented date in milliseconds
long milis1 = sDate.getTimeInMillis();
long milis2 = eDate.getTimeInMillis();
// Calculate difference in milliseconds
long diff = Math.abs(milis2 - milis1);
return (int)(diff / (24 * 60 * 60 * 1000));
}
private Calendar toCalendar(long timestamp)
{
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
Hope it helps.
You should never use formula such 24 * 60 * 60 * 1000! Why? Because there is day saving time, and not all days have 24 hours, also what about leap year, that has +1 day. That's why there is a calendar class.
If you do not want to put any external library to your project like Jodatime, you could use pure Calendar class with very efficient function:
public static int numDaysBetween(final Calendar c, final long fromTime, final long toTime) {
int result = 0;
if (toTime <= fromTime) return result;
c.setTimeInMillis(toTime);
final int toYear = c.get(Calendar.YEAR);
result += c.get(Calendar.DAY_OF_YEAR);
c.setTimeInMillis(fromTime);
result -= c.get(Calendar.DAY_OF_YEAR);
while (c.get(Calendar.YEAR) < toYear) {
result += c.getActualMaximum(Calendar.DAY_OF_YEAR);
c.add(Calendar.YEAR, 1);
}
return result;
}
public long Daybetween(String date1,String date2,String pattern)
{
SimpleDateFormat sdf = new SimpleDateFormat(pattern,Locale.ENGLISH);
Date Date1 = null,Date2 = null;
try{
Date1 = sdf.parse(date1);
Date2 = sdf.parse(date2);
}catch(Exception e)
{
e.printStackTrace();
}
return (Date2.getTime() - Date1.getTime())/(24*60*60*1000);
}
Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
Date today = new Date();
long diff = today.getTime() - userDob.getTime();
int numOfYear = (int) ((diff / (1000 * 60 * 60 * 24))/365);
int numOfDays = (int) (diff / (1000 * 60 * 60 * 24));
int hours = (int) (diff / (1000 * 60 * 60));
int minutes = (int) (diff / (1000 * 60));
int seconds = (int) (diff / (1000));
I had the same need, I finally ended up using Joda Time, it is very convenient and offers lots of additional functions including the one you are looking for.
You can download the files from here.
Once you included the jar file into your project, you can easily do for example the following:
int daysBetween = Days.daysBetween(new DateTime(sDate), new DateTime(eDate)).getDays();
the best way :-
long fromCalender = Calender.getInstance();
fromCalender.set...// set the from dates
long toCalender = Calender.getInstance();
fromCalender.set...// set the to dates
long diffmili = fromCalender - toCalender;
long hours = TimeUnit.MILLISECONDS.toHours(diffmili);
long days = TimeUnit.MILLISECONDS.toDays(diffmili);
long min = TimeUnit.MILLISECONDS.toMinutes(diffmili);
long sec = TimeUnit.MILLISECONDS.toSeconds(diffmili);
Do like this it supports all Api Levels
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss",
Locale.ENGLISH);
try {
String datestart="June 14 2018 16:02:37";
cal.setTime(sdf.parse(datestart));// all done
Calendar cal1=Calendar.getInstance();
String formatted = sdf.format(cal1.getTime());//formatted date as i want
cal1.setTime(sdf.parse(formatted));// all done
long msDiff = cal1.getTimeInMillis() - cal.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
Toast.makeText(this, "days="+daysDiff, Toast.LENGTH_SHORT).show();
} catch (ParseException e) {
e.printStackTrace();
}
fun TimeZone.daysBetween(from: Date, to: Date): Int {
val offset = rawOffset + dstSavings
return ((to.time + offset) / 86400000).toInt() - ((from.time + offset) / 86400000).toInt()
}
Have a try:
val f = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
timeZone = TimeZone.getTimeZone("GMT")
}
val df = f.parse("2019-02-28 22:59:59")
val dt = f.parse("2019-02-28 23:00:00")
TimeZone.getTimeZone("GMT").daysBetween(df, dt) // 0
TimeZone.getTimeZone("GMT+1").daysBetween(df, dt) // 1
java.time and ThreeTenABP
I should like to contribute the modern answer: Use java.time, the modern Java date and time API for your date work. If developing for Android API level 25 or lower, then through the backport for Android, ThreeTenABP (link at the bottom).
LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
LocalDate sDate = eDate.minusDays(127);
long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
System.out.println(daysBetween);
When I ran this code today, the output was the expected:
127
Notice that the code is not only shorter, just one line for finding the difference; it is also clearer and more natural to read. The classes Date and Calendar that you used are poorly designed and long outdated. I recommend you don’t use them.
What went wrong in your code?
You’ve got an int overflow in your conversion of 127 days to milliseconds. In mathematics 127 * 24 * 3600 * 1000 equals 10 972 800 000. Since the numbers you multiply are ints, Java performs the multiplication in int, and the largest number an int can hold is 2 147 483 647, far from enough for your expected result. In this situation it would have been nice if Java would have thrown an exception or in some other way have made us aware of the error. It doesn’t. It tacitly throws away the high order bits, giving us a result of -1 912 101 888. Subtracting this negative number from the current time is equivalent to adding 22 days and a few hours. This explains why you got 22. Funny that 13 answers have been posted and it seems that no one has spotted this …
Even when doing the multiplication using the long type, it still doesn’t calculate 127 days correctly, though. If the 127 days cross a transition to or from summer time (DST), which in France is the case during 254 of the 365 days of a year, the day of the transition is not 24 hours, but either 23 or 25. Which causes an incorrect number of milliseconds.
You should always leave date math to proven library methods. Never hand code it yourself. It’s more complicated than most of us think, so the risk of doing it incorrectly is high.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
The best solution that worked for me is :
private static int findDaysDiff(long unixStartTime,long unixEndTime)
{
Calendar calendar1 = Calendar.getInstance();
calendar1.setTimeInMillis(unixStartTime);
calendar1.set(Calendar.HOUR_OF_DAY, 0);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND, 0);
calendar1.set(Calendar.MILLISECOND, 0);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(unixEndTime);
calendar2.set(Calendar.HOUR_OF_DAY, 0);
calendar2.set(Calendar.MINUTE, 0);
calendar2.set(Calendar.SECOND, 0);
calendar2.set(Calendar.MILLISECOND, 0);
return (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(24 * 60 * 60 * 1000));
}
Since it first converts Hour , Minute, Second and Millisecond to 0 and now the difference will be only in days.
the answer is not correct in some dates like "2019/02/18" , "2019/02/19" but i edit and resolve bug
this is best method :
public int getCountOfDays(String createdDateString, String expireDateString) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date createdConvertedDate = null;
Date expireCovertedDate = null;
try {
createdConvertedDate = dateFormat.parse(createdDateString);
expireCovertedDate = dateFormat.parse(expireDateString);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar start = new GregorianCalendar();
start.setTime(createdConvertedDate);
Calendar end = new GregorianCalendar();
end.setTime(expireCovertedDate);
long diff = end.getTimeInMillis() - start.getTimeInMillis();
float dayCount = (float) diff / (24 * 60 * 60 * 1000);
return (int) (dayCount);
}
Enjoy and if was helpefull +vote to this answer ;)
Kotlin Extension:
fun Date?.getDaysBetween(dest: Date?): Int {
if(this == null || dest == null) return 0
val diff = abs(this.time - dest.time)
val dayCount = diff.toFloat() / (24 * 60 * 60 * 1000)
return dayCount.toInt()
}
I am count the days between last submission date and current date if it is less than zero then student cannot give submission. I am working with kotlin. The below code helps you.
var calendar=Calendar.getInstance().time
var dateFormat= SimpleDateFormat("dd/M/yyyy")
var d2=dateFormat.parse(data.get("date").toString())
var cd=dateFormat.format(calendar)
var d1=dateFormat.parse(cd)
var diff=d2.time-d1.time
var ddd= TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
This is the Java 8 java.time version which works perfectly for me. You might want to make sure that startDate and endDate are set to the same time, otherwise days might vary by +-1!
These are the Kotlin versions I just copy/pasted.
private fun getDawnOfDay(instant: Instant): Temporal =
LocalDate.from(instant.atZone(ZoneOffset.UTC)).atStartOfDay()
fun getNumberOfDaysInBetween(startDate: Date, endDate: Date) =
Duration.between(getDawnOfDay(startDate.toInstant()), getDawnOfDay(endDate.toInstant()))
.toDays()
I have just modified a little bit most popular answer.
Here is my solution:
daysBetween() - Return days count between two dates.
public static long daysBetween(Date date1, Date date2) {
long msDiff = resetTimeToDateStart(date1).getTime() - resetTimeToDateStart(date2).getTime();
return TimeUnit.MILLISECONDS.toDays(msDiff);
}
private static Date resetTimeToDateStart(Date dDate){
if (Utils.isNull(dDate)){
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(dDate);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
int difference in days=(present_year - oldyear) * 365 + (present_month - oldmonth)*30 + (present_date-olddate);
All above answers calculating millis_diff / (24 * 60 * 60 * 1000) is simply wrong if you consider 23:59:59 ~ 00:00:00 as two different days and expect offset day count as 1, instead of 0.
A kotlin version gives you count 1, based on #oleksandr-albul answer above.
fun getDayCountBetween(to: Long, from: Long): Int {
if (to <= from) return 0
val calendar = Calendar.getInstance()
var count = 0
// get day count between 'to' and Jan 1st.
calendar.timeInMillis = to
val year = calendar.get(Calendar.YEAR)
count += calendar.get(Calendar.DAY_OF_YEAR)
// minus day count between 'from' and Jan 1st.
calendar.timeInMillis = from
count -= calendar.get(Calendar.DAY_OF_YEAR)
// plus day count of all the gap years.
while (calendar.get(Calendar.YEAR) < year) {
count += calendar.getActualMaximum(Calendar.DAY_OF_YEAR)
calendar.add(Calendar.YEAR, 1)
}
return count
}

queryUsageStats interval duration

I'm using UsageStatsManager API to get usage statistics for a certain time interval. All works fine if I use the predefined intervals i.e. INTERVAL_DAILY, INTERVAL_WEEKLY, INTERVAL_MONTHLY, INTERVAL_YEARLY. But if I want to view the data for the past 2 or 3 hours, I am getting today's data for the whole day. I have tried using Calendars and System.currentTimeMillis() but that didn't give me filtered results.
Calendar approach :
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
And pass this to queryUsageStats method like this:
usageList = usm.queryUsageStats(interval, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis());
where interval is INTERVAL_BEST.
System.currentTimeMillis() approach :
long startTime = System.currentTimeMillis() - 7200*1000 // 7200 seconds i.e. 2 hrs
long endTime = System.currentTimeMillis();
Pass this to queryUsageStats just like above :
usageList = usm.queryUsageStats(interval, startTime, endTime);
where interval is again INTERVAL_BEST.
I'd like to know whether it's possible to get data for this duration i.e. less than a day, as the INTERVAL_BEST hasn't been documented properly to include this information. Any help would be appreciated as I'm stuck on this problem.
As UsageStatsManager doc says:
A request for data in the middle of a time interval will include that interval.
It seems that usage data is stored in buckets, and minimum bucket is a day, so you can't query usage stats for period less than a day. Even if you query a one-hour interval for a particular day, usage stats for the whole day is returned.
A little late to the party, but I think this might be useful to some.
You could use the queryEvents(long startTime, long endTime) from UsageStatsManager for achieving the desired result. The method could look like this (inspired by this post):
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HashMap<String, AppUsageInfo> queryUsageStatistics(Context context, long startTime, long endTime) {
UsageEvents.Event currentEvent;
List<UsageEvents.Event> allEvents = new ArrayList<>();
HashMap<String, AppUsageInfo> map = new HashMap<>();
UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
assert mUsageStatsManager != null;
// Here we query the events from startTime till endTime.
UsageEvents usageEvents = mUsageStatsManager.queryEvents(startTime, endTime);
// go over all events.
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
String packageName = currentEvent.getPackageName();
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED || currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED ||
currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED) {
allEvents.add(currentEvent); // an extra event is found, add to all events list.
// taking it into a collection to access by package name
if (!map.containsKey(packageName)) {
map.put(packageName, new AppUsageInfo());
}
}
}
// iterate through all events.
for (int i = 0; i < allEvents.size() - 1; i++) {
UsageEvents.Event event0 = allEvents.get(i);
UsageEvents.Event event1 = allEvents.get(i + 1);
//for launchCount of apps in time range
if (!event0.getPackageName().equals(event1.getPackageName()) && event1.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
// if true, E1 (launch event of an app) app launched
Objects.requireNonNull(map.get(event1.getPackageName())).launchCount++;
}
//for UsageTime of apps in time range
if (event0.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED &&
(event1.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED || event1.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED)
&& event0.getPackageName().equals(event1.getPackageName())) {
long diff = event1.getTimeStamp() - event0.getTimeStamp();
Objects.requireNonNull(map.get(event0.getPackageName())).timeInForeground += diff;
}
}
// and return the map.
return map;
}
The AppUsageInfo class would be:
public class AppUsageInfo {
public long timeInForeground;
public int launchCount;
AppUsageInfo() {
this.timeInForeground = 0;
this.launchCount = 0;
}
}
To then get the usage stats for the last two hours, simply call
Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();
HashMap<String, AppUsageInfo> result = queryUsageStatistics(context, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis();

Android get dates as long values

How do I get 11:59 PM of the previous night and 12:00 AM of tonight expressed as long values???
So many different date options I'm confused
you can use this calculation to do so.
//11:59 PM of the previous night and 12:00 AM of tonight
Calendar prevDate = Calendar.getInstance();
if(prevDate.get(Calendar.DATE)==1)
{
if(prevDate.get(Calendar.MONTH)==0)
{
prevDate.set(Calendar.YEAR, prevDate.get(Calendar.YEAR)-1);
prevDate.set(Calendar.MONTH,Calendar.DECEMBER);
prevDate.set(Calendar.DAY_OF_MONTH,31);
}
else
{
prevDate.set(Calendar.MONTH,prevDate.get(Calendar.MONTH)-1);
prevDate.set(Calendar.DAY_OF_MONTH, prevDate.getMaximum(Calendar.DAY_OF_MONTH));
}
}
else
{
prevDate.set(Calendar.DAY_OF_MONTH,prevDate.get(Calendar.DAY_OF_MONTH)-1);
}
prevDate.set(Calendar.HOUR_OF_DAY, 11);
prevDate.set(Calendar.MINUTE, 59);
Calendar currDate = Calendar.getInstance();
currDate.set(Calendar.HOUR_OF_DAY, 0);
currDate.set(Calendar.MINUTE, 0);
long prevDateLong = prevDate.getTimeInMillis();
long currDateLong = currDate.getTimeInMillis();
Log.i("", prevDate.toString()+" >>>>>>>> "+currDate.toString());
Log.i("", prevDateLong+" >>>>>>>>> "+currDateLong);
All Java dates are longs underneath. It's the number of milliseconds since midnight on 1-Jan-1970.
Date today = new SimpleDateFormat("yyyy-MMM-dd").parse("2012-Oct-28"); // today at midnight
long millis = today.getTime();
I'd recommend that you look at the java.util.Calendar class. It's not hard, just tedious.
http://www.exampledepot.com/search/luceneapi_node/Calendar

Wrong "week of year" in Android

The number of "week of year" returned from a Date is wrong.
This is my code:
Calendar c = Calendar.getInstance();
c.setTime(my_date);
int num_week = c.get(Calendar.WEEK_OF_YEAR);
If my_date (type Date) is 01/01/2011, I supposed that "week of year" is 1. But it returned 52.
I try to test with these methods but I don't obtain anything:
c.setFirstDayOfWeek(6);
c.setMinimalDaysInFirstWeek(1)
If It's interesting, I'm from Spain, and our week begin on Monday.
Have I to do anything for obtain right results?
Thanks!
This may be Android/Harmony-specific. For example, this works for me with desktop Java:
import java.util.*;
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(2011, 0, 1, 0, 0, 0);
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR)); // Prints 52
calendar.setMinimalDaysInFirstWeek(1);
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR)); // Prints 1
}
}
Can you confirm that the exact same code (modulo logging options) logs 52 twice on Android?
Here you can view the reference by oracle
https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html
And I have placed a quick solution to find the week count of current day. You can alter and optimize as your way. Also set according to your convenient GMT value
public static int getWeeksOfMonth() {
DATESTATUS = false;
VALUESTATUS = false;
int weekCount;
WEEK_OF_MONTH= -1;
// get the supported ids for GMT+04:00 (Pacific Standard Time)
String[] ids = getAvailableIDs(4 * 60 * 60 * 1000);
// if no ids were returned, something is wrong. get out.
if (ids.length == 0)
return WEEK_OF_MONTH;
// create a Pacific Standard Time time zone
SimpleTimeZone pdt = new SimpleTimeZone(4 * 60 * 60 * 1000, ids[0]);
// create a GregorianCalendar with the Pacific Daylight time zone
// and the current date and time
Calendar calendar = new GregorianCalendar(pdt);
Date trialTime = new Date();
calendar.setTime(trialTime);
weekCount = calendar.get(Calendar.WEEK_OF_YEAR);
return recursiveWeekCountCheck(calendar, weekCount);
}
private static int recursiveWeekCountCheck(Calendar calendar, int weekCount) {
if (calendar.get(Calendar.MONTH) == Calendar.DECEMBER && weekCount == 1) {
DATESTATUS = true;
calendar.add(Calendar.DAY_OF_MONTH, -1);
weekCount = calendar.get(Calendar.WEEK_OF_YEAR);
recursiveWeekCountCheck(calendar, weekCount);
}
if (!VALUESTATUS){
VALUESTATUS = true;
if (DATESTATUS) {
weekCount++;
WEEK_OF_MONTH = weekCount;
} else {
WEEK_OF_MONTH = weekCount;
}
}
return WEEK_OF_MONTH;
}
At the end just call the method getWeeksOfMonth();

Categories

Resources