How to call the handler from separate class in android? - android

In my application, am try to set an time out function i not able to call the handler method in separate class.
My Timeout Class
public class Timeout_function {
private Handler mHandler;
Activity activity;
public Timeout_function(Activity activity,Handler mHandler) {
super();
this.activity = activity;
this.mHandler = mHandler;
}
Runnable myTask = new Runnable() {
#Override
public void run() {
Toast.makeText(activity, "Test", 1000).show();
mHandler.postDelayed(this, 1000);
}
};
// just as an example, we'll start the task when the activity is started
public void onStart() {
mHandler.postDelayed(myTask, 1000);
}
// at some point in your program you will probably want the handler to stop
// (in onStop is a good place)
public void onStop() {
mHandler.removeCallbacks(myTask);
}
}
Main class
In main class i call the method in this way,but it shows error in run time,
Timeout_function timeout = new Timeout_function(this, mHandler);
timeout.onStart();
how to call the method in main class.can any one know please help me to solve this problem.

Instead of creating a seperate class why you are not using Service?
I would insist you to use Service and start your Runnable using Handler in onStartCommand() of Service by call startService(intent);
and you can stop the Runnable using Handler by placing it inside onDestroy() method of Service and calling by stopService(intent).
This is what I had done and it works like a charm!

Related

android: update UI from another thread in another class

The scenario is
I have two threads and a UI thread. The UI thread when clicked on login button creates a ClientThread which creates a socket and runs until the socket is connected, whenever a message is received i use a handler to post message to another thread called ProcessDataThread, now on receiving some messages from server i need to update UI related stuff from ProcessDataThread, I searched around alot and i found these two ways runonUiThread function which i guess can only be run from the Activity Class which is useless and the Asynctask method which i am not sure how to pass the activity context to...
Here is the code
The code executed when clicked on Login Button in the MainActivity
public void onLoginClick(View view)
{
global_constants.clientObject = new ClientThread();
global_constants.clientThread = new Thread(global_constants.clientObject);
global_constants.clientThread.start();
}
The code in ClientThread run method
public class ClientThread implements Runnable {
.......
#Override
public void run() {
......
while(!Thread.currentThread().isInterrupted() && (!CloseThread))
{
byte[] buff;
....
global_constants.updateConversationHandler.post(new ProcessDataThread(buff));
}
}
}
The method code in ProcessDataThread after parsing out the incoming data and stuff
public class ProcessDataThread implements Runnable {
.........
void ProcessLoginFailedPacket(byte[] buff)
{
// how to call the UI thread from here for updating some UI elements??
}
}
[EDIT]
i stored the activity context in a global variable and then did it this way, but i dont know whether it will be safer or not
((Activity)global_constants.MainContext).runOnUiThread(new Runnable(){
public void run()
{
TextView txtErr = (TextView) ((Activity)global_constants.MainContext).findViewById(R.id.errMsg);
txtErr.setVisibility(0);
txtErr.setText(reason);
}
});
You can post a runnable which does the UI operation to main thread as follows,
public class Utils {
public static void runOnUiThread(Runnable runnable){
final Handler UIHandler = new Handler(Looper.getMainLooper());
UIHandler .post(runnable);
}
}
Utils.runOnUiThread(new Runnable() {
#Override
public void run() {
// UI updation related code.
}
});

Android - Running a delayed task from a Worker Thread (NotificationListenerService Thread)

I need to call a delayed method(runnable) from the NLService thread. However the method never gets called. I would appreciate any help.
public class NLService extends NotificationListenerService {
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
if(sbn.getPackageName().contains("mv.purple.aa")){
AudioManager amanager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
amanager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true);
//This is the code I am having issues with.
//I used this code to call the method. However it is not working.
private Handler handler = new Handler();
handler.postDelayed(runnable, 100);
}
}
//I want to call the following method
private Runnable runnable = new Runnable() {
#Override
public void run() {
foobar();
}
};
}
The NotificationListenerService is a service which gets activated when notifications are posted within the framework. It does this via a Binder notification internal to the framework, so your onNotificationPosted() callback is being called from one of the binder pool threads, not the usual main thread of your app. In essence, the Handler you are creating is associating itself with a Looper which never gets called because the thread is managed by the internal binder framework rather than the usual main thread or other thread you may create.
Try this: create a HandlerThread the first time your callback is hit (and save it off) and start it. Toss your Runnable over to a Handler you create which is bound to the Looper in the HandlerThread.
There is also a "simpler" solution.
You can create a new Handler inside your onCreate(). Save it as class variable and call it when ever you want again.
Example:
public class NotificationListener extends NotificationListenerService
private mHandler handler;
public void onCreate() {
super.onCreate();
handler = new Handler();
}
#Override
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do something special here :)
}
}, 5*1000);
}
....
// Override other importand methods
....
}

