Ok, so I was building a clock that would give out times in the form of Log10(hour) and also minute and second in the same format, but I keep getting strange outputs when this runs. I get mostly NANs and sometimes infinity(or its negative). I have a feeling that something is wrong with the numbers that I am using(like maybe they are too large or something like that) NOTE: currentTime is a long, calendar is a Calendar, and hour, minute, and second are doubles. Also the clock variable is a JLabel. After the program goes through two iterations it always switches over to NANs.
this.timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
currentTime = System.currentTimeMillis();
calendar.setTime(new Date(currentTime));
hour = Math.log10(hour);
minute = Math.log10(minute);
second = Math.log10(second);
System.out.println(hour + " " + minute + " " + second);
return null;
}
#Override
protected void done() {
clock.setText("<html><body><p>Log Time: "
+ "Log<sub>10</sub>(" + hour + ") || "
+ "Log<sub>10</sub>(" + minute + ") || "
+ "Log<sub>10</sub>(" + second + ")</p></body></html>");
}
}.execute();
}
}, 0, 200);
This code doesn't make a lot of sense:
currentTime = System.currentTimeMillis();
calendar.setTime(new Date(currentTime));
hour = Math.log10(hour);
minute = Math.log10(minute);
second = Math.log10(second);
You're setting the time in calendar - but then completely ignoring it. I would expect you'd want something like:
currentTime = System.currentTimeMillis();
calendar.setTime(new Date(currentTime));
hour = Math.log10(calendar.get(Calendar.HOUR_OF_DAY));
minute = Math.log10(calendar.get(Calendar.MINUTE));
second = Math.log10(calendar.get(Calendar.SECOND));
EDIT: As noted on comments, you also need to consider what you'll do when the hour, minute or second is 0. (It's very unclear why you'd want to use a log-based clock to start with, to be honest.)
Related
I use UsageStats feature of Android, but the smallest interval is DAILY INTERVAL.
long time = System.currentTimeMillis();
List<UsageStats> appList = manager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - DAY_IN_MILLI_SECONDS, time);
How can I get UsageStats in an hourly interval?
All credit goes to this answer. I have learned from that one.
How can we collect app usage data for customized time range (e.g. for per 1 hour)?
We have to call queryEvents(long begin_time, long end_time) method as it will provide us all data starting from begin_time to end_time. It give us each app data through foreground and background events instead of total spent time like queryUsageStats() method. So, using foreground and background events time stamp, we can count the number of times an app has been launched and also can find out the usage duration for each app.
Implementation to Collect Last 1 Hour App Usage Data
At first, add the following line in the AndroidManifest.xml file and also request user to get permission of usage access.
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
Add the following lines inside any method
long hour_in_mil = 1000*60*60; // In Milliseconds
long end_time = System.currentTimeMillis();
long start_time = end_time - hour_in_mil;
Then, call the method getUsageStatistics()
getUsageStatistics(start_time, end_time);
getUsageStatistics methiod
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
void getUsageStatistics(long start_time, long end_time) {
UsageEvents.Event currentEvent;
// List<UsageEvents.Event> allEvents = new ArrayList<>();
HashMap<String, AppUsageInfo> map = new HashMap<>();
HashMap<String, List<UsageEvents.Event>> sameEvents = new HashMap<>();
UsageStatsManager mUsageStatsManager = (UsageStatsManager)
context.getSystemService(Context.USAGE_STATS_SERVICE);
if (mUsageStatsManager != null) {
// Get all apps data from starting time to end time
UsageEvents usageEvents = mUsageStatsManager.queryEvents(start_time, end_time);
// Put these data into the map
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED ||
currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED) {
// allEvents.add(currentEvent);
String key = currentEvent.getPackageName();
if (map.get(key) == null) {
map.put(key, new AppUsageInfo(key));
sameEvents.put(key,new ArrayList<UsageEvents.Event>());
}
sameEvents.get(key).add(currentEvent);
}
}
// Traverse through each app data which is grouped together and count launch, calculate duration
for (Map.Entry<String,List<UsageEvents.Event>> entry : sameEvents.entrySet()) {
int totalEvents = entry.getValue().size();
if (totalEvents > 1) {
for (int i = 0; i < totalEvents - 1; i++) {
UsageEvents.Event E0 = entry.getValue().get(i);
UsageEvents.Event E1 = entry.getValue().get(i + 1);
if (E1.getEventType() == 1 || E0.getEventType() == 1) {
map.get(E1.getPackageName()).launchCount++;
}
if (E0.getEventType() == 1 && E1.getEventType() == 2) {
long diff = E1.getTimeStamp() - E0.getTimeStamp();
map.get(E0.getPackageName()).timeInForeground += diff;
}
}
}
// If First eventtype is ACTIVITY_PAUSED then added the difference of start_time and Event occuring time because the application is already running.
if (entry.getValue().get(0).getEventType() == 2) {
long diff = entry.getValue().get(0).getTimeStamp() - start_time;
map.get(entry.getValue().get(0).getPackageName()).timeInForeground += diff;
}
// If Last eventtype is ACTIVITY_RESUMED then added the difference of end_time and Event occuring time because the application is still running .
if (entry.getValue().get(totalEvents - 1).getEventType() == 1) {
long diff = end_time - entry.getValue().get(totalEvents - 1).getTimeStamp();
map.get(entry.getValue().get(totalEvents - 1).getPackageName()).timeInForeground += diff;
}
}
smallInfoList = new ArrayList<>(map.values());
// Concatenating data to show in a text view. You may do according to your requirement
for (AppUsageInfo appUsageInfo : smallInfoList)
{
// Do according to your requirement
strMsg = strMsg.concat(appUsageInfo.packageName + " : " + appUsageInfo.launchCount + "\n\n");
}
TextView tvMsg = findViewById(R.id.MA_TvMsg);
tvMsg.setText(strMsg);
} else {
Toast.makeText(context, "Sorry...", Toast.LENGTH_SHORT).show();
}
}
AppUsageInfo.class
import android.graphics.drawable.Drawable;
class AppUsageInfo {
Drawable appIcon; // You may add get this usage data also, if you wish.
String appName, packageName;
long timeInForeground;
int launchCount;
AppUsageInfo(String pName) {
this.packageName=pName;
}
}
How can I customize these codes to collect per 1 hour data?
As you want to get per hour data, please change the end_time and start_time value for every hour data. For instance: If I would try to collect past per hour data (for past 2 hour data). I would do the following thing.
long end_time = System.currentTimeMillis();
long start_time = end_time - (1000*60*60);
getUsageStatistics(start_time, end_time);
end_time = start_time;
start_time = start_time - hour_in_mil;
getUsageStatistics(start_time, end_time);
However, you may use a Handler to skip repeatedly writing start_time and end_time to change value of these variables. Each time data will be collected for one hour, a task will be completed and after automatically changing the values of the variables, you will again call the getUsageStatistics method.
Note: Maybe, you will not be able to retrieve data for more than past 7.5 days as events are only kept by the system for a few days.
Calendar cal = (Calendar) Calendar.getInstance().clone();
//I used this and it worked, only for 7 days and a half ago
if (daysAgo == 0) {
//Today - I only count from 00h00m00s today to present
end = cal.getTimeInMillis();
start = LocalDate.now().toDateTimeAtStartOfDay().toInstant().getMillis();
} else {
long todayStartOfDayTimeStamp = LocalDate.now().toDateTimeAtStartOfDay().toInstant().getMillis();
if (mDaysAgo == -6) {
//6 days ago, only get events in time -7 days to -7.5 days
cal.setTimeInMillis(System.currentTimeMillis());
cal.add(Calendar.DATE, daysAgo + 1);
end = cal .getTimeInMillis();
start = end - 43200000;
} else {
//get events from 00h00m00s to 23h59m59s
//Current calendar point to 0h0m today
cal.setTimeInMillis(todayStartOfDayTimeStamp);
cal.add(Calendar.DATE, daysAgo + 1);
end = calendar.getTimeInMillis();
cal.add(Calendar.DATE, -1);
start = calendar.getTimeInMillis();
}
}
I don't think it's possible, even if you ask for data in the middle of an interval, it looks like the data is stored in buckets and the minimum bucket is a day.
In UsageStatsManager documentation, it says:
A request for data in the middle of a time interval will include that interval.
Also, INTERVAL_BEST is not a real interval, it just selects one of the available intervals for the given time range. In
UsageStatsManager.java source code, it says:
/**
* The number of available intervals. Does not include {#link #INTERVAL_BEST}, since it
* is a pseudo interval (it actually selects a real interval).
* {#hide}
*/
public static final int INTERVAL_COUNT = 4;
Yes, Android is providing minimum INTERVAL_DAILY. But for the best result, you can use INTERVAL_BEST. Android is giving the best interval timer for the given time range in queryUsageStats(int, long, long).
Happy coding...
I have to create a scheduler which runs at a particular day of week. For example my scheduler should run on every Monday at 11:50 PM. Please help me through the task.
PS: I went through these links How to schedule task daily + onStart() in Play 2.0.4? suggests using a cronJob expression to calculate next execution time. Is there a way to do using akka by default i.e. without a cronJob expression?
schedule(initialDelay: Duration, frequency: Duration, receiver: ActorRef, message: Any)
You just need to calculate the initialDelay on the scale (minutes, hours, days) that you want. In your case, you have to find out the time until the next Monday. That's not an issue related with Akka, just plain Java:
//In minutes
private long timeToNextMonday(){
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR, 23);
now.set(Calendar.MINUTE, 50);
int weekday = now.get(Calendar.DAY_OF_WEEK);
System.out.println(now.getTime());
if (weekday != Calendar.MONDAY){
// calculate how much to add
// the 2 is the difference between Saturday and Monday
int days = (Calendar.SATURDAY - weekday + 2) % 7;
now.add(Calendar.DAY_OF_YEAR, days);
}
Date date = now.getTime();
return (now.getTime().getTime() - System.currentTimeMillis())/(1000*60);
}
And then the schedule call itself is pretty straightforward:
Akka.system().scheduler().schedule(
Duration.create(timeToNextMonday, TimeUnit.MINUTES),
Duration.create(7, TimeUnit.DAYS),
actor, actorMessage,
Akka.system().dispatcher(), null);
public void onStart(Application application) {
try{
Duration.create(timeToNextMonday(), TimeUnit.MILLISECONDS),
Duration.create(7, TimeUnit.DAYS),
new Runnable() {
#Override
public void run() {
JPA.withTransaction(new F.Callback0() {
#Override
public void invoke() throws Throwable {
System.out.println("Printing time : " + new Date());
}
});
}
},
Akka.system().dispatcher());
}
catch (Throwable t){
HashMap<String,String> params = new HashMap<>();
Logger.error("{}:params:{}", "error while starting cron for Historical TW questions", params, t);
}
super.onStart(application);
}
//In minutes
private long timeToNextMonday(){
Calendar now = Calendar.getInstance();
while (now.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
now.add(Calendar.DATE, 1);
}
now.set(Calendar.HOUR,11);
now.set(Calendar.AM_PM,Calendar.PM);
now.set(Calendar.MINUTE,50);
now.set(Calendar.SECOND,00);
now.set(Calendar.MILLISECOND,00);
return now.getTime().getTime() - Calendar.getInstance().getTime().getTime();
}
Explanation -
StartTime is being fetched from a table (EX- 2014-07-25 12:00:00)
Startwork() does the insert function
do {
long time = startTime.getTime() + (((59 * 60) + 59) * 1000);
Date endTime = new Date(time);
System.out.println("INFO: Calling startWork(" + startTime + "," + endTime + ")");
startWork(startTime, endTime);
startTime = new Date(startTime.getTime() + (60 * 60 * 1000));
systemHour = new Date(new Date().getYear(), new Date().getMonth(), new Date().getDate(), new Date().getHours(), 0, 0);
String stringToUpdateLastProcessedTime = "update meter_thread set last_processed_time='" + sdf.format(startTime) + "' where name='Gateway Park Occupancy' ";
mysqlStatement.executeUpdate(stringToUpdateLastProcessedTime);
}
while (startTime.getTime() != systemHour.getTime());
System.out.println("INFO: Switching to live mode");
Thread.sleep(1000 * 55 * 60);
The problem I am encountering is that, the program is getting executed for future dates if the starttime fetched from the table is (ex -2014-07-25 12:00:00) and the current system time is (ex-2014-07-25 12:20:00) instead of switching to live mode.
Please help in where I am going wrong.
I would change:
while(startTime.getTime() != systemHour.getTime())
For
while(startTime.getTime() > systemHour.getTime())
Is rather improbable (almost impossible) that your loop check will match to the millisecond the startTime instant.
Task - Turn a bulb on and off at a specified time during a day. I need to know how to fix my code as per the information given below. I also need to know if I am using the timer class correctly, that is, is my code design correct ? The code may work but it could be bad design which will cause problems later. I don't want that to happen.
Output is (This is not the output i really wanted :( ) -
This is the main program
Current time is - xxx
Future time is - xxx+5sec
Future time is - xxx+10sec
Main program ends
Bulb B1 is OFF
Desired output -
This is the main program
Current time is - xxx
Future time is - xxx+5sec
Future time is - xxx+10sec
Bulb B1 is ON //first on
Bulb B1 is OFF //then off
Main program ends//This should always be in the end.
How do I fix the code below to get what I want ?
Bulb Class
class Bulb {
private boolean state = false;//On or off
private String name;
Bulb(String name){
this.name = name;
}
public void setState(boolean state){
this.state = state;
if(this.state == true){
System.out.println("Bulb " + name + " is ON");
}else{
System.out.println("Bulb " + name + " is OFF");
}
}
public boolean getState(){
return this.state;
}
}
BulbJob class which is a TimerTask
import java.util.*;
class BulbJob extends TimerTask{
private Bulb bulbToHandle;
private boolean setBulbStateEqualTo;
BulbJob(Bulb toHandle){
this.bulbToHandle = toHandle;
}
//NOTE: Must be called before run(), otherwise default value is used
public void setBulbStateEqualTo(boolean setBulbStateEqualTo){
this.setBulbStateEqualTo = setBulbStateEqualTo;
}
//NOTE: call run() only before calling above method
public void run(){
this.bulbToHandle.setState(setBulbStateEqualTo);//Set on or off
}
}
BulbScheduler class - this schedules when the bulb is turned on or off.
import java.util.*;
#SuppressWarnings( "deprecation" )
class BulbScheduler {
public static void main(String args[]) throws InterruptedException{
System.out.println("This is the main program");
Timer time = new Timer();
Bulb b1 = new Bulb("B1");
BulbJob bj = new BulbJob(b1);
bj.setBulbStateEqualTo(true);//Task - Turn bulb on at time = afterCurrent
Date current = new Date();//Get current time and execute job ten seconds after this time
Date afterCurrent = (Date) current.clone();
System.out.println("Current time is - " + current);
int currentSecs = current.getSeconds();
int offset = 5;//number of seconds
afterCurrent.setSeconds(currentSecs + offset);
System.out.println("Future time is - " + afterCurrent);
time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent
//Now turn the bulb off at new time = newest afterTime
afterCurrent.setSeconds(currentSecs + 2 * offset);
System.out.println("Future time is - " + afterCurrent);
bj.setBulbStateEqualTo(false);//Task - Now turn the bulb off at time = afterCurrent
System.out.println("Main program ends");
}
}
This section:
time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent
//Now turn the bulb off at new time = newest afterTime
afterCurrent.setSeconds(currentSecs + 2 * offset);
only schedules one task. If you need to schedule it twice, do so explicitly:
time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent
//Now turn the bulb off at new time = newest afterTime
afterCurrent.setSeconds(currentSecs + 2 * offset);
time.schedule(bj, afterCurrent);//Schedule job "bj" at time = afterCurrent
Also. this line:
bj.setBulbStateEqualTo(false);
is executed in the main thread, so it will before both tasks. You should schedule that statement to run between the two tasks.
Code is fixed, but this version cannot exit main in the end -
import java.util.*;
#SuppressWarnings( "deprecation" )
class BulbScheduler {
public static void main(String args[]) throws InterruptedException{
System.out.println("This is the main program");
Timer timeOn = new Timer();
Timer timeOff = new Timer();
Bulb b1 = new Bulb("B1");
BulbJob bjOn = new BulbJob(b1);
BulbJob bjOff = new BulbJob(b1);
bjOn.setBulbStateEqualTo(true);//Task - Turn bulb on
bjOff.setBulbStateEqualTo(false);//Task - Then turn the bulb off later
Date current = new Date();//Get current time and execute job ten seconds after this time
Date afterCurrent = (Date) current.clone();
System.out.println("Current time is - " + current);
int currentSecs = current.getSeconds();
int offset = 3;//number of seconds
afterCurrent.setSeconds(currentSecs + offset);
System.out.println("Future time is - " + afterCurrent);
timeOn.schedule(bjOn, afterCurrent);//Schedule job "bj" at time = afterCurrent
//Now turn the bulb off at new time = latest afterCurrent
afterCurrent.setSeconds(currentSecs + 2 * offset);
System.out.println("Future time is - " + afterCurrent);
timeOff.schedule(bjOff, afterCurrent);
System.out.println("Main program ends");
}
}
you are not setting the time correctly. Need to use GreogarianCalendar.
java.util.Date is used but cannot use its setSeconds Read the Javadoc its pretty good and will help a lot. public void setSeconds(int seconds)
Deprecated. As of JDK version 1.1, replaced by Calendar.set(Calendar.SECOND, int seconds).
Sets the seconds of this Date to the specified value. This Date object is modified so that it represents a point in time within the specified second of the minute, with the year, month, date, hour, and minute the same as before, as interpreted in the local time zone.
You need to use java.util.GregorianCalendar # add(Calendar.SECOND, howManySeconds)
then use getDate() to get the Date object and send it to the Timer.
calling setSecond on a date wont change the other fields. see the java doc of Calendar.add and roll. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html and see the rules in the class inro.
Can also use the timer object's schedule(TimerTask task, long delay)
Schedules the specified task for execution after the specified delay (milliseconds).
Modified code -
import java.util.*;
class BulbScheduler {
private static java.text.SimpleDateFormat sdf1 = new java.text.SimpleDateFormat ("yy MM dd HH mm ss");
//helper
static String formatDate(Date d){
return sdf1.format(d);
}
public static void main(String args[]) throws InterruptedException{
System.out.println("This is the main method");
java.util.GregorianCalendar cal = new java.util.GregorianCalendar();
Bulb b1 = new Bulb("bulb 1", false);
Bulb b2 = new Bulb("bulb 2", false);
System.out.println("Time now " + formatDate(cal.getTime()));
Timer timer = new Timer("bulbs");
BulbJob b1On = new BulbJob(b1, true);
BulbJob b1Off = new BulbJob(b1, false);
BulbJob b2On = new BulbJob(b2, true);
BulbJob b2Off = new BulbJob(b2, false);
timer.schedule(b1On, 3 * 1000);//after 3 seconds
timer.schedule(b2On, 7 * 1000);//after 4 seconds
timer.schedule(b1Off, 6 * 1000);//after 6 seconds; before b2 on
b1On = new BulbJob(b1, true);
timer.schedule(b1On, 9 * 1000);
//if you want main to wait need to add code here to make it wait,
// but even if does the JVM wont exit. Its just a method. The JVM exits when all non daemon threads are done
// or System.exit is called
System.out.println("This is the main method ending; but other threads might be running ...");
//main thread JVM waits for all other non dameons to end
}
}
Changed BulbJob
import java.util.*;
class BulbJob extends TimerTask{
private Bulb bulbToHandle;
private boolean bulbNewState;//dont start propert names with set
//why a seperate property when we need to set the new state everytime and cannot reuse jobs?
BulbJob(Bulb toHandle, boolean newState){
this.bulbToHandle = toHandle;
bulbNewState= newState;
}
public void run(){
this.bulbToHandle.setState(bulbNewState);//Set on or off
}
}
class Bulb ...
public void setState(boolean state){
this.state = state;
System.out.println("Bulb " + name + " is " + (state ? "on" : "off") + " at " + BulbScheduler.formatDate(new java.util.Date()));//if okay too
}
I'm currently reading in MIDI messages in real-time from my midi keyboard using a class that implements Receiver, and outputting the notes played.
The only information i receive when I press a note is the MidiMessage and a timeStamp.
I am trying to paint the notes as actual piano sheet music and currently the user has to set the bpm beforehand.
Therefore if I know the tempo is 120bpm (for example), how can I use the timeStamps to determine the length of the note pressed?
I'm assuming if I can convert the timeStamps into ticks (ppq), then I can use that to work out the timings.
Any help is greatly appreciated. Below is my "send" method in my Receiver class.
The 'firstStamp' and 'secondStamp' variables are just to output the length of a note. I took the timeStamp when a note was released and subtracted the timeStamp when it was pressed.
#Override
public void send(MidiMessage message, long timeStamp) {
String strMessage = null;
if (firstStamp == 0) {
firstStamp = timeStamp;
secondStamp = timeStamp;
}
firstStamp = secondStamp;
secondStamp = timeStamp;
stampDif = (secondStamp - firstStamp);
if (message instanceof ShortMessage) {
strMessage = decodeMessage((ShortMessage) message, timeStamp);
} else if (message instanceof MetaMessage) {
strMessage = decodeMessage((MetaMessage) message);
} else if (message instanceof SysexMessage) {
strMessage = decodeMessage((SysexMessage) message);
} else {
strMessage = "other message" + message.getStatus();
}
r_out.println("Timestamp: " + timeStamp + " " + strMessage);
r_printStream.println("Timestamp: " + timeStamp + " " + strMessage);
}
If the timestamp is in milliseconds then you can convert it to ticks like this:
long ticks = timestamp * bpm / (1000 * 60);
Bit you will get a high start tick since the timestamp is probably since Jan 1 1970. So if you want to have your first "tick" as 0 you need to keep track of if this is your first seen event.
if (tickOffset == -1) { // Using -1 as not initialized
tickOffset = ticks;
}
ticks = ticks - tickOffset;