1

I am developing an Android app that has a page that requires a connection to be active AND requires a certain piece of information to be collected from the device before allowing users to move to the next step.

I was using an AsyncTask to check both of these booleans. If either of them were 'false', it would display a Toast. It would then Thread.sleep for 1 second, check again and toast again until both booleans are true or they have left the page.

The problem, we learned yesterday, is that Thread.sleep sleeps all Async tasks in the threadpool. So it was also sleeping the Connection AsyncTask and preventing us from ever being able to successfully connect.

My alternate plan was to switch my current Task to a scheduled Timer, until I read that it "is discouraged in Android" (but the link to the article is broken): Android Asynctask vs Runnable vs timertask vs Service

I feel that spawning a thread to check the status of two booleans is not a good idea in the first place, but I'm not sure how else to handle it. Thank you for your suggestions!

EDIT: I have reworded the question to be more clear.

Community
  • 1
  • 1
beyondtheteal
  • 729
  • 6
  • 15
  • "I should probably mention that I cannot listen to BluetoothReceiver, as there are actually 2 booleans that I am checking." That doesn't explain why you can't use it. Those booleans can be persisted on `SharedPreferences` for example, so you can retrieve their state when receiving the broadcast. – Anyonymous2324 Apr 15 '15 at 09:33
  • Correct, it doesn't mean that I _can't_ use it. It would superfluous, however. I would still need a solution to periodically check the second boolean until it was 'true'. – beyondtheteal Apr 15 '15 at 09:36
  • Whatever it is you are trying to do, checking for connected devices periodically is bad. You can never be sure of when the bluetooth device will be connected again. What if it is never? Your app will be wasting resources for no reason. Use the broadcast to keep your app updated about the status of connected devices and use your periodically checks for the other boolean while just reading the now known status of the devices. – Anyonymous2324 Apr 15 '15 at 09:38
  • Agreed. As I mentioned in my original final paragraph, it is 'not a great idea' to spawn a thread to listen for a variable to change. I would prefer to register a listener or something, but I am unsure how to…hence the SO Question. – beyondtheteal Apr 15 '15 at 09:41
  • And hence my answer regarding the connected devices. :P – Anyonymous2324 Apr 15 '15 at 09:44
  • For your other variable, you should probably post another question better explaining what you are trying to do and accept this one. – Anyonymous2324 Apr 15 '15 at 09:45
  • I have reworded the question to be more clear. – beyondtheteal Apr 15 '15 at 09:50

3 Answers3

0

better to listen for Bluetooth Connection state change Intent, and if the connection goes from DISCONNECTED to CONNECTED, you will know in via Intent(broadcast receiver). You do not need to check state every second or so.

See below answer to understand how you can register for events.

How to register intent for Connection States

Also see Android Documentation

Community
  • 1
  • 1
AAnkit
  • 27,299
  • 12
  • 60
  • 71
  • Thank you for the suggestion! However, for this particular use case, I am unable to use this approach. Please see the edit on my question. – beyondtheteal Apr 15 '15 at 09:32
0

Regarding your bluetooth devices from your original question, you should use a BroadcastReceiver and listen for specific system actions like BluetoothDevice.ACTION_ACL_CONNECTED, BluetoothDevice.ACTION_ACL_DISCONNECTED and BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.

This way, you keep your app updated about the status of connected devices.

Now for your recent edit, you should use a Handler and a Runnable for this. Declare both as members of your Activity and start the Runnable like so on your activity's onResume():

myHandler.postDelayed(myRunnable, 1000);

Your Runnable should look like:

private Runnable myRunnable = new Runnable() {

    @Override
    public void run() {
        //Check your logic here

        if (logic not present) {
            myHandler.postDelayed(myRunnable, 1000);
        }
    }
};

Inside the Runnable you check if your variables match what you want. If they don't, you use your Handler to run the Runnable again. One last thing, on your Activity onPause() you should stop the Runnable from running:

myHandler.removeCallbacks(myRunnable);

Hope that helps.

Anyonymous2324
  • 250
  • 3
  • 12
0

The other two guys provides you with the clean solution that you probably should use. I however think there is a quick and dirty fix if you don't want to re-write your code.

The problem is the default behaviour of AsyncTask; They run sequentally. So when your thread sleeps, the other tasks are just waiting in line for it to finish. To change this behaviour you can do your AsyncTask with .executeOnExecutor(); rather than .execute();

This will make other AsyncTasks run without interference, allowing multiple threads at a time.

Treeline
  • 475
  • 1
  • 8
  • 23
  • I probably should have shared that I was already running them like this: task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); However, the Thread.sleep still seems to affect both of them. – beyondtheteal Apr 15 '15 at 09:27
  • Damn. In that case, the other two solutions apply. :) – Treeline Apr 15 '15 at 09:29
  • 1
    Thank you anyway! If you find any documentation on _why_ Thread.sleep affects both of them, that would be great. I was unable to dig up anything. – beyondtheteal Apr 15 '15 at 09:33