timer task strange behaviour - android

I m facing issue in fitness app after 1 hr timertask runs slow or sometimes it runs too fast like it increase 2 second simantaneously please someone suggest stable solution ..I am saving user history when ever I get new location any help is appreciated
public void reStartTimerTask(final boolean onCreate) {
if (Validator.isNull(timer)) {
if (preferences.isGps()) {
IntentFilter intentFilter = new IntentFilter(Util.LOCAL_RECEIVER);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
workoutReceiver = new WorkoutReceiver();
registerReceiver(workoutReceiver, intentFilter);
if (!onCreate) {
if (!Util.isGPSEnabled(this)) {
displayGPSAlert();
}
if (!preferences.isTryOut()) {
Request.getRequest().sendRequest(Request.GET_ALL_TRACE_USER, this, this, RequestParameterBuilder.buildMapForUserId(this));
}
}
}
timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
if (preferences.isGps()) {
WorkoutServiceHelper.getWorkoutServiceHelper(MainActivity.this).connect();
}
if (!preferences.isWorkoutPaused()) {
history.duration++;
history.calories = HWUtil.calculateCalorie(history, MainActivity.this);
history.cascadeSave();
}
if (history.duration % 5 == 0 && preferences.isTrace() && !preferences.isRequestSent()) {
//Sync record every five second
UserHistoryModel historyModel = history.loadAll();
if (Validator.isNotNull(historyModel)) {
UserHistory uh = convertUserHistoryModelToUserHistory(historyModel);
/*
don't set history pictures when tracing
*/
uh.setHistoryPictures(null);
uh.setId(uh.getUniqueId());
preferences.setRequestSent(true);
Request.getRequest().sendJsonRequest(Request.ADD_USER_HISTORY, MainActivity.this, MainActivity.this, RequestParameterBuilder.buildJsonObjectFromUserHistory(uh));
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if (getSupportFragmentManager().findFragmentByTag(TabFragment.class.getName()) != null) {
TabFragment tabFragment = (TabFragment) getSupportFragmentManager().findFragmentByTag(TabFragment.class.getName());
if (tabFragment.getCurrentFragment() instanceof UpdateListener) {
((UpdateListener) tabFragment.getCurrentFragment()).update();
}
} else if (getSupportFragmentManager().findFragmentByTag(FullMapFragment.class.getName()) != null) {
FullMapFragment mapFragment = (FullMapFragment) getSupportFragmentManager().findFragmentByTag(FullMapFragment.class.getName());
mapFragment.update();
}
}
});
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
}
whenever user starts any workout/after pause i m calling this method

Related

The Timer does not accelerate when it runs for the first time, but the timer accelerates at the next working moments. How can i fix it?

public void startCountdownTimer() {
currentCountdown = startCountdown;
// stopTimer=false;
if (stopTimer == true) {
return;
}
for (int i = 1; i <= startCountdown + 1; i++) {
task = new TimerTask() {
#Override
public void run() {
countdownHandler.post(doA);
}
};
countdownTimer = new Timer();
countdownTimer.schedule(task, i * 1000);
}
}
final Runnable doA = new Runnable() {
#Override
public void run() {
//reset timer when switching to another question
if (currentCountdown != -1 && btn_next.getText().equals("CHECK") && stopTimer != true) {
if (currentCountdown == 0) {
relative_stop.setVisibility(View.INVISIBLE);
currentCountdown = startCountdown;
btn_next.setText("NEXT");
toast = Toasty.warning(getApplicationContext(), "Time's UP", 1000);
toast.show();
toast = Toasty.info(getApplicationContext(), correctAnswer, 1000);
toast.show();
countdownTimer.cancel();
countdownTimer.purge();
}
tv_timer.setText("" + currentCountdown);
currentCountdown--;
}
}
};
I'm trying to make a timer that counts down for 10 seconds, it works normally when it runs for the first time, and when it runs consecutively, the timer caused by delay suddenly speeds up.

Android: Playing MIDI Notes Using Handler and Scrolling RecyclerView Accordingly

