Running toast in at certain interval in a service - java

I am trying to show a toast at 2 seconds interval from a service.
This normal code works fine. This one is just a test to show toast.
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
new Thread(new ToastRunner(this)).start();
return START_STICKY;
}
But the below code crashes...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
new Thread(new ToastRunner(this)).start();
return START_STICKY;
}
class ToastRunner implements Runnable{
Context context;
public ToastRunner(Context context){
this.context = context;
}
#Override
public void run() {
try {
while (true) {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
Thread.sleep(2000);
}
}catch (Exception e){
Log.d("tag", e.toString() );
}
}
}
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Try this code,
while (true) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
}
});
Thread.sleep(2000);
}

That mean you cannot access ui element from one another thread. You must use uiThred. Try this code,
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Service Started", Toast.LENGTH_SHORT).show();
Thread.sleep(2000);
}
}
}

try like this...
#Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
// now, the handler will automatically bind to the
// Looper that is attached to the current thread
// You don't need to specify the Looper explicitly
handler = new Handler();
// After the following line the thread will start
// running the message loop and will not normally
// exit the loop unless a problem happens or you
// quit() the looper (see below)
Looper.loop();
}
catch (Throwable t) {
Log.e(TAG, "halted due to an error", t);
}
}

Related

How to make a service to loop constantly?

I have a service which is started by a BroadcastReceiver that activates when the boot is completed. So the service starts and I have the following on my onStartCommand
public int onStartCommand(Intent intent, int flags, int startId) {
mQueue = Volley.newRequestQueue(getApplicationContext());
//FROM NOW ON I WANT IT TO LOOP CONSTANTLY
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, API.getDeviceTypes(), null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
processResponse(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("mytag", "Error de response");
error.printStackTrace();
}
});
mQueue.add(request);
// LOOP TILL HERE
return START_STICKY;
}
I want the service to make that request constantly or at least every 3 minutes or something. How can I achieve this?
As of now the service starts ok but of course it only executes those lines once.
Use Handler for your requirement do not use Thread it will block
Main UI Thread
private Handler handler;
private Runnable runnable;
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
if (runnable != null) {
runnable = null;
}
runnable = new Runnable() {
#Override
public void run() {
// do your stuff here, called every 3 second
mQueue = Volley.newRequestQueue(getApplicationContext());
//FROM NOW ON I WANT IT TO LOOP CONSTANTLY
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, API.getDeviceTypes(), null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
processResponse(response);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("mytag", "Error de response");
error.printStackTrace();
}
});
mQueue.add(request);
h.postDelayed(this, 3000);
}
};
// start it with:
handler.post(runnable);
return START_STICKY;
}
And dont forget to remove handler callback also in onDestroy() or in onstop according to your need
handler.removeCallbacks(runnable);
handler.removeMessages(0);
Read why handler is better from here
difference between Thread and Handler
AlarmManager can be used to perform a task periodically:
Let’s say we want to perform a task after every 3 minutes.
setRepeating() allows to schedules an alarm with exact repeating time.
AlarmManager mgr=(AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
180000+System.currentTimeMillis(),
getPendingIntent(ctxt));
and you can get pending intent
// Specify ur receiver
private PendingIntent getPendingIntent(Context ctxt) {
Intent i=new Intent(ctxt, APIReceiver.class);
return(PendingIntent.getBroadcast(ctxt, 0, i, 0));
}
You can stop alarm manager by calling:
public void stopAlarmManager()
{
if(alarmMgr != null)
alarmMgr.cancel(pendingIntent);
}

How can one thread tell another thread to stop?

