So I understand the error. I'm trying to adjust the UI with a thread that isn't the main UI thread. But that's inherently the problem. Doing image processing (in this case greyscaling multiple bitmaps) is a CPU intensive task. Therefore, wouldn't me trying to launch a thread that deals with image processing be the right thing to do? Or is my thought just an ideal thought that simply isn't possible because of the valid error I am receiving? Is there a work around that I'm unaware of?
Actual error message: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
//Package declaration
//Many import statements
public class PhotoViewer extends Activity implements OnClickListener {
private Button refresh_;
private Button grey_;
private ImageView image1_;
private ImageView image2_;
private ImageView image3_;
private ImageView image4_;
private GreyBitmaps gMap_;
private Bitmap bMap1_;
private Bitmap bMap2_;
private Bitmap bMap3_;
private Bitmap bMap4_;
private int num_;
private boolean makeGrey_;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photos);
// this GreyBitmaps class creates the other thread
gMap_ = new GreyBitmaps();
refresh_ = (Button) findViewById(R.id.refresh);
grey_ = (Button) findViewById(R.id.grey);
image1_ = (ImageView) findViewById(R.id.view1);
image2_ = (ImageView) findViewById(R.id.view2);
image3_ = (ImageView) findViewById(R.id.view3);
image4_ = (ImageView) findViewById(R.id.view4);
refresh_.setOnClickListener(this);
grey_.setOnClickListener(this);
makeGrey_ = false;
getPhotos();
setBitmap();
//num_ =0;
}
public void onClick(View v) {
Log.d("onClick", "Begin");
if(v == refresh_){
refreshPhoto();
}else if (v == grey_){
greyPhoto();
}
Log.d("onClick", "end");
}
protected void onResume(){
super.onResume();
gMap_.resume();
}
protected void onPause(){
super.onPause();
gMap_.pause();
}
private void refreshPhoto(){
getPhotos();
}
private void greyPhoto(){
makeGrey_ = true;
}
private void getPhotos(){
bMap1_ = BitmapFactory.decodeResource(getResources(), R.drawable.p1);
bMap2_ = BitmapFactory.decodeResource(getResources(), R.drawable.p2);
bMap3_ = BitmapFactory.decodeResource(getResources(), R.drawable.p3);
bMap4_ = BitmapFactory.decodeResource(getResources(), R.drawable.p4);
}
private void setBitmap(){
image1_.setImageBitmap(bMap1_);
image2_.setImageBitmap(bMap2_);
image3_.setImageBitmap(bMap3_);
image4_.setImageBitmap(bMap4_);
}
private Bitmap goGrey(Bitmap bmIn){
final double gs_red = 0.299;
final double gs_green = 0.587;
final double gs_blue = 0.114;
int width = bmIn.getWidth();
int height = bmIn.getHeight();
Bitmap bmOut = Bitmap.createBitmap(width, height, bmIn.getConfig());
int a, r, g, b;
int pix;
for(int x = 0; x<width; x++){
for(int y = 0; y<height; y++){
pix = bmIn.getPixel(x, y);
a = Color.alpha(pix);
r = Color.red(pix);
g = Color.green(pix);
b = Color.blue(pix);
r = g = b = (int) (gs_blue*b +gs_green*g +gs_red*r);
//write out
bmOut.setPixel(x, y, Color.argb(a, r, g, b));
}
}
return bmOut;
}
public class GreyBitmaps implements Runnable{
Thread t = null;
boolean isActive = false;
public void run() {
Log.d("Runnable", "running");
//num_ = 100;
while(isActive) {
Log.d("Runnable", "running2");
num_ = 200;
setBitmap();
try {
Thread.sleep(100);
if (makeGrey_) {
goGrey(bMap1_);
goGrey(bMap2_);
goGrey(bMap3_);
goGrey(bMap4_);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void pause(){
isActive = false;
while(true){
try{
t.join();
}catch (InterruptedException e) {
e.printStackTrace();
Log.e("Error", "Failed to join thread");
}
break;
}
t = null;
}
public void resume(){
isActive = true;
t = new Thread(this);
t.start();
}
}
}