how to use runOnUiThread without getting "cannot make a static reference to the non static method" compiler error

I have a main class;
ClientPlayer extends Activity {
and a service
LotteryServer extends Service implements Runnable {
when trying to use the RunOnUiThread in the run method of this service I am getting compiler error of, "cannot make a static reference to the non static method"
how to fix this?, how I am using the code is shown here;
#Override
public void run() {
// I tried both ClientPlayer.runOnUiThread and LotteryServer.runOnUiThread
// both don't work
ClientPlayer.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "from inside thread", Toast.LENGTH_SHORT).show();
}
});
} // end run method
runOnUiThread is not a static method.
If u want to run your runnable on UIThread You can use this
Handler handler = new Handler(Looper.getMainLooper());
This will create a handler for UI Thread.
ClientPlayer extends Activity {
.
.
public static Handler UIHandler;
static
{
UIHandler = new Handler(Looper.getMainLooper());
}
public static void runOnUI(Runnable runnable) {
UIHandler.post(runnable);
}
.
.
.
}
Now u can use this anywhere.
#Override
public void run() {
// I tried both ClientPlayer.runOnUiThread and LotteryServer.runOnUiThread
// both don't work
ClientPlayer.runOnUI(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "from inside thread", Toast.LENGTH_SHORT).show();
}
});
} // end run method
There is a very simple solution to the above problem
just make a static reference of your Activity before your onCreat() method
MainActivity mn;
then initialize it in you onCreat() method like this
mn=MainActivity.this;
and after that you just have to use it to call your runOnUiThread
mn.runOnUiThread(new Runnable() {
public void run() {
tv.setText(fns);///do what
}
});
hope it work.
You can get the instance of your Activity, pass it to the service, and use that instead of the class name.
then you can use:
yourActivity.runOnUiThread( ...
Generally we use this method(RunOnUiThread) when we try to update our UI from a working thread. but As you are Using Service Here, runOnMainThread is seems inappropriate as per your situation.
Better to Use Handler here. Handler is an element associated to the thread where is created, you can post a runnable with your code to the Handler and that runnable will be executed in the thread where the Handler was created.
Create a Handler on your Service in his MainThread and post Runnables on
it / send messages to it.

Using a Service with A Timer to Update a View

I'm not sure if this is the correct way to go about but I will try and explain what I want to do.
I have an Activity which creates a fragment called TemporaryFragment with a label. What I want to do is create and start a service with a Timer in it and that Timer then updates the time in that TextView.
The way I am thinking of going is somehow, when the Service is started, passing the TextView from the Activity to the Service and then the Service keeping a reference to it.
Another possible way is to make the Activity become a listener of the Service and then calling a method in the Service to update the TextView.
Any thoughts would be great and maybe some options.
Thanks in advance.
ADDITION
I'm sorry, I should also specify that I need this timer to run in the background. So when the application is sent to the background, I need the timer to carry on and only stop when I tell it to.
Service is not ideal for such minor task like this, moreover, Service can be run independently of activity. Also spawning new thread or using timer which introduces new thread into the application is not ideal for this relatively minor reason if you are thinking in the terms of mobile applications.
Instead use Handler in your fragment.
create handler in your fragment
private Handler mHandler = new Handler();
to execute your defined task call
mHandler.postDelayed(mUpdateTask, 1000);
or
mHandler.post(mUpdateTask);
and define your task in the fragment
private Runnable mUpdateTask = new Runnable() {
public void run() {
Toast.makeText(getActivity(), "hello world", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(this, 1000);
}
};
If you are showing time-like information instead of countdown-like one, use
mHandler.removeCallbacks(mUpdateTimeTask);
in onPause() method to stop executing your task if the activity is not visible as updating UI isn't relevant and it saves battery (you start task again in onResume() method)
Basically, the idea behind the timer is eventually I am going to add some tracking into my application and therefore need it to continue running even if the application isn't in the foreground – Disco S2
Based on this comment I suggest you to use a local service which resides in the background, doing it's stuff (start a thread from Service#onStart), until it gets stopped by stopService(..).
Activities on the other hand may bind and unbind to that service (see: bindService(..)) to get notified about updates or to communicate with the service in any way.
I would use a more simple approach by using a Thread:
public class MainActivity extends Activity implements Callback {
private static final int MSG_UPDATE = 1;
private static final long INTERVAL = 1000; // in ms
private final Handler handler = new Handler(this);
private Thread worker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE:
updateView();
return true;
}
return false;
}
private void updateView() {
// TODO tbd
}
#Override
protected void onStart() {
super.onStart();
// start background thread
worker = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
break;
}
// send message to activity thread
handler.sendEmptyMessage(MSG_UPDATE);
}
}
});
worker.start();
}
#Override
protected void onStop() {
super.onStop();
// stop background thread
worker.interrupt();
try {
worker.join();
} catch (InterruptedException e) {
}
worker = null;
}
}
You can use the TimerTask Class for this. Override the TimerTask.run() method and then add that TimerTask to Timer class.
Also check this question: controlling a task with timer and timertask

