Send a toast from a thread within a service - android

I'm trying to send a toast notification of an error in a thread. The thread is started in a service that is called from the main thread. I've tried several things with View.post and some weird handler stuff, but nothing seems to work. An excerpt of the thread is as follows:
public int onStartCommand(Intent intent, int flags, int startId)
{
new Thread(new Runnable(){
public void run() {
boolean bol = true;
while (bol)
{
try
{
//Some socket code...
}
catch (Exception e)
{
//Where I want the toast code.
}
}
}
}).start();
return START_STICKY;
}

Try following inside the thread in the service:
Handler h = new Handler(context.getMainLooper());
// Although you need to pass an appropriate context
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context,message,Toast.LENGTH_LONG).show();
}
});
Taken from answer given by #Alex Gitelman here on Android: How can i show a toast from a thread running in a remote service? . This might help somebody as it helped me.

Toast can be shown only from UI Thread (Main Thread). To show Toast from some other threads you have to use Handler.
Threads, Handlers and AsyncTask

Yes you should use a Handler, and bind you Activity to your Service
Once the Handler is set, here is what you should do,
Message msg = Message.obtain(null, MyActivity.TOAST);
Bundle bundle = new Bundle();
bundle.putString(MyActivity.TOAST_MSG, "Toast message");
msg.setData(bundle);
try {
myActivityMessenger.send(msg);
} catch (RemoteException e) {
if (D) Log.w(TAG, "Unable to send() the toast message back to the UI.");
e.printStackTrace();
}
myActivityMessenger is set with the Handler of your MyActivity and sent to the Service when you bind MyActivity to it.
However displaying a Toast with a Service as context should work (but it's not the best way), so maybe it's because you try to make it from a new Thread. What is your code for making the Toast ?

new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
_dialog.dismiss();
Toast.makeText(LatestNewsActivity.this, "NO Internet Connection Available", Toast.LENGTH_LONG).show();
}
});
}
}.start();

Related

finish Thread actions before activity continues

this is a piece of code from my project, i need this thread to be over untill the end and only then go to the last Log.i() and finish the function.
public void delay3Seconds(final String txt1, final String txt2, final String s, final Intent i)
{
//keepMoving= false;
counter= 3;
secondsBool= true;
if(!errorMonitor)
{
Log.i("Main.delay3Seconds()", s+" in 3 seconds");
new Thread()
{
public void run()
{
while(secondsBool)
{
try {
Thread.sleep(1500);
}
catch (InterruptedException e){e.printStackTrace();}
if(!errorMonitor)
{
handler.post(new Runnable()
{
public void run()
{
final DialogFragment loadDF= new RecDialog(MainActivity.this, txt1, txt2, s+(counter--)+" שניות", null, false, true, ll.getWidth(), ll.getHeight());
loadDF.show(getSupportFragmentManager(), "RecDialog");
dialog.dismiss();
dialog= loadDF;
if(counter == 0)
secondsBool= false;
}
});
}
else
secondsBool= false;
}
if(!errorMonitor)
{
handler.post(new Runnable()
{
public void run()
{
dialog.dismiss();
if (i.resolveActivity(getPackageManager()) != null)
{
Log.i("Main.delay3Seconds()", "resolveActivity != null");
setResolveNotFail(true);
Log.i("Main.delay3Seconds()", "resolveNotFail = "+resolveNotFail);
startActivity(i);
}
else
{
Log.i("Main.delay3Seconds()", "resolveActivity == null");
setResolveNotFail(false);
Log.i("Main.delay3Seconds()", "resolveNotFail = "+resolveNotFail);
}
}
});
}
}
}.start();
}
Log.i("Main.delay3Seconds()", "(end) resolveNotFail = "+resolveNotFail);
}
i can't figure out how to do that. i tried using synchronized(), but i probably use it wrong because the function finishes itself first and only then the thread works, simultaneously to the activity.
i would appreciate any tips on how to do that..
That's absolutely not how or why you use a Thread. First off, if this is the UI thread you should never pause it for 3 seconds. Second, the entire point of a Thread is to work in parallel. You never want one thread to pause and wait for another. If you need something on Thread A to occur only when Thread B is done, you send a message via a handler, semaphore or other method to Thread A when Thread B is done.
Looking at your code, it seems like you should throw it out and reimplement it with a timer.
https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html
Just call the .join() method after you start your thread so the calling thread will wait until your new thread executes.
Something like this:
Thread t = new Thread(...);
t.start();
t.join();

