Polling inside Main Activity - android

My requirements are to poll a web service every fixed interval. After instantiating the handler as a private field of the class, I'm doing this in the onCreate method of the main activity:
if (handler != null) {
handler.post(new Runnable() {
#Override
public void run() {
String sessionId = SharedPreferencesHelper.getSessionId(MainActivity.this);
if (sessionId != null && !sessionId.isEmpty()) {
if (Utils.isNetworkAvailable(MainActivity.this)) {
restHandler.getUnreadMessages(sessionId);
}
handler.postDelayed(this, Constants.CHAT_POLLING_REFRESH_DELAY);
} else {
handler.removeCallbacks(this);
}
}
});
}
Then onDestroy:
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
}
The backend is complaing that sometimes the sessionId passed is empty or null. How can this be possible? I'm using retrofit. Bonus question: can I have problems with MainActivity.this context reference when app goes in background?

Related

NullPointerException when invoking Handler.sendEmptyMessageDelayed(int, long)

Saw this crash in Crashlytics after recent app release. It happens 100% in background; 50% in Sony, some in Huawei / Xiaomi, not in Samsung; 79% in Android 10, 19% in Android 8.
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.sendEmptyMessageDelayed(int, long)' on a null object reference
at xxx.xxx.xxx.MyEventManager$MyHandler.handleMessage(MyEventManager.java:80)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:359)
at android.os.HandlerThread.run(HandlerThread.java:67)
Code snippet:
public class MyEventManager {
private static class SingletonInstance {
private static final MyEventManager INSTANCE = new MyEventManager();
}
public static MyEventManager getInstance() {
return SingletonInstance.INSTANCE;
}
private HandlerThread mHandlerThread;
private Handler mHandler;
private class MyHandler extends Handler {
public MyHandler(#NonNull Looper looper) {
super(looper);
}
#Override
public void handleMessage(#NonNull Message message) {
super.handleMessage(message);
switch (message.what) {
case ACTION_SEND_REQUEST:
if (isThreadReady()) {
queryDatabaseAndSendRequest();
mHandler.sendEmptyMessageDelayed(ACTION_SEND_REQUEST, 600 * 1000);
}
break;
default:
break;
}
}
}
private boolean isThreadReady() {
return mHandler != null && mHandlerThread != null && mHandlerThread.getState() != Thread.State.TERMINATED;
}
private void initHandlerThreadIfNeeded() {
if (!isThreadReady()) {
mHandlerThread = new HandlerThread(TAG_HANDLER);
mHandlerThread.start();
mHandler = new MyHandler(mHandlerThread.getLooper());
}
}
public void stopAll() {
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
if (mHandlerThread != null) {
mHandlerThread.quit();
mHandlerThread = null;
}
}
}
The class MyEventManager periodically sends some data to server; as you can see from the code snippet, it calls mHandler.sendEmptyMessageDelayed() in handleMessage() to schedule the next trigger.
The method stopAll() is called in MainActivity's onDestroy().
Since it happens 100% in background and mHandler is set to null in stopAll(), so I believe that MainActivity has been destroyed at that moment, but that's strange because any pending messages should have been removed by mHandler.removeCallbacksAndMessages(null) when stopAll() is called, furthermore, there is null-checking before calling mHandler.sendEmptyMessageDelayed().
Can anyone tell me why I'm getting NPE?

how to know AsyncTask working in background or not?