I'm making a Service that creats a thread in the Oncreate methed. this thread is a endless loop thAT PLAYS A MP3 FILE, GOES TO SLEEP FOR 30 SECONDS.
i'M TRYING TO FIGURE OUT HOW TO stop this in the onDestroy methed
code
public void onCreate() {
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(this, R.raw.nysound);
mThread=new myThread();
mThread.start();
}
public class myThread extends Thread {
public void run() {
do{
mediaPlayer.start();
try
{
Thread.sleep(1000*20);
} catch(Exception e)
{
ted++;
}
} while(true);
} // end methed
} // end class
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
You could use a boolean flag for that
public class myThread extends Thread {
private volatile boolean running = true;
public void run() {
do{
mediaPlayer.start();
try
{
Thread.sleep(1000*20);
} catch(Exception e)
{
ted++;
}
} while(running);
} // end methed
public void setRunning(boolean newValue) {
this.running = newValue;
}
} //
And then do the following in main thread
#Override
public void onDestroy() {
mThread.setRunning(false);
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
Calling onDestroy() is not the right way to stop Service
public void onDestroy () is called by the system to notify a Service that it is no longer used and is being removed. The service should clean up any resources it holds (threads, registered receivers, etc) at this point. Upon return, there will be no more calls in to this Service object and it is effectively dead. Do not call this method directly.
if you are in service class please call method
stopSelf();
if you are in another class, like your MusicPlayerActivity call below code
Intent i = new Intent(this, ServiceName.class);
stopService(i);
Both of these will stop your service.
You should consider using higer-level object ScheduledExecutorService to handle thread execution :
public void onCreate() { Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(this, R.raw.nysound);
ScheduledExecutorService ses =
Executors.newScheduledThreadPool(1);
scheduledFuture = ses.scheduleWithFixedDelay(new MyThread(), 0, 20, TimeUnit.SECONDS);
}
public class myThread extends Thread {
public void run() {
mediaPlayer.start();
} // end methed
} // end class
#Override
public void onDestroy() {
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
scheduledFuture.cancel(true);
}

Android work in background

I got 3 activities ( A , B ,C ) and a service that I call to check if I got new messages from DB. It's a HTTP request . I need to make the request each 15 sec.
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(15000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here i call
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
How to make it work when i am changing activities ?
Option: Consider changing setup to have three fragments as your original activities, and a MainActivity that controls the repeat polling for messages to DB, as well as controlling the fragments.
#SuppressLint("SimpleDateFormat")
public class AlarmService extends Service {
private PendingIntent pendingIntent;
Handler mHandler;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
}
public void f() {
Toast t = Toast.makeText(this, "Service is still running",
Toast.LENGTH_SHORT);
t.show();
};
}
#Override
#Deprecated
public void onStart(Intent intent, int startId) {
Toast t = Toast.makeText(this, "Service started", Toast.LENGTH_SHORT);
t.show();
// TODO Auto-generated method stub
super.onStart(intent, startId);
mHandler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
f();
mHandler.postDelayed(this, 20000);
}
};
mHandler.postDelayed(r, 20000);
}
}
and in manifest use this
<service android:name="com.example.yourservice"></service>

Setting up a background process with Threading to handle work in Android