Handler stuck in loop within Android Service

I'm currently trying to do an app that keeps track of the phone through the GPS by using a service. in order to get the GPS to update the coordinates, I need to use a handler within the service. Right now the proble I have is that when the I do the Handler.post, it gets stuck in an loop, and after that, it completely ignores the rest of the service code.
When I was debugging, I found out that the handler was alternating messages between methods but nothing useful came out of it, it was just a loop between the same methods over and over again.
Here's my Service code that includes the handler:
public int onStartCommand(Intent intent, int flags, int startId)
{
ctx = ServicioDeFondo.this;
mHandler = new Handler();
reportarGPS = new Thread(new Runnable() { public void run()
{
try
{
while(true)
{
mHandler.post(new Runnable() {
#Override
public void run() {
gps = new GPSTrack(ctx);
latitude = String.valueOf(gps.getLatitude());
longitude = String.valueOf(gps.getLongitude());
}
});
Thread.sleep(10000);
try {
new APISendClass().execute();
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
catch (Exception e)
{
//TODO Auto-generated catch block
e.printStackTrace();
}
} });
reportarGPS.start();
return START_STICKY;
}
I"ve been stuck here all day, any help would be greatly appreciated!
With your brief description of the problem, it's hard to understand what the expected behavior is. You don't explain what GPSTrack and APISendClass do and what type of objects that are. You state "it gets stuck in a loop". It's not clear what "it" is. With the while (true) statement, the thread will loop until cancelled.
Note that Service methods, such as onStartCommand() run on the main thread. That means that your Handler() constructor associates the handler with the main thread. The runnables you post to that handler run on the main thread. Is that what you wanted?
Also note that stopping the service by stopSelf() or Context.stopService() does not kill the thread. You need to have code to cancel the thread when it is no longer needed. This is often done in onDestroy().
I took the code you posted, replaced the calls to unknown objects with Log statements and ran it. The logcat output alternated between "Get lat/long" and "APISendClass()".
Handler mHandler;
Context ctx;
Thread reportGPS;
public int onStartCommand(Intent intent, int flags, int startId){
Log.i("TEST", "onStartCommand()");
ctx = this;
// Service methods run on main thread.
// Handler constructor with no args associates Handler
// with current thread, which here is the main thread.
mHandler = new Handler();
reportGPS = new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
mHandler.post(new Runnable() {
#Override
public void run() {
// This runnable is posted to the main thread.
// Is that what you intended?
//gps = new GPSTrack(ctx);
//latitude = String.valueOf(gps.getLatitude());
//longitude = String.valueOf(gps.getLongitude());
Log.i("TEST", "Get lat/long");
}
});
Thread.sleep(2000);
try {
//new APISendClass().execute();
Log.i("TEST", "APISendClass().execute()");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
reportGPS.start();
return START_STICKY;
}

How to show toast when service running on a separate thread?

Is there any way to show a toast when the service is running on a separate thread?
I use the code below.
public void onStart(Intent intent, int startid){
final String name = intent.getStringExtra("name");
Log.d(TAG,"onStart()");
new Thread(new Runnable() {
public void run() {
try
{
Toast.makeText(getApplicationContext(), "Ashish 1",Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
Log.d(TAG,"Exception....."+e);
}
}
}).start();
}
Toast messages can only shown on uithread. But if you want to use on another thread, you can implement it like this.
yourActivityObject.runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(yourContextObject, "some text",Toast.LENGTH_LONG).show();
}
});

While Loop inside Thread not working?

I have a very simple UI and i need to constantly run a check process, so I am trying to use a Thread with a while loop.
When I run the loop with nothing but a Thread.sleep(1000) command, it works fine, but as soon as I put in a display.setText(), the program runs for a second on the emulator then quits. I cannot even see the error message since it exits so fast.
I then took the display.setText() command outside the thread and just put it directly inside onCreate, and it works fine (so there is no problem with the actual command).
here is my code, and help will be greatly appreciated.
Thank you!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
on=(Button) findViewById(R.id.bon);
off=(Button) findViewById(R.id.boff);
display=(TextView) findViewById(R.id.tvdisplay);
display2=(TextView) findViewById(R.id.tvdisplay2);
display3=(TextView) findViewById(R.id.tvdisplay3);
stopper=(Button) findViewById(R.id.stops);
stopper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(boo=true)
{
boo=false;
display3.setText("System Off");
}
else{
boo=true;
}
}
});
Thread x = new Thread() {
public void run() {
while (boo) {
display3.setText("System On");
try {
// do something here
//display3.setText("System On");
Log.d(TAG, "local Thread sleeping");
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
};
display3.setText("System On");
display3.setText("System On");
x.start();
}
You can't update the UI from a non-UI thread. Use a Handler. Something like this could work:
// inside onCreate:
final Handler handler = new Handler();
final Runnable updater = new Runnable() {
public void run() {
display3.setText("System On");
}
};
Thread x = new Thread() {
public void run() {
while (boo) {
handler.invokeLater(updater);
try {
// do something here
//display3.setText("System On");
Log.d(TAG, "local Thread sleeping");
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
};
You could also avoid a Handler for this simple case and just use
while (boo) {
runOnUiThread(updater);
// ...
Alternatively, you could use an AsyncTask instead of your own Thread class and override the onProgressUpdate method.
Not 100% certain, but I think it is a case of not being able to modify UI controls from a thread that did not create them?
When you are not in your UI thread, instead of display3.setText("test") use:
display3.post(new Runnable() {
public void run() {
display3.setText("test");
{
});
You should encapsulate this code in an AsyncTask instead. Like so:
private class MyTask extends AsyncTask<Void, Void, Void> {
private Activity activity;
MyTask(Activity activity){
this.activity = activity;
}
protected Long doInBackground() {
while (true){
activity.runOnUiThread(new Runnable(){
public void run(){
display3.setText("System On");
}
});
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
Then just launch the task from your onCreate method.
In non-UI thread,you can't update UI.In new Thread,you can use some methods to notice to update UI.
use Handler
use AsyncTask
use LocalBroadcast
if the process is the observer pattern,can use RxJava

How to start a new Thread in a service?

I am developing an Android app and I am doing some heavy work (bringing data from an online web page and parsing it to store in database) in a service. Currently, it is taking about 20+ mins and for this time my UI is stuck. I was thinking of using a thread in service so my UI doesn't get stuck but it is giving error. I am using the following code:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
Toast.makeText(getBaseContext(), "Running Thread...", Toast.LENGTH_LONG).show();
}
} catch (InterruptedException e) {
Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
};
thread.start();
This simple code is giving run time error. Even If I take out the while loop, it is still not working.
Please, can any one tell me what mistake I am doing. Apparently, I copied this code directly from an e-book. It is suppose to work but its not.
Android commandment: thou shall not interact with UI objects from your own threads
Wrap your Toast Display into runOnUIThread(new Runnable() { });
Example of new thread creation taken from Android samples (android-8\SampleSyncAdapter\src\com\example\android\samplesync\client\NetworkUtilities.java):
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
runnable is the Runnable that contains your Network operations.
You can use HandlerThread and post to it, here is an example to service that has one.
public class NetworkService extends Service {
private HandlerThread mHandlerThread;
private Handler mHandler;
private final IBinder mBinder = new MyLocalBinder();
#Override
public void onCreate() {
super.onCreate();
mHandlerThread = new HandlerThread("LocalServiceThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
public void postRunnable(Runnable runnable) {
mHandler.post(runnable);
}
public class MyLocalBinder extends Binder {
public NetworkService getService() {
return NetworkService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
You may define your jobs in a runnable object, use a thread object for running it and start this thread in your service's onStartCommand() function. Here is my notes:
In your service class:
define your main loop in an Runnable object
create Thread object with the runnable object as parameter
In your service class's onStartCommand method():
call thread object's start function()
my code :
private Runnable busyLoop = new Runnable() {
public void run() {
int count = 1;
while(true) {
count ++;
try {
Thread.sleep(100);
} catch (Exception ex) {
;
}
ConvertService.running.sendNotification("busyLoop" + count);
}
}
};
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification("onStartCommand");
if (! t.isAlive()) {
t.start();
}
return START_STICKY;
}

Categories

Resources