I have a service class in my Android app which uses a timer. The timer is set to run at a delay of 1min (60000ms). I want the user to be able to dynamically change this delay. Normally, in java I could just use timer.setDelay(); but Android does not have this function.
Service class so far:
public class LocalService extends Service
{
Timer timer = new Timer();
int newDelay;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
mainTask();
}
}, 0, 60000);
}
private void mainTask()
{
//do something
}
private void shutdownService()
{
if (timer != null) timer.cancel();
}
public void onDestroy()
{
super.onDestroy();
shutdownService();
}
private void readNewDelay()
{
InputStream in = openFileInput("updateDelay");
if(in != null)
{
InputStreamReader input = new InputStreamReader(in);
BufferedReader buffreader = new BufferedReader(input);
newDelay = Integer.parseInt(buffreader.readLine()) * 60000; //value in file is saved in minutes
}
in.close();
}
}
The delay I want is saved to a text file by an activity. I then want the service to read this file and update its timer delay accordingly.
You'll have to destroy the timer object and create a new one.
Don't forget that timers don't run when the phone sleeps. A better way is to use an Alert instead of a timer.
Related
Hi I am trying to show 100 markers on google maps but when we render markers on the map. Google map scrolling stop and App show ANR.
Below is my code to show Marker on Map.
Also, API calls every 5-sec using service.
Please what we do wrong.
if (getWorkerSummaryListResponse.getErrorCode() == 0) {
workerListList = getWorkerSummaryListResponse.getWorkerListList();
Log.d(TAG, "setData: " + workerListList.toString());
for (user.WorkerSummary workerBasicInfo : workerListList) {
userPosition = workerBasicInfo.getUserPosition();
workerAlarmStatus.get(workerBasicInfo.getUserAlarmStatus());
if (workerBasicInfo.getWorkerActiveStatus() == 1) {
if (!userPosition.toString().equalsIgnoreCase("")) {
if (!mOnlineWorkerList.contains(workerBasicInfo)) {
mOnlineWorkerList.add(workerBasicInfo);
}
userPosition.getGpsData().getLat();
userPosition.getGpsData().getLng();
markerOptions = new MarkerOptions();
markerOptions.icon(icon);
markerOptions.position(new LatLng(userPosition.getGpsData().getLat(), userPosition.getGpsData().getLng()));
markerOptions.title(workerBasicInfo.getWorkerInfo().getEmail());
// mMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(userPosition.getGpsData().getLat(), userPosition.getGpsData().getLng())));
// mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(userPosition.getGpsData().getLat(), userPosition.getGpsData().getLng()), 12.0f));//where 14.0 is the zoom level
marker = mMap.addMarker(markerOptions);
marker.setTag(workerBasicInfo);
}
}
}
Service code:---
public class MyService extends Service {
public static final int notify = 20000; //interval between two services(Here Service run every 5 seconds)
int count = 0; //number of times service is display
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
AuthorizeApp mAuthorizeApp;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
mAuthorizeApp = AppManager.shareInstance(this).getAuthorizeApp();
if (mTimer != null) // Cancel if already existed
mTimer.cancel();
else
mTimer = new Timer(); //recreate new
mTimer.scheduleAtFixedRate(new TimeDisplay(), 0, notify); //Schedule task
}
#Override
public void onDestroy() {
super.onDestroy();
mTimer.cancel(); //For Cancel Timer
Toast.makeText(this, "Service is Destroyed", Toast.LENGTH_SHORT).show();
}
//class TimeDisplay for handling task
class TimeDisplay extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast
mAuthorizeApp.getRealTimeInstrumentInfo(new GetInstrumentListTask(getApplicationContext()));
}
});
}
}
Hi people I am getting problem in getting my latest JSON value after every 10 seconds. I have developed this code and now I am stucked in this. When I run this code it shows the value after second and did not get updated the second time. I have implemented the handler but it is also not working here.
public class MainActivity extends AppCompatActivity {
TextView a,b,c,d,e,f,g,h;
String result = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a=(TextView) findViewById(R.id.a);
b=(TextView) findViewById(R.id.b);
c=(TextView) findViewById(R.id.c);
DownloadTask task = new DownloadTask();
task.execute("https://api.thingspeak.com/channels/12345/feeds.json?results=1");
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
new Handler().postDelayed(new Runnable() {
public void run() {
search(result);
}
}, 10000);
}
public void search(String result){
try {
JSONObject jsonObject = new JSONObject(result);
JSONArray weatherInfo = jsonObject.getJSONArray("feeds");
JSONObject legsobject = weatherInfo.getJSONObject(0);
a.setText(legsobject.getString("field1"));
b.setText(legsobject.getString("field2"));
c.setText(legsobject.getString("field3"));
}catch (JSONException e) {
e.printStackTrace();
}
}
}
}
I want to get my value refreshed after every 10 seconds and it is not doing it.
Can any one guide me that how can I make it possible.
Try this code ..
private final int INTERVAL_MILLI = 60000; // define your time..
Handler mHandler;
#Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(SyncData);
}
Runnable SyncData = new Runnable() {
#Override
public void run() {
// call your code here..
Log.e(TAG, "SyncData1: " + new java.sql.Date(System.currentTimeMillis()).toString());
final String Token = AppSetting.getStringSharedPref(mContext, Constants.USER_KEY_TOKEN, "");
if (!TextUtils.isEmpty(Token) && !CommonUtils.isServiceRunning(mContext)) {
Log.e(TAG, "SyncData2: " + new java.sql.Date(System.currentTimeMillis()).toString());
startService(new Intent(mContext, SyncService.class));
}
callSyncData();
}
};
public void callSyncData()
{
mHandler.postDelayed(SyncData, INTERVAL_MILLI);
}
and callSyncData() method called in activity onCreate method and run method.
To begin with, I don't like the idea of hammering the server with a request every 10s even nothing changes really. If you can move to a solution with notification from the server it will be better.
If you still need to do that you can use three common solutions to fire a repeating task with a period:
1- Use Timer & TimerTask
For this solution you need to declare your timer task to run:
final TimerTask repeatedTask = new TimerTask() {
#Override
public void run() {
//you stuff here
}
};
Then you need to schedule your task using a timer like below:
final Timer timer = new Timer();
timer.scheduleAtFixedRate(repeatedTask,0, 10 * 1000);
==> Don't forget to call timer.cancel(); when your are done (or activity pause, stop, ...)
2- Use ScheduledThreadPoolExecutor
This is basically a replacing for Timer task starting android 5.0. The setup is more easy and straightforward like below:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
//you stuff here
}
}, 0, 10, TimeUnit.SECONDS);
==> don't forget to shutdown your executor when you are done by calling : executor.shutdown();
3- Use Handler
The tip here is to repost the runnable after downloading your json like mentionned in the previous answer.
You can use TimerTask and Timer. If you need to update UI components you should run it on UI thread.
final TimerTask yourRepeatedTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//your code here
}
});
}
};
And the Timer which schedules your task in a given interval. In your case, it is 10s. Make sure to give the interval in milliseconds.
final Timer timer = new Timer();
timer.scheduleAtFixedRate(yourRepeatedTask ,0, 10 * 1000);
At last call timer.cancel() to stop the timer.
#Override
protected void onPause() {
if (timer != null) {
timer.cancel();
}
super.onPause();
}
Every time I`m trying to finish an activity inside of a timer method, the activity comes back alive over and over again.
I running this activity:
public class PlayerNoAdmin extends ActionBarActivity {
Timer myTimer; boolean isAdmin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player_no_admin);
Intent oldIntent = getIntent();
if (oldIntent != null && oldIntent.hasExtra("THE_LIST")){
songs = oldIntent.getParcelableArrayListExtra("THE_LIST");
id = oldIntent.getIntExtra("ID",0);
listId = oldIntent.getIntExtra("LIST_ID",0);
isAdmin = oldIntent.getBooleanExtra("IS_ADMIN",false);
}
//update the list every k seconds
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, k_time2Update);
}
private void TimerMethod() {
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//Here check for update in the list every 30 seconds and send the new location
String url = getRunUrl();
new TaskMusicPlay().execute(url);
}
};
private class TaskMusicPlay extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String jsonResult = null;
try {
String url = params[0];
TestMain client = new TestMain();
jsonResult = client.doGetRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
checkIfNew(aVoid);
}
private void checkIfNew(String result) {
try {
JSONObject object = new JSONObject(result);
String temp = object.getJSONObject("info").getString("isAdmin");
isAdmin = (temp.equals("true"));
if (isAdmin) {
Intent intent = new Intent(getApplication(),YouTubePlayer.class);
intent.putExtra("THE_LIST", songs);
intent.putExtra("ID", id);
intent.putExtra("LIST_ID",listId);
intent.putExtra("IS_ADMIN",isAdmin);
startActivity(intent);
finish();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
At the end, I succeeded to move to the YouTubePlayer activity, but every few seconds the app returns to the code of this activity (and then executes again the startActivity call and goes back to YouTubePlayer) and that's going on and on.
Your Timer is periodically calling the player to start over and over again.
You must make a cancel() call to the Timer if it is no longer needed so you prevent it from holding a reference for your activity and thus preventing from being removed from the backstack and GC.
http://developer.android.com/reference/java/util/Timer.html
And your Timer is not running on the same thread as it's code because the timer thread iis another Thread and the Code in the Timer is running on UI. You can check it out by adding some logs in the Timer's run method outside of the runOnUIThread() and inside of it.
code for calculating start and end time of scan. Calling scanTime as soon as the scan starts and retTime as soon as the results are received, however, getting two retTimes and the difference between scanTime and retTime is not consistent
public void startService() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (location != null) {
retTime = System.currentTimeMillis() / 1000L;
Log.i("end", Long.toString(retTime));
sendResults(wifi.getScanResults(), androidID, Long.toString(retTime), location);
Long result = retTime - scanTime;
} else {
Log.i("Location", "is Missing");
}
}
};
context.registerReceiver(br, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
t = new Thread(new Runnable() {
public void run() {
try {
setSleepTime(dataTimeDifference);
while (!Thread.interrupted()) {
wifi.startScan();
scanTime = System.currentTimeMillis() / 1000L;
Log.i("start", Long.toString(scanTime));
Thread.sleep(sleepingTime);
}
} catch (InterruptedException e) {
}
}
});
t.start();
}
In short, you know the scan is complete when the BroadcastReceiver is triggered.
This may not directly answer your question, but it seems that this might be a better way of implementing the functionality that you want.
Instead of using Thread.sleep() and a while loop in your Runnable, just rely on the BroadcastReceiver in order to determine when to start a new scan.
Also keep in mind that both the user and the OS can initiate scans, and your BroadcastReceiver will be triggered when those scans complete as well.
private final Runnable mStartScan = new Runnable() {
#Override
public void run() {
wifi.startScan();
}
};
public void startService() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)){
if (location != null) {
sendResults(wifi.getScanResults(), androidID, Long.toString(retTime), location);
} else {
Log.i("Location", "is Missing");
}
t = new Thread(mStartScan);
t.start();
}
}
};
context.registerReceiver(br, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
t = new Thread(mStartScan);
t.start();
}
In my app, I have a service implementing timer task through which i am getting user's location after every 10 seconds.
The thing I am stuck with is I would like to stop this service as well as timer after say 1 or 2 minutes.
I am not able to put behind the logic for it.
Please help me out.
public class TimeService extends Service {
// constant
public static final long NOTIFY_INTERVAL = 20 * 1000; // 10 seconds
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
int i=0;
#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();
new LongOperation().execute("");
}
});
}
private String getDateTime() {
// get date time in custom format
SimpleDateFormat sdf = new SimpleDateFormat("[yyyy/MM/dd - HH:mm:ss]");
return sdf.format(new Date());
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
System.out.println("bgnotification Long operation doinbackground called----> ");
return "";
}
#Override
protected void onPostExecute(String result) {
System.out.println("bgnotification Long operation post execute called----> ");
if(i<3){
GPSTracker mGPS = new GPSTracker(getApplicationContext());
onLocationChanged(mGPS);i++;
Toast.makeText(getApplicationContext(), "HEllo Post execute called",
}
#Override
protected void onPreExecute() {
System.out.println("bgnotification Long operation pre execute called----> ");
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
public void onLocationChanged(GPSTracker track) {
// Getting latitude
double latitude = track.getLatitude();
// Getting longitude
double longitude = track.getLongitude();
System.out.println( latitude);
System.out.println( longitude);
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try
{
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
Log.e("Addresses","-->"+addresses);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
#Wishy to stop service and timer task at certain time you need to make an other timer task which going to execute one time and execution time duration will be whatever you specify. In run method u need to write mTimer.purge(); mTimer.cancel() and stopService(newIntent(class.this,yourservice.class));
An easier solution is making timer public static.
public class TimeService extends Service {
//...
private Timer mTimer = null;
//...
}
another Activity:
//...
if(TimeService.mTimer!=null) TimeService.mTimer.cancel();
//...
Override onDestroy() method in service class like thus:
#Override
public void onDestroy() {
super.onDestroy();
if (mTimer != null) {
mTimer.cancel();
}
}
Call stopService() there where you want to stop your service, like thus:
stopService(serviceIntent);
That's all.