0

If I leave a thread running when I quit my android app, can I get access to that thread when the app is restarted? I know that the thread is still associated with my app because I can kill it by going to settings-apps-force stop.

more details: my app connects to a device via bluetooth. when i rotate the tablet, it restarts the app, but if i don't stop all the threads, the old thread reconnects to the device and the app is not able to connect with a new thread.

I have fixed the basic problem by not allowing the app screen to rotate, and by killing the connect thread onDestroy(). but I would like to know how to re-connect with that sort of zombie thread just out of curiosity.

I can see threads that I don't recognize in Thread.enumerate(), but I don't know how to get access to those threads, other than seeing the name and their state.

3 Answers3

0

The way I deal with this in my apps is to override an Activity's onRetainCustomNonConfigurationInstance() method, which allows you to retain an object through the restart that happens when the screen is rotated. Here's how I implement it.

I have an AsyncTask that performs a web request. The AsyncTask is in a separate file, and takes a reference to the calling Activity as a listener for some callbacks I have implemented. So the constructor for my web request AsyncTask is something like this:

private Callbacks listener;

public WebRequest(Callbacks listener) {
    this.listener = listener;
}

I implement onRetainCustomNonConfigurationInstance() in my Activity like this:

@Override
public Object onRetainCustomNonConfigurationInstance() {
    if(webRequest != null) {
        webRequest.detachFromActivity();
        return webRequest;
    } else {
        return null;
    }
}

Now, when my screen is rotated, the Activity restarts, and if my AsyncTask is running, it will save a reference to it here. Notice that I also "detach" my task from this current Activity, which will now be destroyed. I accomplish this in my task by just making the listener (which is the current Activity) null. Like this:

public void detachFromActivity() {
    listener = null;
}

Now when the Activity restarts, in onCreate(), I check to see if there was a retained reference to my running thread by calling getLastCustomNonConfigurationInstance() like this:

Object retainedRequest = getLastCustomNonConfigurationInstance();
if(retainedRequest != null) {
    if(retainedRequest instanceof WebRequest) {
        webRequest = (WebRequest) retainedRequest;
        webRequest.setListener(this);
    }
}

Since the reference to my running thread is passed as an Object, I need to retrieve it as an Object, then check if it's an instance of my AsyncTask, then cast it if it is.

The last step is to "reconnect" the callbacks to this NEW Activity, which was just created, so the task knows where to send the results. I use the setListener(this) method to do it in my task, like this:

public void setListener(Callbacks listener) {
        this.listener = listener;
}

Now I can re-attach a reference to an old thread with a newly re-created Activity. You may not be using an AsyncTask, but the concept is the same and should work for any Thread, or any object you want, really.

Hope this helps!

NoChinDeluxe
  • 3,446
  • 1
  • 16
  • 29
0

Im not sure on your question, but what you are doing is kinda wrong. Screen rotation are UI changes and they should not affect your other code. Check this answer for some guidance- http://stackoverflow.com/questions/5913130/dont-reload-application-when-orientation-changes PS: NoChinDeluxes answer is also good for decoupling UI with other elements

X3Btel
  • 1,408
  • 1
  • 13
  • 21
0

The basic problem, as you have discovered, is that you have implemented your app in such a way that your bluetooth connection is logically bound to an Activity (i.e. the Activity is responsible for keeping track of the thread handling bluetooth activity).

To have the bluetooth connection reference survive a rotation, you will need to decouple it from the Activity. There are a number of ways to do this, depending on exactly what your requirements are.

You could, for instance, implement the bluetooth code as a Service. There are other ways as well - for instance, take a look at Activity restart on rotation Android

Community
  • 1
  • 1
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • thank you. the blog post in the second response (using a retained fragment) appears to be exactly what I need. – rod_droid May 16 '16 at 14:47