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.
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 questions on how to use the scheduler properly.
I'm running a scheduler that trigger a job that sends list of emails at 10:00 am on working days.
The scheduler will trigger the job every 1 minute. However, the execution time for sending an email will take around 5 seconds.
Therefore, if I have 20 emails to send out for a day, it will take 20x5sec = 100 sec.
The scheduler will trigger after 1 minute, before the 20 emails being sent out completely.
Therefore, some emails will be left unsent.
Please kindly advise me on how do I send out the email completely before the next trigger time ?
Below is my sample code.
//CalendarReminder.java
// Job 1 & Group 1
JobDetail job = new JobDetail();
job.setName("Job1");
job.setJobClass(SendEmailJob.class);
job.setGroup("group1");
//example of adding an excluded day of the week - This excludes sundays from job
//firing schedule
WeeklyCalendar weeklyOff = new WeeklyCalendar();
weeklyOff.setDayExcluded(Calendar.SUNDAY, true);
// Trigger 1
//configure the scheduler time
SimpleTrigger trigger = new SimpleTrigger();
trigger.setStartTime(new Date(System.currentTimeMillis() + 1000));
trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
trigger.setRepeatInterval(60000); // Trigger every 1 min
trigger.setGroup("group1");
trigger.setName("trigger1");
try{
//schedule the job
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.addCalendar("weeklyOff", weeklyOff, false, true);
scheduler.start();
scheduler.scheduleJob(job, trigger);
}catch(Exception ex){
}
-----------------------------------------------------------------------------
//SendEmailJob.java
try {
//getting database connection to MySQL server
dbCon = DriverManager. getConnection(dbURL, username, password);
//getting PreparedStatment to execute query
stmt = dbCon.prepareStatement(query);
//Resultset returned by query
rs = stmt.executeQuery(query);
while(rs.next()){
Str_Company = rs.getString("erscheduledemail.company");
Str_Dept = rs.getString("erscheduledemail.dept");
Str_EventType = rs.getString("erscheduledemail.eventtype");
Str_OneTimeDate = rs.getString("erscheduledemail.onetimedate");
Str_TimeSend = rs.getString("erscheduledemail.timesend");
Str_EmailFrom = rs.getString("erscheduledemail.emailfrom");
Str_EmailTo = rs.getString("erscheduledemail.emailto");
Str_EmailCCTo = rs.getString("erscheduledemail.emailccto");
Str_EmailSubject = rs.getString("erscheduledemail.emailsubject");
Str_EmailMessage = rs.getString("erscheduledemail.emailmessage");
Str_DeliveryStatus = rs.getString("erscheduledemail.deliverystatus");
Str_ActiveStatus = rs.getString("erscheduledemail.activestatus");
// Retrieve Scheduled Records Date yyyy-mm-dd & Time hh:mm:ss
Int_Year = Integer.parseInt(Str_OneTimeDate.substring(0, 4));
Int_Month = Integer.parseInt(Str_OneTimeDate.substring(5, 7));
Int_Day = Integer.parseInt(Str_OneTimeDate.substring(8,10));
Int_Hour = Integer.parseInt(Str_TimeSend.substring(0, 2));
Int_Min = Integer.parseInt(Str_TimeSend.substring(3, 5));
Int_Sec = Integer.parseInt(Str_TimeSend.substring(6, 8));
// Retrieve Computer System Date & Time
Calendar SysCalen = Calendar.getInstance();
int sys_calYear = SysCalen.get(Calendar.YEAR);
int sys_calMonth = SysCalen.get(Calendar.MONTH) + 1;
int sys_calDay = SysCalen.get(Calendar.DAY_OF_MONTH);
int sys_calHour = SysCalen.get(Calendar.HOUR_OF_DAY);
int sys_calMinute = SysCalen.get(Calendar.MINUTE);
int sys_calSecond = SysCalen.get(Calendar.SECOND);
// If the time match at 10:00 am
if(sys_calYear == Int_Year && sys_calMonth == Int_Month && sys_calDay == Int_Day &&
sys_calHour == Int_Hour && sys_calMinute == Int_Min /*&& sys_calSecond == Int_Sec*/){
System.out.println( " The time now" + String.valueOf(sys_calHour) + ":" +
String.valueOf(sys_calMinute) + ":" + String.valueOf(sys_calSecond));
System.out.println( " company: " +Str_Company);
SendingEmail(Str_EmailFrom,Str_EmailTo,Str_EmailCCTo, Str_EmailSubject, Str_
EmailMessage);
// Update deliverystatus to Yes and ActiveStatus to No
stm = dbCon.createStatement();
sql = "UPDATE erscheduledemail SET deliverystatus = 'Y', activestatus = 'N' "
+
"WHERE company = '"+Str_Company+"' and dept = '"+Str_Dept+"' and onetimedate =
'"+Str_OneTimeDate+"' and eventtype = '"+Str_EventType+"' ";
//Execute INSERT SQL Statement
stm.executeUpdate(sql) ;
}
}
dbCon.close();
} catch (SQLException ex) {
//System.out.println("SQL Exception thrown :" + ex);
System.out.println("SQL Exception thrown :" + ex);
}
Thanks & Regards,
Goshen
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.)
I am making a ping program using Java sockets. One bug in my program is that sometimes it will not connect and will just sit there for ever. So I am trying to add a timeout (after twenty seconds) and the ping will fail. But I have no idea how to.
Here is part of my ping program:
boolean result = false;
long before1 = System.nanoTime();
out.println(new byte[64]);
System.out.println("(1) Sent 64 bytes of data to " + address
+ "...");
try {
if ((in.readLine()) != null) {
int size = in.readLine().toString().getBytes().length;
long after = System.nanoTime();
long s = ((after - before1) / 1000000L) / 1000;
System.out.println("(1) Recieved reply from " + address
+ " (" + size + " bytes), time = " + s
+ " seconds...");
result = true;
} else if ((in.readLine()) == null) {
long after = System.nanoTime();
long s = ((after - before1) / 1000000L) / 1000;
System.out.println("(1) Failed to recieve reply from "
+ address + ", time = " + s + " seconds...");
result = false;
}
} catch (IOException exc) {
long after = System.nanoTime();
long s = ((after - before1) / 1000000L) / 1000;
System.err.println("(1) Failed to recieve reply from "
+ address + ", time = " + s + " seconds...\nReason: "
+ exc);
result = false;
}
But I would like to measure time elapsed any where in my code, instead of:
long time = System.nanoTime();
If one part of my code is stuck doing something it will time out after 20 seconds.
Any suggestions on how to measure if twenty seconds has passed at the start of a try/catch block or anywhere else in my code so it doesn't get stuck during the ping?
As "jsn" and "jahory" said you need to do this with threads. Here's 2 useful links, you can check them ;)
How to implement timeout using threads
Adding a thread timeout to methods in Java
You can use Future and FutureTask:
ExecutorService pingExecutor = ... // executor service to run the ping in other thread
void showPing(final String target) throws InterruptedException {
Future<String> ping = executor.submit(new Callable<String>() {
public String call() {
String pingResult = ... // do your Ping stuff
return pingResult;
}});
System.out.println("Pinging..."); // do other things while searching
try {
System.out.println(future.get(20, TimeUnit.SECONDS)); // use future, waits 20 seconds for the task to complete
} catch (ExecutionException ex) {
} catch (TimeoutException tex) {
// Ping timed out
}
}
You can find some hints here: How do I call some blocking method with a timeout in Java?
Future interface looks like a good solution to your problem. Remember, however, that depending on what your task is doing, you probably would be not able to really cancel it. Additional info:
tutorial (see, in particular, Non-blocking algorithms section)
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;