I am calling one webservice in home page in that i will send all the details in that this process is working in bacground. when i come to this home page again i want to know prvious AsyncTask is end or not
what iam doing exactly here
public void callAsynchronousTask() {
//http://stackoverflow.com/questions/6531950/how-to-execute-async-task-repeatedly-after-fixed-time-intervals
final Handler handler = new Handler();
Timer timer = new Timer();
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
if (vist != null && saves != null && prof != null && semail != null) {
if (vist.getStatus() != AsyncTask.Status.RUNNING) {
if (saves.getStatus() == AsyncTask.Status.PENDING || saves.getStatus() == AsyncTask.Status.FINISHED && saves.getStatus() != AsyncTask.Status.RUNNING)
{
if (prof.getStatus() == AsyncTask.Status.PENDING || prof.getStatus() == AsyncTask.Status.FINISHED && prof.getStatus() != AsyncTask.Status.RUNNING)
{
if (semail.getStatus() == AsyncTask.Status.PENDING || semail.getStatus() == AsyncTask.Status.FINISHED && semail.getStatus() != AsyncTask.Status.RUNNING)
{
checkandsave();
}
}
}
}
} else {
checkandsave();
}
public void checkandsave(){
ConnectionDetector cd = new ConnectionDetector(Home_page.this);
Boolean isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent) {
DatabaseToadd da = new DatabaseToadd(Home_page.this);
mu = new ArrayList<>();
mu = da.getAllUser();
if (mu.size() > 0) {
vist = new Getvisiterid();
saves=new SaveVisitor();
semail=new sendemail();
prof=new saveprofpic();
vist.executeOnExecutor(THREAD_POOL_EXECUTOR);
}
}
else {
System.out.println("null db");
}
but in this when i come back to this actvity if asynctask running in background then also its showing null if i create object on top its showing pending
Based on your text I'm making the assumption you only need this task run in this activity, and dont need multiple tasks run at once. If this is the case use an asynctaskloader. The asynctask is tied to the lifecycle of the activity and you receive callbacks when it is starting, running in background, and done.
AsyncTaskLoader basic example. (Android)

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

ScheduledThreadPoolExecutor only "ticking" once

I was using a CountDownTimer for some countdown functionality I have in my Activity. I decided to move away from CountDownTimer and use ScheduledThreadPoolExecutor because CountDownTimers can't cancel themselves in onTick().
For some reason, my Runnable in the following code only executes once. I'm not sure why it isn't executing multiple times. The destroyCountdownTimer() function is not getting hit.
private ScheduledThreadPoolExecutor mCountdownTimer;
private Tick mTick;
class Tick implements Runnable {
#Override
public void run() {
Log.e("tick", String.valueOf(mAccumulatedMilliseconds));
mAccumulatedMilliseconds += 1000;
populateTimeAccumulated();
populateTimeRemaining();
updatePercentages();
if (mTotalMilliseconds <= mAccumulatedMilliseconds) {
destroyCountdownTimer();
}
}
}
private void startCountdown() {
if (mAccumulatedMilliseconds < mTotalMilliseconds) {
mCounterIsRunning = true;
if (mCountdownTimer == null) {
mCountdownTimer = new ScheduledThreadPoolExecutor(1);
}
if (mTick == null) {
mTick = new Tick();
}
mCountdownTimer.scheduleAtFixedRate(mTick, 1000, 1000, TimeUnit.MILLISECONDS);
}
}
private void destroyCountdownTimer() {
if (mCountdownTimer != null) {
mCountdownTimer.shutdownNow();
mCountdownTimer = null;
}
if (mTick != null) {
mTick = null;
}
}
The documentation says:
If any execution of the task encounters an exception, subsequent executions are suppressed.
Add try-catch block to your Tick runnable.

How to fix null sending message to a Handler on a dead thread warning?

I have a thread using handler and messages to send data to the activity. Everything work fine except when the activity is paused :
null sending message to a Handler on a dead thread
java.lang.RuntimeException: null sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
at android.os.Looper.quit(Looper.java:173)
at pocket.net.ComD.stopConnection(ComD.java:154)
at pocket.net.ComD.finalize(ComD.java:184)
at dalvik.system.NativeStart.run(Native Method)
In my activity , i have the following code which lets me close all the network connection opened by the thread :
public void onPause()
{
if(this.myThread != null) {
this.myThread.stopConnection();
}
}
In my Thread :
public void run()
{
this.setName("MessagesThread");
if(this.initSocket())
{
Looper.prepare();
this.threadHandler = initHandler();
Looper.loop();
}
else
{
this.timeout();
}
}
public void stopConnection()
{
if(this.threadHandler != null) {
this.threadHandler.removeMessages(ALIVE); // Remove a delayed message
this.threadHandler.getLooper().quit(); // Warning
}
this.connected = false;
if(this.client != null) {
this.client.close();
}
}
private Handler initHandler()
{
return new Handler() {
public void handleMessage(Message msg)
{
switch(msg.what)
{
//Handling messages
}
}
}
}
When i receive the warning "null sending message to a Handler on a dead thread" is that the activity trying to send a message to the thread or the oppposite ?
How can i fix this ?
Thanks
You are getting the error as Looper.quit() has already been called.
So the message queue is basically unusable after Looper.quit() has been called the first time, as it enqueues a Message with a null target, which is the magical identifier for the message queue to stop enqueuing and appear "dead".
You need to do something like:
private boolean stoppedFlag= false;
public void stopConnection()
{
if(this.threadHandler != null) {
this.threadHandler.removeMessages(ALIVE); // Remove a delayed message
if(!stoppedFlag){
this.threadHandler.getLooper().quit(); // Warning
stopFlag = true;
}
}
this.connected = false;
if(this.client != null) {
this.client.close();
}
}
To stop quit() being called multiple times
Ref Looper
Ref Looper SOQ

Categories

Resources