myHandler.obtainMessage() is not allowed in Service class in android - android

I am trying to create a service class with a inner class which is a Handler class , unfortunately I am not able to access handler.obtainMessage() in this class .. Can any one give suggestions on this ?
Source code for the Service class:
public class MyService extends Service {
private MyHandler myHandler;
private final class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
try {
Thread.sleep(5000);
// use the unique startId so you don't stop the
// service while processing other requests
stopSelfResult(msg.arg1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void close() {
}
#Override
public void flush() {
}
#Override
public void publish(LogRecord record) {
}
}
#Override
public void onCreate() {
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
// Create a new HandlerThread with a specified priority
HandlerThread thread = new HandlerThread("MyHandlerThread",Thread.NORM_PRIORITY);
// Start the handler thread so that our Handler queue will start
// processing messages
thread.start();
// Run the handler using the new HandlerThread
myHandler = new MyHandler(thread.getLooper());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message msg = myHandler.obtainMessage();
msg.arg1 = startId;
myHandler.sendMessage(msg);
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
}

You've got the wrong Handler class imported. It should be android.os.Handler, not java.util.logging.Handler.

Related

Run Android Service every 30 seconds

I am creating a Notification using Android Service independent from UI. This works perfectly fine. Below is the code.
public class SendNotificationService extends Service {
Context context;
String test_heading;
String test_body;
final class notifThread implements Runnable {
int service_id;
notifThread(int service_id) {
this.service_id = service_id;
}
#Override
public void run() {
String requested_method = "LoadBU";
String bu_status = "1";
CheckNewEntry checkNewEntry = new CheckNewEntry(SendNotificationService.this);
checkNewEntry.execute(requested_method, bu_status);
stopSelf(this.service_id);
}
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(new notifThread(startId));
thread.start();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Notifications Stopped...", Toast.LENGTH_LONG).show();
}
}
This service also starts automatically on system boot. CheckNewEntry is my AsyncTask that checks the database and sends notification if there is any change. I have not added CheckNewEntry as it is beyond the scope of this question.
Now what I want to do is, run CheckNewEntry every 30 seconds or 1 minute.
Can anyone help?
After going through different Stackoverflow questions/answers, I managed to come up with my own solution.
Below is the code that I have created and is working now.
public class SendNotificationService extends Service {
public Context context = this;
public Handler handler = null;
public static Runnable runnable = null;
#Override
public void onCreate() {
handler = new Handler();
runnable = new Runnable() {
public void run() {
String requested_method = "LoadBU";
String bu_status = "1";
CheckNewEntry checkNewEntry = new CheckNewEntry(SendNotificationService.this);
checkNewEntry.execute(requested_method, bu_status);
handler.postDelayed(runnable, 10000);
}
};
handler.postDelayed(runnable, 15000);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
handler.removeCallbacks(runnable);
Toast.makeText(this, "Notifications Stopped...", Toast.LENGTH_LONG).show();
}
}
If anyone of you can provide a better solution, please do post.
you can use handler like this.
public class SendNotificationService extends Service {
Context context;
String test_heading;
String test_body;
public static Runnable runn;
public static Handler hand =new Handler();
final class notifThread implements Runnable {
int service_id;
notifThread(int service_id) {
this.service_id = service_id;
}
#Override
public void run() {
String requested_method = "LoadBU";
String bu_status = "1";
CheckNewEntry checkNewEntry = new CheckNewEntry(SendNotificationService.this);
runn = new Runnable() {
#Override
public void run() {
checkNewEntry.execute(requested_method, bu_status);
hand.postDelayed(runn, 30000);
}
};
runn.run();
stopSelf(this.service_id);
}
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(new notifThread(startId));
thread.start();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Notifications Stopped...", Toast.LENGTH_LONG).show();
}
}

Create different service with the same class (android)

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

continue service working when the application closes

I have a simple Service
public class UpdateService extends Service {
private int seconds;
final static String MY_ACTION = "MY_ACTION";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
timer.start();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
final CountDownTimer timer = new CountDownTimer(86400000, 1000) {
public void onTick(long millisUntilFinished) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
Intent intent = new Intent();
intent.setAction(MY_ACTION);
sendBroadcast(intent);
}
public void onFinish() { }
};
}
When I close an application service stops working. But showing that the service is running.
What am I doing wrong?
Update
I changed CountDownTimer to Thread, but the problem remained
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
OnStart()
if(!t1.isAlive())
t1.start();
Because CountDown Timer is working only foreground means app is running and not minimized or closed. You have to place a Thread in Service that executing at particular time of you want.
try this :
public class LocalService extends Service
{
private static Timer timer = new Timer();
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
ctx = this;
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
System.out.println("test");
}
};
}