removeCallbacks not stopping runnable

I am calling from a method:
myHandler.postDelayed(mMyRunnableHide, 6000);
which calls:
public Runnable mMyRunnableHide = new Runnable()
{
public void run()
{
mTextDisplay.setText("");
DisplayX();
}
};
if a button on screen is clicked I want to stop the runnable:
Button next = (Button) findViewById(R.id.Breaction);
next.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myHandler.removeCallbacks(mMyRunnableHide);
mTextDisplay.setText("");
DisplayX();
}
});
}
the removecallbacks is not stopping the runnable. What am I doing wrong? Am I using the correct method? I just want the runnable to "Not Run" when the user clicks the button.
Thanks for any help.
It appears to me that removeCallbacks(..) only stops pending messages (Runnables). If your runnable has already started, then there's no stopping it (at least not this way).
Alternatively, you can extend the Runnable class and give it some kind of kill switch like this:
public class MyRunnable implements Runnable
{
private boolean killMe = false;
private void run()
{
if(killMe)
return;
/* do your work */
}
private void killRunnable()
{
killMe = true;
}
}
This will only prevent it from starting, but you could occasionally check killMe and bail out. If you are looping the runnable (like some kind of background thread) you can say:
while(!killMe) {
/* do work */
}
Hope this helps
EDIT I just wanted to post an update on this. Since this original post, Google has come up with a great class called AsyncTask that handles all of this stuff for you. Anyone reading this really should look into it because it is the correct way of doing things.
You can read about it here
Handler.removeCallback is synchronous and will work nicely provided:
You call postDelayed always in the main thread.
You call removeCallback always in the main thread
You don't call postDelayed again after having removed callbacks.
So in your case removeCallbacks is called from a button handler, which runs in the main thread. But you didn't show in your code the point from where you call postDelayed. If you call it from a background thread thats where your problem is.
If you are sure you don't call any of these methods from background threads, and the order of the calls is correct, then you might be leaving uncancelled tasks unadvertedly alive due to activity recreation on config changes (screen rotation, etc). Always make sure to call removeCallbacks again in the onDestroy method to prevent this kind of problems.
Here is another way to accomplish what mtmurdock is describing. This class will allow editing of instance variables in any class that your Runnable is defined as an anonymous inner class.
package support;
/**
* Runnable that can be stopped from executing
*/
public abstract class KillableRunnable implements Runnable{
private boolean isKilled=false;
/**
* Instead of Overriding run(), override this method to perform a Runnable operation.
* This will allow editing instance variables in the class that this Runnable is defined
*/
public abstract void doWork();
//The handler that posts this Runnable will call this method.
//By default, check if it has been killed. doWork() will now be the method
//override to implement this Runnable
#Override
final public void run(){
if(!isKilled){
doWork();
}
}
final public void kill(){
isKilled=true;
}
}
I don't think that removeCallbacks(..) only stops pending messages (Runnables) ,I think removeCallbacks(..) not working have other cause,but i don‘t know. because postDelayed(..) and removeCallbacks(..) is in the same thread
the following has worked for me. Place it in onResume.
mService= null;
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "OnServiceConnected");
ContadorFG.LocalBinder binder = (ContadorFG.LocalBinder) service;
mService = binder.getService();
connected = true;
synchronized (lock){
lock.notifyAll();
}
}
public void onResume() {
super.onResume();
loopDelayed();
}
private void loopDelayed(){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (mService != null) {
----
----
----
return;
}else{
//auto call
loopDelayed();
}
}
}, 10);
}

Categories

Resources