I am playing MIDI notes using this library as follows:
handler.postDelayed(new Runnable() {
ShortMessage message;
#Override
public void run() {
{
MidiEvent event = midiEvents.get(index[0]);
if (index[0] < midiEvents.size() - 1) {
delta = midiEvents.get(index[0] + 1).getDelta();
time[0] = timeFactor * midiEvents.get(index[0] + 1).getDelta();
mTotalMidiTime += time[0];
int noteValue;
int NOTE_STATUS;
if (event instanceof NoteOn) {
noteValue = ((NoteOn) event).getNoteValue();
NOTE_STATUS = NOTE_ON;
if (index[0] != 0) {
if (delta != 0) {
Intent intent = new Intent();
intent.setAction(Constants.SCROLL_RECYCLERVIEW);
localBroadcastManager.sendBroadcast(intent);
}
}
} else {
noteValue = ((NoteOff) event).getNoteValue();
NOTE_STATUS = NOTE_OFF;
}
try {
message = new ShortMessage(NOTE_STATUS, 2, noteValue,
127);
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setAction(Constants.ACTION_SEEK);
localBroadcastManager.sendBroadcast(intent);
if (message != null)
recv.send(message, -1);
index[0]++;
} else {
index[0] = 0;
time[0] = 1;
mTotalMidiTime = mMinimumTime;
delta = 0;
}
handler.postDelayed(this, time[0]);
}
}
}, 0);
With each NoteOn event I am smooth scrolling a RecyclerView and updating a Seekbar using a LocalBroadcastManager
My problem is that playback is fine when UI operations are not performed but playback and UI get completely out of sync as soon as multiple MIDI notes (chords) are played in very quick succession. It would be appreciated if any performance improvements are suggested for the same. I have already tried performing the UI operations in runOnUiThread and also launching a new Handler for UI operations.
My BroadcastReceiver is as follows:
BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String actionType = intent.getAction();
switch (actionType) {
case Constants.SCROLL_RECYCLERVIEW:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
mNotesRecycler.smoothScrollBy(pixels, 0);
}
});
break;
case Constants.ACTION_SEEK:
Handler seekHandler = new Handler();
seekHandler.post(new Runnable() {
#Override
public void run() {
mPinchSeekBar.setSelectedCentreValue(mTotalMidiTime);
mCurrentTime.setText(timeInMinutes((int) mTotalMidiTime));
}
});
break;
}
}
};
Besides the optimizations you can do, I think the problem itself is RecyclerView's smoothScroll is more a method you call sometimes to do a fancy scroll rather than bomb it with requests that cause it to constantly recompute the running animation.
One thing you can try is to write yourself a simple scroll handler that calls mRecyclerView.scrollTo() that does the scroll without animation but I guess it's going to be more reliable.
Try something like this
Handler mHandler = new Handler();
int mPosition, mTargetPosition;
#IntRange(from = 20, to = 100)
final int INTERVAL = 50; // try with 50 ms or a little lower
Runnable mTimerScroll = new Runnable() {
public void run() {
if (mPosition != mTargetPosition) {
if (mPosition < mTargetPosition) {
mPosition += mDelta;
if (mPosition > mTargetPosition) mPosition = mTargetPosition;
}
if (mPosition > mTargetPosition) {
mPosition -= mDelta;
if (mPosition < mTargetPosition) mPosition = mTargetPosition;
}
mRecyclerView.scrollTo(mPosition, 0);
}
// repeat every 50ms
mTimerScroll.post(mRunnable, INTERVAL);
}
}
And then you start it
void startTimer() {
stop(); // prevent double start
mHandler.post(mTimerScroll);
}
void stopTimer() {
mHandler.removeCallbacks(mTimerScroll);
}
void scroll(int target) {
mTargetPosition = target;
}
void scrollBy(int pixels) {
scroll(mPosition + pixels);
}
I don't know the specifics of your app but it might work.
About optimization, you are using a lot of stuff there that can or cannot be necessary depending on the specifics of your library, etc, but if there are no different threads or services involved you could avoid the LocalBroadcast thing and all the handler.post() as everything is already on the UI thread (handler.post just posts a runnable to the thread where the handler was created, that in your case is the UI thread, so it doesn't do anything)

How to resolve ANR while invoking a list

I am developing an app in which a thread will run in main thread and it will call a list of users in every 1 sec,but i am getting the pop up that ANR. please suggest. How To Resolve?
Below is my code
super.onCreate(savedInstanceState);
System.setProperty("java.net.preferIPv4Stack", "true");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
mHandler = new Handler();
Runnable runable = new Runnable() {
#Override
public void run() {
try{
listofUsers = GcmIntentService.getListOfUsers();
if (listofUsers.size() > 0) {
for (int index = 0; index < listofUsers.size(); index++) {
if (index == 0) {
startTime = listofUsers.get(0).getLoggedinDateTime();
} else {
Calendar calender1 = Calendar.getInstance();
calender1.setTime(startTime);
calender1.add(Calendar.SECOND, i);
newTime = calender1.getTime();
listofUsers.get(index).setLoggedinDateTime(newTime);
i = i + 72;
}
///user time is checked with the current system time.
Iterator<UserInformation> userDetailsIter = listofUsers.iterator();
Calendar calender2 = Calendar.getInstance();
while (userDetailsIter.hasNext()) {
UserInformation newUserInfo = userDetailsIter.next();
Date userTime=newUserInfo.getLoggedinDateTime();
Date systemTime=calender2.getTime();
if ( userTime.compareTo(systemTime) < 0 ) {
userDetailsIter.remove();
}
}
}
}
mHandler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//also call the same runnable
mHandler.postDelayed(this, 100);
}
}
};
mHandler.postDelayed(runable, 100);
}
Please help me by guiding me about what I have done wrong
You can't make a while loop or any kind of long running operation on main queue
why don't you make a normal thread inside a repeated timer
like the below code
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
check();
}
}, 0, 100);
and inside check make a thread and do what ever you want
public void check(){
new Thread(new new Runnable() {
#Override
public void run() {
// do what you want here
}
}).start();
}