android - how can I stop the thread inside the service?

I have a checked button in my MainActivity. If that button is checked it should start the service but if a user unchecked the button I want to stop the service.
So in uncheck condition I have written this stopService(intentname); but the problem is the service is not stopping. Here is my code snippet:
Service Class
public class SimpleService extends Service
{
String selectedAudioPath = "";
private MyThread myythread;
public Intent intent;
public boolean isRunning = false;
long interval=30000;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
myythread = new MyThread(interval);
}
#Override
public synchronized void onDestroy()
{
super.onDestroy();
if(!isRunning)
{
myythread.interrupt();
myythread.stop();
isRunning = false;
}
}
#Override
public synchronized void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
if(!isRunning)
{
//this.intent = intent;
//System.out.println("the intent is" + intent);
myythread.start();
isRunning = true;
}
}
class MyThread extends Thread
{
long interval;
public MyThread(long interval)
{
this.interval=interval;
}
#Override
public void run()
{
while(isRunning)
{
System.out.println("Service running");
try
{
String myString = intent.getStringExtra("name");
if(myString == null)
Log.d("Service","null");
else
{
Log.d("Service","not null");
if(myString.equalsIgnoreCase("image"))
{
uploadImages();
Thread.sleep(interval);
}
else if(myString.equalsIgnoreCase("audio"))
{
uploadAudio();
Thread.sleep(interval);
}
}
}
catch (InterruptedException e)
{
isRunning = false;
e.printStackTrace();
}
}
}
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
Source: Stopping a thread inside a service
Don't use Threads. Use AsyncTask instead.
public class MyService extends Service {
private AsyncTask<Void,Void,Void> myTask;
#Override
public void onDestroy(){
super.onDestroy();
myTask.cancel(true);
}
#Override
public void onStart(Intent intent, int startid) {
myTask = new AsyncTask<Void,Void,Void>(){
#Override
public void doInBackground(Void aVoid[]){
doYourWorkHere();
}
}
myTask.execute();
}
}

IntentService won't show Toast

This IntentService I created will show Toasts in onStartCommand() and in onDestroy(), but not in onHandleIntent(). Am I missing something about the limitations of an IntentService?
public class MyService extends IntentService {
private static final String TAG = "MyService";
public MyService(){
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
cycle();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); //This happens!
return super.onStartCommand(intent,flags,startId);
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
Toast.makeText(this, "service stopping", Toast.LENGTH_SHORT).show(); //This happens!
super.onDestroy();
}
private void cycle(){
Toast.makeText(this, "cycle done", Toast.LENGTH_SHORT).show(); //This DOESN'T happen!
Log.d(TAG,"cycle completed"); //This happens!
}
}
The accepted answer is not correct.
Here is how you can show toast from onHandleIntent():
Create a DisplayToast class:
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
Instantiate a Handler in your service's constructor and call the post method with a DisplayToast object inside.
public class MyService extends IntentService {
Handler mHandler;
public MyService(){
super("MyService");
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new DisplayToast(this, "Hello World!"));
}
}
You should start the Toast on the main thread:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
This is because otherwise the thread of the IntentService quits before the toast can be send out, causing a IllegalStateException:
java.lang.IllegalStateException: Handler (android.os.Handler) {12345678} sending message to a Handler on a dead thread
onHandleIntent() is called from a background thread (that is what IntentService is all about), so you shouldn't do UI from there.
Another option is RxJava, e.g.:
private void showToast(final String text) {
Observable.just(text)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
#Override
public void call(String s) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
}
});
}
Caveat: I'm new to Android.

Categories

Resources