/**
* intervals of loop
*/
private final long HEART_BEAT_DELAY = 1000L;
private long lastTime = 0;
/**
* whether user is chatting with other(true:isChatting; false: not chatting)
*/
private boolean mIsChatting = false;
/**
* mainThread
*/
private Thread mThread = new Thread() {
#Override
public void run() {
mThread.setPriority(Thread.MAX_PRIORITY);
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
//if user is chatting and activity is not finishing, keep cycling
while (mIsChatting && !VideoChatViewActivity.this.isFinishing()) {
try {
sleep(HEART_BEAT_DELAY);
//get current time
long thisTime = System.currentTimeMillis();
//get interval between current time and last request time
long duration = thisTime - lastTime;
//every 60 seconds do network request
if (mIsChatting && duration >= 60 * 1000) {
//set last heartbeat time to current time
lastTime = thisTime;
//network request
mModel.sendHeartBeat(mUserId, mCallId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
/**
* start heartbeat thread
*/
public void startHearBeat() {
if (!mIsChatting) {
mIsChatting = true;
lastTime = System.currentTimeMillis();
mThread.start();
} else {
LogUtil.e("ralph", "start second time, ignore it");
}
}
/**
* stop heartbeat thread
*/
public void endHeartBeat() {
mIsChatting = false;
}
I've got this code and heartbeat should request network for every 60s, but sometimes it will wait to 90s to the next requet.
To fix that i've set processPriority and threadPriority,but they didn't work anyway.
How can i fix that make request on time?
If you are setting threadPriority to the highest, it means that you want this thread to run before anything else.
Try using mThread.join() in startHearBeat() method.
Related
So I found this background service code that keeps on popping up a toasts every 10 seconds. What I want to ask is translate this code on popping up in minutes interval instead of 10 seconds of interval and instead of a toast popping up I want to it to popup an activity when the interval finishes.
public class TimeService extends Service {
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast
Toast.makeText(getApplicationContext(), getDateTime(),
Toast.LENGTH_SHORT).show();
}
});
}
private String getDateTime() {
// get date time in custom format
SimpleDateFormat sdf = new SimpleDateFormat("[yyyy/MM/dd - HH:mm:ss]");
return sdf.format(new Date());
}
}
...
}
public static final long NOTIFY_INTERVAL = 10 * 1000 * 60;
10*1000 is 10 seconds.Time is always counted as milliseconds. so
change 10 * 1000 to 10 * 1000 * 60
public static final long NOTIFY_INTERVAL = 10 * 1000 * 60;
I would like to implement this function:
When the user click on button start the task and after 5 minute send one file to dropbox, but if the user click another time on the button, the precedent task abort and new task (5 min) start.
I wrote code to upload files to Dropbox, but never written code using task with such a long time (5 minute).
How can do that?
-- EDIT --
thanks #xdevs23, I have implemented the final code
public void onSendOrder() {
try {
mHandler.removeCallbacks(postRunnable); // stop current wait
} catch(Exception ex) {
// Just if the above fails (might be first time)
ex.printStackTrace();
}
int minutes = 5;
mHandler.postDelayed(postRunnable, minutes * 20 * 1000 /* 5 minutes in milliseconds */);
...
...
...
private Runnable postRunnable = new Runnable() {
#Override
public void run() {
Thread myThread = new Thread(myRunnable);
myThread.start();
}
};
private Runnable myRunnable = new Runnable() {
#Override
public void run() {
// your code
int cloud = GetPreferenceCloud();
if(cloud > 0){
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
final File bckDatabase = BackupDatabase();
if (networkInfo != null && networkInfo.isConnected() && bckDatabase != null) {
runOnUiThread(new Runnable() {
public void run() {
// call your asynctask here
new UploadOnCloud(MainActivity.this,
PreferenceConstants.DB_DATABASE_STORE_CLOUD,
PreferenceConstants.FILE_DIR_CLOUD,
bckDatabase,
mUListener,
cloud).execute();
}
});
} else {
Toast.makeText(getContext(),getContext().getResources().getString(R.string.send_msg13), Toast.LENGTH_SHORT).show();
}
}
}
};
* EDIT. V2 *
For implement the Countdown on statusbar I've implemented this:
Modify the onSend function:
public void onSendOrder() {
try {
mHandler.removeCallbacks(postRunnable); // stop current wait
} catch(Exception ex) {
// Just if the above fails (might be first time)
ex.printStackTrace();
}
minute = 3600;
//mHandler.postDelayed(postRunnable, minutes * 20 * 1000 /* 5 minutes in milliseconds */);
mHandler.postDelayed(postRunnable, 1000 /* 1 seconds */);
....
....
in the file menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/break_timer"
android:title="00:00"
app:showAsAction="always"
app:actionViewClass="android.widget.TextView" />
<item
android:id="#+id/action_refresh"
android:title="#string/action_refresh"
app:showAsAction="ifRoom"
android:icon="#drawable/ic_action_autorenew"/>
</menu>
modify the onCreateOptionsMenu
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem timerItem = menu.findItem(R.id.break_timer);
timerText = (TextView) MenuItemCompat.getActionView(timerItem);
timerText.setPadding(10, 0, 10, 0); //Or something like that...
return super.onCreateOptionsMenu(menu);
}
private int minute;
private Runnable postRunnable = new Runnable() {
#Override
public void run() {
if(minute >= 0){
minute--;
mHandler.postDelayed(postRunnable, 1000 /* 1 seconds */);
timerText.setText(secondsToString(minute));
}else {
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}
};
Instead of using an AsyncTask, you could use Threads and Runnables.
Create a Runnable where your code, which you want to run in the background, is located:
Runnable myRunnable = new Runnable() {
#Override
public void run() {
// your code
}
}
Create your Thread:
private Thread myThread;
Make sure that you have a handler created on the main thread.
For best results, add it to your onCreate() method:
private Handler mHandler;
#Override
public void onCreate() {
// ...
mHandler = new Handler();
// ...
}
You need to import android.os.Handler.
Declare the runnable where your upload code is:
private Runnable postRunnable = new Runnable() {
#Override
public void run() {
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}
Now do following when the user clicks on the button:
try {
mHandler.removeCallbacks(postRunnable); // stop current wait
} catch(Exception ex) {
// Just if the above fails (might be first time)
}
int minutes = 5;
mHandler.postDelayed(postRunnable, minutes * 60 * 1000 /* 5 minutes in milliseconds */);
And that's it.
Explanation:
When the user clicks on the button, it will wait (without blocking the UI) for 5 seconds, and then it will run the code inside postRunnable, which starts a new thread in the background, which will run the code inside your myRunnable.
Edit for updating notification
private Handler mHandler;
private int minutes = 5;
private Runnable updateRunnable = new Runnable() {
#Override
public void run() {
if(minutes > 0) {
String notifContent = "" + minutes + " remaining.";
// Create your notification (there are several guides which show you how to do this), use notifContent as title or text or whatsoever
minutes--;
mHandler.postDelayed(updateRunnable, 60 * 1000);
} else {
// Remove your notification
}
}
};
To start the countdown:
mHandler.post(updateRunnable);
My intention is to create an timer which starts from 00:00:00 and hangs together with a recording function. This recording is done in a service so, the timer is also in the same service. If the app moves to the background, the recording and thus the timer keep on going and the app picks the time up at the onResume with a myService.getTime().
But I experience two strange things. The first is that my timer sometimes goed faster than a second, sometimes slower, sometimes jumps from for example 00:00:04 to 00:00:06 etc. There is no consitency in it. I use the code below, but there might be a better option to solve this? The second is that it is causing a lag on my button, although I am starting it in a service?
SERVICE
//////////TIMER FUNCTION START//////////
private void startTimerClick() {
if (stopped) {
startTime = System.currentTimeMillis() - elapsedTime;
} else {
startTime = System.currentTimeMillis();
}
mHandler.removeCallbacks(startTimer);
mHandler.postDelayed(startTimer, 0);
}
private void pauseTimerClick() {
mHandler.removeCallbacks(startTimer);
stopped = true;
}
private void stopTimerClick() {
mHandler.removeCallbacks(startTimer);
stopped = false;
}
private void startTimer() {
startTimer = new Runnable() {
public void run() {
elapsedTime = System.currentTimeMillis() - startTime;
updateTimer(elapsedTime);
mHandler.postDelayed(this, REFRESH_RATE);
}
};
}
private void updateTimer(float time) {
secs = (long) (time / 1000);
mins = (long) ((time / 1000) / 60);
hrs = (long) (((time / 1000) / 60) / 60);
/*
* Convert the seconds to String and format to ensure it has a leading
* zero when required
*/
secs = secs % 60;
seconds = String.valueOf(secs);
if (secs == 0) {
seconds = "00";
}
if (secs < 10 && secs > 0) {
seconds = "0" + seconds;
}
/* Convert the minutes to String and format the String */
mins = mins % 60;
minutes = String.valueOf(mins);
if (mins == 0) {
minutes = "00";
}
if (mins < 10 && mins > 0) {
minutes = "0" + minutes;
}
/* Convert the hours to String and format the String */
hours = String.valueOf(hrs);
if (hrs == 0) {
hours = "00";
}
if (hrs < 10 && hrs > 0) {
hours = "0" + hours;
}
}
//////////TIMER FUNCTION END////////////
public String getHours(){
return hours;
}
public String getMinutes(){
return minutes;
}
public String getSeconds(){
return seconds;
}
}
ACTIVITY(/FRAGMENT)
private void timerStart() {
handler = new Handler();
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
handler.post(new Runnable() {
#Override
public void run() {
timer.setText(myService.getHours()+":"+myService.getMinutes()+":"+myService.getSeconds());
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
}
You are using Threads both in your Service and in your Activity/Fragment code.
Using threads for time sensitive tasks in Android is a problem because Android is able to significantly delay threads.
I have been using a ScheduledThreadPoolExecutor for a similar task and it worked great.
You are then using it like this:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); // where 1 is the number of needed concurrent threads. 1 should last for your needs.
executor.scheduleWithFixedDelay(new TimerTask() {
// your recurringly executed code here
}, 0, 1, TimeUnit.SECONDS);
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
public class MainActivity extends Activity {
private Button Start, Reset, Stop;
private EditText stop_watch, lblDate, lblTime;
public MainActivity() {
init();
}
private final UpdateClockThread ucThread = new UpdateClockThread();
private final StopwatchThread swThread = new StopwatchThread();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Start = (Button)findViewById(R.id.button1);
Stop = (Button)findViewById(R.id.button3);
Reset = (Button)findViewById(R.id.button2);
stop_watch = (EditText)findViewById(R.id.editText3);
lblTime = (EditText)findViewById(R.id.editText2);
lblDate = (EditText)findViewById(R.id.editText1);
Start.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
startactionPerformed();
}
});
Stop.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
stopactionPerformed();
}
});
Reset.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
resetactionPerformed();
}
});
}
public void init() {
swThread.setDaemon(true);
ucThread.setDaemon(true);
swThread.start();
ucThread.start();
}
/** Listens to the Start/Stop/Resume button. */
void startactionPerformed() {
swThread.go();
//init();
}
void stopactionPerformed() {
swThread.noGo();
}
void resetactionPerformed() {
swThread.reset();
}
/** A thread that updates the current date & time. */
private class UpdateClockThread extends Thread {
/** The actual work of the thread. */
public void run() {
while (true) {
lblTime.setText("ampm");
Calendar now = Calendar.getInstance();
String month = Integer.toString(now.get(Calendar.MONTH)+1);
String date = Integer.toString(now.get(Calendar.DAY_OF_MONTH));
String year = Integer.toString(now.get(Calendar.YEAR));
String hour = Integer.toString(now.get(Calendar.HOUR));
if (hour.equals("0")) hour = "12";
String minute = Integer.toString(now.get(Calendar.MINUTE));
if (minute.length() == 1) minute = "0" + minute;
String second = Integer.toString(now.get(Calendar.SECOND));
if (second.length() == 1) second = "0" + second;
String ampm = now.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM";
lblDate.setText(month + "/" + date + "/" + year);
lblTime.setText(hour + ":" + minute + ":" + second + " " + ampm);
try {
sleep(500);
} catch (InterruptedException e) {}
}
}
}
/** A thread that keeps track of the stop watch & updates
* the display accordingly.
*/
class StopwatchThread extends Thread {
/** Whether or not stop watch is running. */
private boolean going = false;
/** Stores elapsed milliseconds of previous runs. */
private long prevElapsed = 0;
/** Stores beginning time of this run. */
private Date startDate = new Date();
/** Returns elapsed time in milliseconds.
*#return The elapsed time
*/
private long elapsedTime() {
return prevElapsed + (going ? new Date().getTime() - startDate.getTime() : 0);
}
/** Changes the number of elapsed milliseconds into a string.
*#param time Number of elapsed milliseconds
*#return The elapsed time as a string.
*/
private String msToString(long time) {
String ms, sec, min;
if (time % 10 >= 5) //round to nearest hundredth
time += 5;
ms = Long.toString(time % 1000);
while (ms.length() < 3)
ms = "0" + ms;
ms = ms.substring(0, ms.length() - 1);
time /= 1000;
sec = Long.toString(time % 60);
if (sec.length() == 1) sec = "0" + sec;
time /= 60;
min = Long.toString(time);
return min + ":" + sec + "." + ms;
}
/** Called when the stop watch is to go.
*/
public void go() {
startDate = new Date();
going = true;
}
/** Called when the stop watch is to stop.
*/
public void noGo() {
prevElapsed = elapsedTime();
going = false;
}
/** Resets the stop watch.
*/
public void reset() {
going = false;
prevElapsed = 0;
}
/** Adds a lap to the list.
*/
/** Main code of the thread.
*/
public void run() {
while (true) {
stop_watch.setText(msToString(elapsedTime()));
yield();
}
}
}
}
What is my app getting force close? There is some error with the thread. But i'm not able to figure it out?
Try make all interaction with UI from threads in runOnUiThread method of Activity http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
EDIT
private class UpdateClockThread extends Thread {
public void run() {
/* Do somthing expensive */
......
/* Update UI */
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
/* Do UI update */;
lblTime.setText("ampm");
......
}
});
}
}
You should run adb logcat on your developer machine. Usually if you get a force close a traceback is displayed in the log.
Your class StopwatchThread contains the line:
stop_watch.setText(msToString(elapsedTime()));
This will not work, and neither will the UI updates within UpdateClockThread. This is because you cannot modify the UI from a background thread. Your background thread should either:
send a message to a Handler that has been created on the UI thread, so that the Handler then makes the update to the UI, or
you can pass a runnable into runOnUiThread that performs the UI update.
In my app i manage to determine is there connection or not, but i want that application itself try to reconnect 5 times, and every time to increase the interval between to reconnects m i did some code, but its not working, he give me response immediate.
Here is my reconnect class:
public class ReestablishConnection {
Application APP = new Application();
boolean status;
int reconnectInterval = 1000;
int i;
public boolean reconnect(String URL){
Thread timer = new Thread(){
public void run(){
for(i=1;i<6;i++){
if(APP.testConnection(APP.defaultUrl()) == 0){
status = false;
}else if(APP.testConnection(APP.defaultUrl()) == 1){
status = true;
}
try {
sleep(reconnectInterval * i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
return status;
}
}
You create a new thread, which sleeps for a while, but the method which spawned it (reconnect) will return immediately. You should be using a Handler with postDelayed().
Take a look at the answer here:
How to run a Runnable thread in Android?
Sleep is used too often. The correct design is to implement a listener for when a connection is available and respond to listener callback in your UI.