How to make a service to loop constantly? - java

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);
}

Related

Wait until socket as service gets available

I have read about Thread sleep, Handler, Runnable, AsyncTask and TimerTask, tried Thread sleep but could not figure out how can I accomplish the task.
I have implemented socket.io.client-java as service and using Volley as well as multiple activities & fragments. I need as follow:
Check if socket is connected before making Volley request.
If socket is connected then process Volley request otherwise re-check socket connectivity (a maximum of 5 times with 1 second interval).
In case of failure in 5 attempts, show a Toast message and continue the Volley request.
I 'm using a common class to perform Volley requests and others.
Socket Service
public class SocketClient extends Service {
private Socket mSocket = null;
private static SocketClient iSocket;
public SocketClient() {
super();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onCreate(){
super.onCreate();
iSocket = this;
startSocket();
}
public static synchronized SocketClient getInstance(){return iSocket;}
private void startSocket(){
try {
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
//...
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
//...
}
}).on(...{...});
mSocket.connect();
} catch (URISyntaxException e){
e.printStackTrace();
}
}
public boolean isConnected(){ return (mSocket != null && mSocket.connected()); }
#Override
public void onDestroy(){
super.onDestroy();
mSocket.disconnect().close();
mSocket = null;
}
}
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
Helpers.startServices(getApplicationContext(), 1);
}
#Override
protected void onResume() {
Helpers.getNotifed(); //A Volley Request
}
Helpers Class
public static void makeReq(Map<String, Object> params, String api, final Context context, final VolleyListener listener)
{
manager = new SessionManager(context);
final String url = baseURL + api;
int i = 0;
boolean ss = SocketClient.getInstance().isConnected();
Log.i(TAG, "Socket status" + ss);
while(i < 5 && !ss) {
try {
Log.i(TAG, "Socket status" + ss);
Log.i(TAG, "sleeping " + i);
Thread.sleep(1000);
ss = SocketClient.getInstance().isConnected();
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!ss)
Toast.makeText(context, "Operation interrupt!", Toast.LENGTH_LONG).show();
//Volley JSON Object Request
}
public static void startServices(Context context, int st) {
switch (st) {
case 1: //Socket
if (!isServiceRunning(context, SocketClient.class))
context.startService(new Intent(context, SocketClient.class));
break;
}
}
Issues:
Getting NullPointerException at boolean ss = SocketClient.getInstance().isConnected(); as class might not initialized yet.
ANR (Application Not Responding) because the main Thread is halted in while loop.
P.S.: I'm just a beginner in Android/Java so reply with clear code would be appreciable.

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>

Running toast in at certain interval in a service

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);
}
}

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