i'm basicaly tying to open up a service, that every 10 seconds, will show up a toast to say "10 seconds passed"
this is what i'm trying to do,
and after many research ive found out that to loop a service i'm
going to need to use while (true) - sleep... method...
but the service or my app crashes every time i start the service
(or to be exact every time the timer runs out)
what is my problem ?
my guess is that maybe the contaxt i'm passing to the toast is wrong ?
maybe there is another way to show toast every 10 seconds in loop (inside a serivice) ?
here is my service code >
package com.greenroad.candidate.mywallpaperchanger;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
/**
* Created by pitsponet on 31/08/2015.
*/
public class myService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getApplicationContext(), "service created",
Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//try to run loop for showing up a toast
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//REST OF CODE HERE//
Toast.makeText(getApplicationContext(), "service started",
Toast.LENGTH_LONG).show();
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), "service stoped",
Toast.LENGTH_LONG).show();
}
}
The reason for the crash, as explained by Brad, is because you are trying to perform UI operation from a non-UI Thread.
To achieve what you're trying to do, use the code below in your service. First of all remove your Thread in onStartCommand()
public class MyService extends Service {
private Handler mHandler;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler.postDelayed(ToastTask, 10000); // Starts the loop here
super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
// Stop the loop
mHandler.removeCallbacks(ToastTask);
super.onDestroy();
}
private Runnable ToastTask = new Runnable() {
#Override
public void run() {
Toast.makeText(MyService.this, "10 Seconds have passed", Toast.LENGTH_SHORT).show();
// Schedule this Runnable to run again after 10 sec
mHandler.postDelayed(this, 10000);
}
}
}
The reason that the service is crashing is because you're trying to run UI tasks (Toasts) outside of the main thread. Since you are creating a secondary thread for the infinite while loop, you'll need to post your Toast calls to the main looper as follows:
final Handler mainHandler = new Handler(getApplicationContext().getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Text to display", Toast.LENGTH_LONG).show();
}
});
That being said, I highly discourage using Thread.sleep() in any code that will run on a device, as this could lead to some serious issues. You should be able to accomplish the same thing (and also get rid of the infinite while-loop) using a Timer instead.
To use a Timer, you should be able to do something like the following:
// Schedules a TimerTask to execute every 10 seconds after a 10 second delay.
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your Toast code here.
}
}, 10000, 10000);
Here's a complete example:
public class MyService extends Service {
private Handler mainHandler;
private Timer timer;
public void onStartCommand(final Intent intent, final int flags, final int startId) {
mainHandler = new Handler(getApplicationContext().getMainLooper());
timer = new Timer();
timer.schedule(new MyTimerTask(), 10000, 10000);
}
public void onDestroy() {
timer.cancel();
}
private class MyTimerTask extends TimerTask {
#Override
public void run() {
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Text to display", Toast.LENGTH_LONG).show();
}
});
}
}
}
Related
I want to update user location in every 30 second for which i am using volley request with Service.
The code in bellow:
public class CarLocationUpdateService extends Service {
Context context;
long delay = 1000; // delay for 1 sec.
long period = 10000; // repeat every 10 sec.
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = this;
Handler ha=new Handler();
ha.postDelayed(new Runnable() {
#Override
public void run() {
//call function
CarLocationUpdateVolleyClass carLocationUpdateVolleyClass=new CarLocationUpdateVolleyClass(context);
carLocationUpdateVolleyClass.carLocationRequest();
}
}, delay);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
use JobScheduler with firbaseJobDispatcher
https://developer.android.com/topic/performance/scheduling.html
You can use fused location service to get location updates.I have created a service to get location updates.This code will give you the location in onLocationChanged method.
Check out my answer here here
try this :
mHandler = new Handler();
Runnable r = new Runnable() {
#override
public void run() {
f();
mHandler.postDelayed(this, 30000);
}
};
mHandler.postDelayed(r, 30000);
you have to call the handler.postDelayed() method again inside the runnable because it´s executed only once, that´s a normal behaviour. Seperate the runnable from the handler like this:
Handler ha = new Handler();
private Runnable yourRunnable = new Runnable() {
#Override
public void run() {
CarLocationUpdateVolleyClass carLocationUpdateVolleyClass=new CarLocationUpdateVolleyClass(context);
carLocationUpdateVolleyClass.carLocationRequest();
ha.postDelayed(yourRunnable, 30000);
}
};
ha.post(yourRunnable);
by the way, your question tells us something about 30 seconds, but you just call it every 10 seconds.
Try this it works
public void doWork(){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// This method will be executed once the timer is over
// insert your data to db here
// close this activity
doWork();
Toast.makeText(MainActivity.this, "LOL", Toast.LENGTH_SHORT).show();
}
}, TIME_OUT);
}
And then simple call this method in onStartCommand()
doWork();
final Handler ha=new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// ...
ha.postDelayed(this,30000);
}
};
ha.post(runnable);
I have to create an app for sending programmed messages, if I create a single service for a single message is all ok, but if I create messages how do I handle the deletion of a specific service? also after the stop of the first service if i try to create other service crash all... i use a timer for my service
public class service extends Service
{
private static Timer timer = new Timer();
int i=1;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags,int startId){
Toast.makeText(getApplicationContext(), "service start", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(new mainTask(), 0, 20*1000);
return service.START_NOT_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
Toast.makeText(getApplicationContext(), "distrutta", Toast.LENGTH_SHORT).show();
Log.i("PROVA SERVICE", "Distruzione Service");
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
} private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (i==1)
{
Toast.makeText(getApplicationContext(), "test1", Toast.LENGTH_SHORT).show();
i++;}
else
{
i=0;
Toast.makeText(getApplicationContext(), "fine", Toast.LENGTH_SHORT).show();
stopSelf();
timer.cancel();
}
}
};
service call:
Intent i=(new Intent(this,service.class));
startService(i);
i'm new in android.
i made an app with service and thread to show a Toast every 5 seconds:
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
Handler mHandler = new Handler();
#Override
public void onCreate() {
super.onCreate();
final Runnable RunnableUpdateResults = new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Hello", Toast.LENGTH_SHORT).show();
}
};
new Thread() {
public void run() {
try {
mHandler.postDelayed(RunnableUpdateResults);
sleep(5000);
} catch (InterruptedException e) {e.printStackTrace();}
}
}.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
public void onStart(final Context context,Intent intent, int startId)
{
}
}
but my Toast shown only once. with no crash.
i used Handler's postDelayed function for this purpose. It will run your code with specified delay on the main UI thread, so you will be able to update UI controls but it dose not work too.
any solution to do a task repetitively ?
call Thread.sleep inside while loop as:
boolean isThreadRunning=true;
new Thread() {
public void run() {
try {
while(isThreadRunning){
mHandler.postDelayed(RunnableUpdateResults);
sleep(5000);
}
} catch (InterruptedException e) {e.printStackTrace();}
}
}.start();
To stop Thread make isThreadRunning=false;
You can achieve same using handler.postDelayed
mHandler.postDelayed(RunnableUpdateResults,5000);
and in RunnableUpdateResults call mHandler.postDelayed :
final Runnable RunnableUpdateResults = new Runnable() {
public void run() {
mHandler.postDelayed(RunnableUpdateResults,5000);
Toast.makeText(getBaseContext(),
"Hello", Toast.LENGTH_SHORT).show();
}
};
To stop Handler call removeCallbacks method:
mHandler.removeCallbacks(RunnableUpdateResults);
Use a Timer with a TimerTask
new Timer().schedule(new TimerTask() {
#Override
public void run() {
mHandler.post(RunnableUpdateResults);
}
}, 0, 5000);
I wish to create an app, which would change the wallpaper of the Android device at fixed intervals, say every hour or so. Currently in my code, I start a service and am using a Timer object. The Timer object would be invoked at regular intervals and change the wallpaper.
This is the code I am using currently. The wallpaper gets changed only once and not after that. Please let me know what should I do?
public class Wallpaper extends Service {
Timer mytimer;
int interval=60000;
Drawable drawable;
WallpaperManager wpm;
int prev=1;
#Override
public void onCreate() {
super.onCreate();
mytimer=new Timer();
wpm=WallpaperManager.getInstance(Wallpaper.this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mytimer.schedule(new TimerTask() {
#Override
public void run() {
if(prev==1){
drawable = getResources().getDrawable(R.drawable.two);
prev=2;
}
else if(prev==2){
drawable = getResources().getDrawable(R.drawable.three);
prev=3;
}
else{
drawable = getResources().getDrawable(R.drawable.one);
prev=1;
}
Bitmap wallpaper=((BitmapDrawable)drawable).getBitmap();
try {
wpm.setBitmap(wallpaper);
} catch (IOException e) {
e.printStackTrace();
}
}
}, interval);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Also, do I need to use an AlarmManager or Handler to achieve this ? I am quite new to Android and a bit confused.
It looks like you're using the timer wrong. If you want to have it recur, you need to specify an initial delay as the second argument, and an interval as the third. Timer.schedule(timertask, initial delay, interval between recurrences);
Note: I'm talking about your call to myTimer.schedule(object, interval);
Try instead of Timer class ScheduledFuture
This helped for me to resolve all problems with timer tasks
Good luck!
private ScheduledFuture mytimer;
//...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
mytimer = timer.scheduleWithFixedDelay(new TimerTask() {
#Override
public void run() {
//...
}
}, 0, interval, TimeUnit.MILLISECONDS);
return super.onStartCommand(intent, flags, startId);
}
//...
#Override
public void onDestroy() {
super.onDestroy();
if (mytimer != null) {
mytimer.cancel(true);
}
//...
}
I need to write thread in service . But I'm not sure how to do this exactly. There must be more than one thread.
Can you help me please.
You start a thread in a service the same way you start a thread in anything. Either use Java threads, timers, or async task.
Java threads are usually started like so:
private Thread yourThread;
private NewRunnable yourRunnable;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
... code...
yourThread = new Thread(yourRunnable);
... code...
}
private final class NewRunnable extends Runnable
{
#Override
public void run()
{
... Code here will be run in new thread....
}
}
This way works great.
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class Servicio extends Service {
#Override
public void onCreate() {
super.onCreate();
initialize();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public void initialize(){
Thread th = new Thread(new Runnable() {
#Override
public void run() {
//Your code ......
}
});
th.start();
}
}
Just get The context in the Service and Use AsyncTask to create another Thread... Or you can also do
new Thrad(){
public void Run(){
//your implementation..
}
}