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..
}
}
Related
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.
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();
}
});
}
}
}
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 am developing a serialport application for knx modules in android. I can send and recieve commends to knx modulde.
I want to change ui(for ex. button properties) when a message recieved from serialport. I tried it with handlers but i havent be able to change ui. help me plss.
#Override public void OnSerialsData(final byte[] buffer, final int
size) { .... }
its my serialport listener function calling insine ReadThread. This thread is starting in differend package from my activity. I want to send a message in this method to main activity.
You can use Activity.runOnUiThread() to communicate with UI thread. Read more about Processes and Threads, especially about worker threads.
For example within your OnSerialsData, you can call
mActivity.runOnUiThread(new Runnable() {
public void run() {
mActivity.mButton.setText("message arrived!");
}
}
first you have to create a static handler inside your main activity:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public static Handler myHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.e("Test", msg.getData().getCharSequence("MAINLIST").toString());
}
};
}
then in your socket class:
public void OnSerialsData(final byte[] buffer, final int size) {
Message msg = MainActivity.myHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putCharSequence("MAINLIST", "IS_OK");
msg.setData(bundle);
MainActivity.myHandler.sendMessage(msg);
}
but you have to ensure that your handler must be created before you call OnSerialsData method.
I hope this help.
just extending #auselen answer.
Create on your activity the following:
public void messageReceived(final String msg){
runOnUiThread(new Runnable() {
#Override
public void run() {
// Put here your code to update the UI
}
});
}
and then you can call this from any class that have a reference to your activity.
If the class does not have a reference to the activity, then you should pass the reference to it.
I need a timer which will send a message for its' handler. I've made a class that implements Runnable and I feed its' object to the thread runnable constructor. When I start the thread it hangs application and it obviously isn't working asyncroniously. I could've used AsyncTask but I've also heard that they're designed for short-term operations while my background timer must work throughout activity onResumed state. Would you mind pointing out my mistake and maybe giving useful links on the subject of threads in android. Thanks.
Here's the code I've written:
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
_myTimerInstance = new MyTimer(new Handler() {
#Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
// ...
}
});
_myThread = new Thread(_myTimerInstance);
_myThread.run();
}
private static class MyTimer implements Runnable {
private Handler _myHandler;
private boolean _activityHasBeenLeft;
public MyTimer(Handler myHandler) {
_myHandler = myHandler;
}
public void setActivityHasBeenLeft(boolean b) {
_activityHasBeenLeft = b;
}
#Override
public void run() {
while (!_activityHasBeenLeft) {
try {
Thread.sleep(2000);
_myHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You should always use Thread.start() not Thread.run()
Thread.run() is like a normal method call and is run on the same thread.
use
_myThread.start();