Hello I am trying to create a sample app when executed, will bring you back to the home screen , run a back ground process, and display toast points.
I figure that I will need a separate thread in the background process to do whatever work I need. Here is the Code of my Main Activity(BackGroundPrcessingExampleActivity):
enter code here
public class BackGroundProcessExampleActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
Intent myIntent = new Intent(this, MyService.class);
startService(myIntent);
moveTaskToBack(false);
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the Code from "MyService.java":
enter code here
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getBaseContext(), "Service is started!", 1).show();
myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(getBaseContext(), "Hello!",
Toast.LENGTH_SHORT).show();
}
};
Runnable runnable = new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(2);
myHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
return super.onStartCommand(intent, flags, startId);
}
The problem I am having is that the Toast message is not appearing. I can put breakpoints and see that it is stepping through the code but no message appears. I think it might be that the context is not correct? Do I need the UI's Context(BackGroundPRcessExampleActivity)? Any help is appreciated, thanks in advance.
D
Try it -
public int onStartCommand(Intent intent, int flags, int startId) {
Handler mHandler = new Handler();
Toast.makeText(getApplicationContext(), "Service is started!", 1).show();
Runnable runnable = new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Hello!", Toast.LENGTH_LONG).show();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
return super.onStartCommand(intent, flags, startId);
}
With the help of the replies, this is what eventually worked for me. There is notification code added.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
// Create Notifcation
final Notification notification = new Notification(R.drawable.ic_launcher,
"A new notification", System.currentTimeMillis());
// Cancel the notification after its selected
notification.flags |= Notification.FLAG_AUTO_CANCEL;
//
notification.number += 1;
// Specify the called Activity
Intent intent2 = new Intent(this, NotificationReceiver.class);
Toast.makeText(getApplicationContext(), "Service is started!", 1)
.show();
PendingIntent activity = PendingIntent.getActivity(this, 0, intent2, 0);
notification.setLatestEventInfo(this, "This is the title",
"This is the text", activity);
myHandler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
int i = 0;
while (true) {
final int x = i++;
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
myHandler.post(new Runnable() {
#Override
public void run() {
try {
Toast.makeText(getApplicationContext(),
"Hello!" + String.valueOf(x),
3).show();
if(x == 100)
notificationManager.notify(0, notification);
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
};
new Thread(runnable).start();
Thank you everyone for their help.
D

Stopping a Android service in an Activity

I'm having trouble STOPPING the StimulationService , I'm not sure if i'm calling the stopservice method correctly from my activity.
Any help will be much appreciated.
Activity to start and stop Service
public class Stimulation extends Activity implements OnClickListener {
private static final String TAG = "StimulationActivity";
Button buttonStart, buttonStop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.someapp.Activities.R.layout.stimulation);
buttonStart = (Button) findViewById(com.someapp.Activities.R.id.ButtonStart);
buttonStop = (Button) findViewById(com.someapp.Activities.R.id.ButtonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case com.someapp.Activities.R.id.ButtonStart:
Log.d(TAG, "onClick: starting service");
startService(new Intent(this, StimulationService.class));
break;
case com.someapp.Activities.R.id.ButtonStop:
Log.d(TAG, "onClick: stopping service");
stopService(new Intent(this, StimulationService.class));
break;
}
}
}
}
Service
public class StimulationService extends Service {
private static final String TAG = "StimulationService";
private IOIO ioio_;
private DigitalOutput led
private volatile IOIOThread ioio_thread_;
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
ioio_thread_.stop();
}
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
ioio_thread_ = new IOIOThread();
ioio_thread_.start();
}
public void onStop(Intent intent, int stopid) {
Log.d(TAG, "stop()");
ioio_thread_ = null;
}
class IOIOThread extends Thread {
private IOIO ioio_;
private DigitalOutput led;
/** Thread body. */
public void run() {
Thread thisThread = Thread.currentThread();
super.run();
while (ioio_thread_ == thisThread) {
ioio_ = IOIOFactory.create();
try{
Log.d(TAG, "Wait for IOIO Connection");
ioio_.waitForConnect();
Log.d(TAG, "IOIOConnected");
while (true) {
intializePins();
Log.d(TAG, "Pins Intialized");
while(true){
led.write(false);
sleep(2000);
led.write(true);
sleep(2000);
}
}
}
catch (ConnectionLostException e) {
} catch (Exception e) {
Log.e("Hello", "Unexpected exception caught", e);
ioio_.disconnect();
break;
} finally {
try {
ioio_.waitForDisconnect();
} catch (InterruptedException e) {
}
}
}
}
}
First, as #Waqas notes, there is no onStop() method. There is an onDestroy() method, which will be called after stopService() is called.
Second, you are not stopping the background thread ever. Simply setting the ioio_thread_ data member to null does not stop the thread. That thread will keep running forever. Please do not do this. If nothing else, use an AtomicBoolean instead of a hardwired true in your while() loop, and flip that AtomicBoolean to false in onDestroy().
Your activity is OK. The problem is that the service is not killing the IOIOThread.
Thread.stop() is deprecated and will not do what you want anyway.
What you want is to call ioio_.disconnect() from the service's onStop() (through a method on your thread class), and then join() the thread.
See AbstracIOIOActivity as an example. With minor modifications it can be turned into AbstractIOIOService, and will enable you to leave you application-specific logic in a subclass.

Categories