ScheduledThreadPoolExecutor only "ticking" once

I was using a CountDownTimer for some countdown functionality I have in my Activity. I decided to move away from CountDownTimer and use ScheduledThreadPoolExecutor because CountDownTimers can't cancel themselves in onTick().
For some reason, my Runnable in the following code only executes once. I'm not sure why it isn't executing multiple times. The destroyCountdownTimer() function is not getting hit.
private ScheduledThreadPoolExecutor mCountdownTimer;
private Tick mTick;
class Tick implements Runnable {
#Override
public void run() {
Log.e("tick", String.valueOf(mAccumulatedMilliseconds));
mAccumulatedMilliseconds += 1000;
populateTimeAccumulated();
populateTimeRemaining();
updatePercentages();
if (mTotalMilliseconds <= mAccumulatedMilliseconds) {
destroyCountdownTimer();
}
}
}
private void startCountdown() {
if (mAccumulatedMilliseconds < mTotalMilliseconds) {
mCounterIsRunning = true;
if (mCountdownTimer == null) {
mCountdownTimer = new ScheduledThreadPoolExecutor(1);
}
if (mTick == null) {
mTick = new Tick();
}
mCountdownTimer.scheduleAtFixedRate(mTick, 1000, 1000, TimeUnit.MILLISECONDS);
}
}
private void destroyCountdownTimer() {
if (mCountdownTimer != null) {
mCountdownTimer.shutdownNow();
mCountdownTimer = null;
}
if (mTick != null) {
mTick = null;
}
}
The documentation says:
If any execution of the task encounters an exception, subsequent executions are suppressed.
Add try-catch block to your Tick runnable.

Android listview timer run in every second

I have a issue with using a timer on a listview.
In the list item I showed using sqlite values. There is a textview which showing time difference of last updated time of the data and current time. i have to show it in every one second. so the user can know how long he updated the record.
I tried this in several ways.
First way
I tried to add timer in adapter class. so for every item new timer is created. so application crashed because of many timers run simultaneously.
Second way
I tried using adapter.notifyDataSetChanged() way. Like as this.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (adapterChatThread != null) {
adapter.notifyDataSetChanged();
}
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
I move to another activity when click on list item and user can come back to this Activity.
so in Onresume I used
timerHandler.postDelayed(timerRunnable, 500);
and OnPause
timerHandler.removeCallbacks(timerRunnable);
Issue is data is not showing well. I mean in every second data difference is not one second. some time differnce is 2sec, 5 sec, .. etc.
means timer is not working as I expected.
Third way
I used a asynctask and call it in every second using a timer.
class ThreadTimer extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
if (adapter != null)
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this as in here
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
new ThreadTimer().execute();
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
previous issue triggered. (data not showing well)
Fourth way
Using AsyncTask as this
class ThreadTimer extends AsyncTask<Void, Void, Void> {
void Sleep(int ms) {
try {
Thread.sleep(ms);
} catch (Exception e) {
}
}
#Override
protected Void doInBackground(Void... params) {
while (threadRun) {
Sleep(1000);
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this class in OnResume.
In on pause I set threadRun= false;
issue is same.
please help me.
My requirement is update list item in every second.
Thank you.
edit
here is my adapter class textview update code.
Date lastUpdatedTime;
final ChatThreadDAO ctd = new ChatThreadDAO();
long timeForNextResponse = ctd.getLastRespondedTime(vct.get(position).getThread_id());
try {
if (vct.get(position).getThread_read_status() == 1 && timeForNextResponse > 0) {
final long respTime = timeForNextResponse;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
lastUpdatedTime = formatter.parse(vct.get(position).getLast_updated_time());
final long timeDiff = (new Date()).getTime() - lastUpdatedTime.getTime();
if (timeDiff <= respTime) {
timeForNextResponse = respTime - timeDiff;
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), timeForNextResponse);
holder.tvChatTimer.setVisibility(View.VISIBLE);
holder.tvChatTimer.setText(timeForNextResponse / 1000 + "");
} else {
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), 0);
}
} else {
holder.tvChatTimer.setVisibility(View.INVISIBLE);
}
} catch (ParseException e) {
e.printStackTrace();
}
here vct is
Vector vct;
I assign the values to vector in adapter class constructer.
Here is an example similar to your case.
private class connectionControl extends Thread {
boolean stop_ = false;
public void stop_() {
this.stop_ = true;
}
public void run() {
System.out.println("Thread started:" + getClass().getSimpleName());
while(!this.stop_) {
try {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
int rightNow = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60;
if(rightNow - lastUpdatedTime > 10) {
wirelessIcon.setImageResource(R.drawable.wirelessred);
}
else if(rightNow - lastUpdatedTime > 5) {
wirelessIcon.setImageResource(R.drawable.wirelessyellow);
}
else {
wirelessIcon.setImageResource(R.drawable.wirelessgreen);
}
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Thread stoped:" + getClass().getSimpleName());
}
}
You set your lastUpdatedTime the same way you created rightNow whenever you call notifyDataSetChanged() method of your adapter.

Categories

Resources