0

I have an Android App that has a class which runs a thread. Basically the same as here.

The thread at the moment updates a text-view with a calculated value every 500 ms and additionally logs the value, so I can see it in adb-logcat.

When I exit my Application with the back-button of the device, the thread still runs in the background. (Which is what I want). The adb-logcat still gives me the values, that the thread is calculating.

But when I reopen the application, the textview is not updated anymore!

What do I have to do, that it resumes updating the textview, when I open the app again?

Here is my simplified code:

SensorProcessor.java

public class SensorProcessor implements Runnable {

    protected Context mContext;
    protected Activity mActivity;

    private volatile boolean running = true;
    //Tag for Logging
    private final String LOG_TAG = SensorProcessor.class.getSimpleName();

    public SensorProcessor(Context mContext, Activity mActivity){
        this.mContext = mContext;
        this.mActivity = mActivity;
    }


    public void run() {

            while (running){

                try {                    
                    final String raw = getSensorValue();
                    mActivity.runOnUiThread(new Runnable() {
                        public void run() {
                            final TextView textfield_sensor_value;
                            textfield_sensor_value = (TextView) mActivity.findViewById(R.id.text_sensor);
                            textfield_sensor_value.setText("Sensor Value: " + raw); // <-------- Does not update the field, when app resumes
                            Log.v(LOG_TAG, raw); // <-------- Still working after the app resumes
                        }
                    });


                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    //When an interrupt is called, we set running to false, so the thread can exit nicely
                    running = false;
                }
            }

            Log.v(LOG_TAG, "Sensor Thread finished");

    }
}

MainActivity.java

public class MainActivity extends Activity implements OnClickListener, OnInitListener {
    //Start the Thread, when the button is clicked
    public void onClick(View v) {
        if (v.getId() == R.id.button_start) {
            runnable = new SensorProcessor(this.getApplicationContext(),this);
            thread = new Thread(runnable);
            thread.start();
        }
}
Community
  • 1
  • 1
Michael B
  • 1,660
  • 3
  • 28
  • 59

1 Answers1

1

You can extend Application class and insert there getter and setter method to your Runnable. Here is example of MyApplication (don't forget to add the manifest connection!), in manifest.xml:

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppBaseTheme" >

Then MyApplication:

public class MyApplication extends Application {

    private SensorProcessor mSensorProcessor = null;

     public SensorProcessor getCurrentSensorProcessor(){
        return mSensorProcessor;
     }

      public void setSensorProcessor(SensorProcessor mSensorProcessor){
          this.mSensorProcessor = mSensorProcessor;
     }

}

Inside onCreate() of your activity by call :

 ((MyApplication)getApplication()).getCurrentSensorProcessor().mActivity = this;

you need also to modify the Runnable constructor:

public SensorProcessor(Context mContext, Activity mActivity){
    this.mContext = mContext;
    this.mActivity = mActivity;
    ((MyApplication)mActivity.getApplication()).setSensorProcessor(this);
}

And don't forget to empty the instance of mSensorProcessor by calling this inside the Runnable when finish :

((MyApplication)mActivity.getApplication()).setSensorProcessor(null);

Finally you need to modify onClick in your Activity:

 if (v.getId() == R.id.button_start) {
        SensorProcessor mSensorProcessor = ((MyApplication)getApplication()).getCurrentSensorProcessor();
        if (mSensorProcessor != null)
            mSensorProcessor.mActivity = this;
        else {
            runnable = new SensorProcessor(this.getApplicationContext(), this);
            thread = new Thread(runnable);
            thread.start();
        }
    }

It should work, maybe by some minor changes.

yshahak
  • 4,996
  • 1
  • 31
  • 37
  • Your answer looks very promising, thank you! However I don't fully understand it yet. I have 2 Classes (See edit in Question). How and where exactly do I store (set) my Activity, that I need to get later, when the Application is resumed? – Michael B Jul 02 '15 at 11:48
  • Wow, Thank you! This is much more complicated than I thought it would be. I am currently refactoring a few things to try this out. (I extended "Activity" instead of "Application", so this solution won't work out of the box). – Michael B Jul 03 '15 at 09:50
  • I had to change this line: "((MyApplication)getApplication()).getCurrentSensorProcessor().mActivity = this;" but apart from that, your solution works brilliantly! Thanks again! – Michael B Jul 06 '15 at 11:22