I am writing a flashlight app that is a “screen light” for any phone without a torch. I want to have a setting that enables a Strobe Light feature. However, with this type of “flashlight” I thought the easiest way to do this, would be to change the background of the view. I do this in a separate thread because I use a SeekBar to get how fast the strobelight should flash. However, I keep getting the error that the Thread cannot access the View because it is not the Thread that created it. Any suggestions?
Here is what is contained within the onCreate():
mSeekBar = (SeekBar) findViewById(R.id.seekBar);
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
final Thread strober = new Thread(new Runnable(){
public void run(){
strobeLight();
}
});
if (mSeekBar.getProgress()>0) {
runOnUiThread(new Runnable() {
@Override
public void run() {
strober.start();
}
});
}
else {
runOnUiThread(new Runnable() {
@Override
public void run() {
strober.interrupt();
relLayout.setBackgroundColor(color.all_white);
}
});
}
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
Here is the strobeLight() method:
public void strobeLight(){
boolean lightIsOn=true;
runOnUiThread(new Runnable() {
@Override
public void run() {
do {
if (lightIsOn){
relLayout.setBackgroundColor(color.all_black);
try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
catch (InterruptedException e) {}
lightIsOn=false;
strobeActivated=true;}
else{
relLayout.setBackgroundColor(color.all_white);
try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
catch (InterruptedException e) {}
lightIsOn=true; }
if (mSeekBar.getProgress()<1)
strobeActivated=false;
} while (strobeActivated);
relLayout.setBackgroundColor(color.all_white);
}
});
}
Here is the LogCat for the code above:
11-28 17:17:58.383: E/ActivityManager(16877): ANR in com.marshall.meadows182 (com.marshall.meadows182/.LightNoTorch), time=603431510
11-28 17:17:58.383: E/ActivityManager(16877): Reason: keyDispatchingTimedOut
11-28 17:17:58.383: E/ActivityManager(16877): Load: 1.53 / 1.62 / 1.62
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 14662ms to 0ms ago:
11-28 17:17:58.383: E/ActivityManager(16877): 0.8% 16877/system_server: 0.4% user + 0.4% kernel / faults: 7 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0% 14673/com.qikffc.android: 0% user + 0% kernel / faults: 151 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0.2% 16957/com.android.systemui: 0.2% user + 0% kernel / faults: 1 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0.1% 16999/com.android.phone: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 0.1% 13/kondemand/0: 0% user + 0.1% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 0% 68/rild: 0% user + 0% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0% 14830/logcat: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 0.1% 14868/com.marshall.meadows182: 0% user + 0% kernel / faults: 9 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0% 24825/adbd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 0% 5446/com.google.android.apps.maps:NetworkLocationService: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 0% 7839/wpa_supplicant: 0% user + 0% kernel / faults: 3 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0% 17054/com.google.process.gapps: 0% user + 0% kernel / faults: 4 minor
11-28 17:17:58.383: E/ActivityManager(16877): 0% 25055/iqd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 2.7% TOTAL: 1.8% user + 0.8% kernel
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 416ms to 935ms later with 99% awake:
11-28 17:17:58.383: E/ActivityManager(16877): 7.4% 16877/system_server: 0% user + 7.4% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877): 9.2% 16923/InputDispatcher: 1.8% user + 7.4% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 3.8% TOTAL: 0% user + 3.8% kernel
The error message is self-explanatory. You are not allowed to call many methods of views outside of the Thread they were created on, known as the UI Thread.
The problem is the lines
which are run in your thread. You should run them on the UI thread like this: