Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this not working sometimes?

TL;DR I have many buttons, and I am swapping the images of them. For some reason, my code only works on certain phones, and not on others.

My app uses the following code to compare images on imagebuttons:

onCreate:

redsquare = getResources().getDrawable(R.drawable.redsquare);
bitred = ((BitmapDrawable) redsquare).getBitmap();

onClick (v is the button clicked)

ClickGround = v.getBackground(); //Get the background of button clicked
//the bitmap background of the button clicked
BitClick = ((BitmapDrawable) ClickGround).getBitmap(); 

Then, later on in the onClick, I check if the user clicked on the redSquare by doing this:

if (BitClick == bitred) { //Make sure it is the red square that user clicked
}

I have tested it on my emulator and HUAWEI phone, and it works fine. When I tested it on my other phone (lg g3), the if statement doesn't go through. Why are the results different? Is the image somehow being messed up in my phone?

like image 576
Ruchir Baronia Avatar asked Jan 06 '16 04:01

Ruchir Baronia


People also ask

Why this app is not working?

Sometimes, the accumulated cache data of an app can cause it to stop working. When such a thing happens, you need to reset the cache data from the device settings. So, if individual Android apps are not working on your phone, another solution to fix it is by clearing the app's cached data.

Why sometimes Google is not working?

Users have to uninstall the updates before the app start functioning well again. And most times, Google apps not working on Android devices could result from a faulty Android System WebView or Google Play Services update. That is to say, the problem cannot be tied to particular reasons.

Why do some apps stop working?

One reason could be low memory or a weak chipset. Apps can also crash if they are not coded properly. Sometimes the reason could also be the custom skin on your Android phone.


3 Answers

First of all, Resources.getDrawable(int) is deprecated. It is probably not related to your problem, but you should fix it.

If you compare bitmaps using == you are comparing object identities. If the == test is giving you false, that means you are comparing different objects. There can be no doubt about that.

Your snippets don't give enough context to be sure, but here are some possibilities:

  1. Something in your code is causing a different value to be assigned to bitred.

  2. The bitred identifiers in the two snippets of code do not denote the same Java variable.

  3. Your assumption that the "red" bitmap that is being used as a red background will always be the same object is invalid.

Lets assume that you have already eliminated 1. and 2. above, and focus on 3. How could that happen? Well, we can't see the relevant code (where you randomly swap the button images) but I can think of a couple of possibilities:

  • You could be fetching the bitmap from Resources repeatedly.
  • The method you call to switch the bitmaps could be creating / setting a copy.
  • The method you call to get the clicked button's bitmap could be returning a copy.

And since each of the above operations could depend on API implementations that could behave differently (because the javadoc allows that) the behavior of your app can be platform dependent.


So what is the solution?

Hypothetically, if you can figure out what is causing different bitmap objects to be used, you could potentially work around it. However, while your code still relies on unspecified behavior, there is a risk that it will break on other phones ...

A better solution is to change your app so that DOES NOT rely on using == to compare Bitmap objects. For example:

  • Associate a tag with each button.

     button1.setTag("one");
     button2.setTag("two");
    
  • Create a HashMap that maps from a button's tag to the current color for that button. The HashMap is part of the app's "model" state.

    Map colors = new HashMap();
    ...
    colors.put("one", "red");
    colors.put("two", "blue");
    
  • When you change the image bitmaps for the buttons, make the corresponding update to the map.

    // After swap the images of button1 and button2 ...
    String c1 = colors.get("one");
    String c2 = colors.get("two");
    colors.put("one", c2);
    colors.put("two", c1);
    
  • In the onClick method, use the map to lookup the button's current color rather than attempting to figure it out by comparing Bitmap objects.

    if (colors.get(v.getTag()).equals("red")) {
        // it is red!
    }
    

(Note that this is close to what Biju Parvathy suggests, but he hasn't said explicitly how to deal with the button colors / images changing.)

like image 122
Stephen C Avatar answered Oct 24 '22 10:10

Stephen C


You Can, I'm making a small change in your comparison code to make it work with all devices.

Bitmap BitRed = ((BitmapDrawable)getResources().getDrawable(R.drawable.redsquare)).getBitmap();

Bitmap BitClick = ((BitmapDrawable) v.getBackground()).getBitmap();

if (BitClick.sameAs(BitRed)) 
{ 
    //Your Button with Red Square Clicked
}

Please refer SameAs function for more details. Hope this help you.

like image 7
Let'sRefactor Avatar answered Oct 24 '22 10:10

Let'sRefactor


First of all Resources.getDrawable(int) is deprecated , so you will surely get this kind of issues in some newer devices. Better approach is to use tags for your button for each drawable you gonna use for that specific button. For example, Consider you have 4 buttons i.e. button1, button2, button3 and button4. Now suppose initials they all have some defualt background.

Lets say,

button1.setBackgroundResource(R.drawable.default1);
button1.setTag(R.drawable.default1); // set the tag for button same as the drawable id

Do the same for all of your 4 buttons

button4.setBackgroundResource(R.drawable.default4);
button4.setTag(R.drawable.default4); // set the tag for button same as the drawable id

Now everytime when you change background/images for your buttons, you need to update the tag as well, something like this

button1.setBackgroundResource(R.drawable.redimage);
button1.setTag(R.drawable.redimage); // set the tag for button same as the drawable id

and on your buttons onClick(), you have to simply make use of a switch case to differentiate between different tags

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.button1:
        switch(button1.getTag()){
            case R.drawable.default1:
            // do whatever action you want to perform
            break;
            case R.drawable.redimage:
            // do whatever action you want to perform
            break;
        }
        break;
        // similarly you can do the same for rest of the buttons.
    }
}

Hope this helps.

like image 2
Mukesh Rana Avatar answered Oct 24 '22 10:10

Mukesh Rana