The bounty expires in 14 hours. Answers to this question are eligible for a +50 reputation bounty.
km11 wants to draw more attention to this question:
Should not experience any more crashes with the proposed changes
In my latest release, I suddenly started getting this error: Resources$NotFoundException: Resource ID #0x7f080120. The resource ID is my notification icon, which is used in one of the tabs in a ViewPager, which is displayed at startup. I am not able to reproduce the issue myself, but see a lot of new crashes in Firebase Crashlytics.
The notification icon is stored in multiple densities:
The code that causes the crash:
ContextCompat.getDrawable(context, R.drawable.ic_notification_icon)
The weird thing is that I did not change anything related to this drawable or the code in the ViewPager in this release. The best suggestion I found from searching around, was to clean and rebuild the project. I did this and uploaded a new version, but the crash reappeared.
The crash is observed on the following Android versions:
Android 13
Android 11
Android 8.1.0
Android 7.1.2
And the following devices:
Galaxy A53 5G
Nexus 5X
Standard PC (i440FX + PIIX, 1996)
vivo S1
OnePlus8Pro
Mi 9x
Edit:
I can see that 44% of the affected devices are rooted. Does it mean I should not worry about the issue?
We are too facing this kinda of error a lot in our app. So,By doing little bit of search, I am changing ContextCompat to AppCompatResources to get the drawables. I seriously don't know now yet it will be beneficial for our app or not but reason to change is simply because the way ContextCompat returns result with respect to the way the AppCompatResources returns result. ContextCompat is just calling context's getDrawable method which in turn calls Resource's getDrawable method which in turn calls ResourceImpl getValueForDensity method and finally calling a native method. Whereas AppCompatResources calls AppCompatDrawableManager's getDrawable method which try different approaches to get the drawable and eventually fallback to ContextCompat if none of the approaches work. This seems to be better candidate for me get the drawable.
AppCompatDrawableManager's getDrawable method
public Drawable getDrawable(#NonNull Context context, #DrawableRes int resId,
boolean failIfNotKnown) {
checkVectorDrawableSetup(context);
Drawable drawable = loadDrawableFromDelegates(context, resId);
if (drawable == null) {
drawable = createDrawableIfNeeded(context, resId);
}
if (drawable == null) {
drawable = ContextCompat.getDrawable(context, resId);
}
if (drawable != null) {
// Tint it if needed
drawable = tintDrawable(context, resId, failIfNotKnown, drawable);
}
if (drawable != null) {
// See if we need to 'fix' the drawable
DrawableUtils.fixDrawable(drawable);
}
return drawable;
}
This answer also has useful information too.
ContextCompat is creating the issue
use it directly
getDrawable(context, R.drawable.ic_notification_icon)
Related
Getting,
no method with name='setBackground' signature
or
no method with name='setBackground'
upon changing .Background property (to change the background visuals) in the app running on legacy Android versions (<4.1)
Any ideas on how to fix this?
As this question about Eclipse suggests, setBackground is problematic on API below level 16. Unlike covered in the question though, to work around the issue AND have your code Android 4.0-compatible, you'd want to change your background with the following (reproducible logic)
if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.JellyBean)
{
layout.SetBackgroundDrawable(gd);
}
else
{
layout.Background = gd;
}
I'm using following function to enable and disable drawables...
public static void setDrawableState(Drawable d, boolean enabled)
{
if (d == null)
return;
d.mutate(); // so drawables don't share state anymore
if (enabled)
d.setAlpha(255);
else
d.setAlpha(100);
}
This worked on all phones I've tried yet, now I see it does not seem to work on android 4.4.2 (maybe it's not even version specific).
Is there another (better) way to set the alpha of a drawable? Or am I'm missing something?
Because drawables might share the same state, changing the drawable state will not have any effect. You need to mutate the drawable, for example in your code, try something like:
d.mutate().setAlpha(100);
Android developer Blogs has a great blog post explaining more on drawable state and mutations.
in case you wanna be really sure:
Drawable d2 = d.getConstantState().newDrawable().mutate();
d2.setAlpha(100)
As part of an app I'm working on, I'm attempting to obtain a reference to the ActionBar's container view. I used the answer from this question, and it's working nicely for me as long as the Android device in question is running API level 11 or up. However, the app needs to work as far back as API level 9 (the target API level is 19), and Gingerbread devices are giving me problems. I was originally using Sherlock for the project, but recently made the switch over to the v7 compat library instead. I can see and interact with the action bar in normal ways on Gingerbread devices (buttons work, etc.), but it fails when I attempt to get the container. The code I'm using is this (note - it's running inside a subclass of ActionBarActivity):
private FrameLayout getActionBarContainer() {
FrameLayout result = null;
int resId = getResources().getIdentifier("action_bar_container", "id", "android");
try {
result = (FrameLayout)getWindow().getDecorView().findViewById(resId);
}
catch (Exception e) {
// If we get an exception, just eat it
}
return result;
}
To answer a few questions before they get asked:
resId resolves to a proper ID value on v11 devices and up, but resolves to 0 on pre-v11 devices.
The code that uses this has proper checks to handle a null result, which is why I'm just eating the exceptions. The try/catch block is mostly just there in case, by some freak occurrence, a ClassCastException manages to get thrown (which it never should, since the container is a subclass of FrameLayout).
I've checked and re-checked my imports; all of my ActionBar references (and all things related, like the ActionBarActivity superclass I'm extending) are the v7 compat library versions, not the standard library versions.
The action_bar_container ID should exist within the v7 compat library, if this is any indication.
I'm about out of ideas at this point. Is there something simple I'm missing? Any suggestions will be appreciated, and if you need more context/clarification, let me know.
I think your error is on the last parameter of
int resId = getResources().getIdentifier("action_bar_container", "id", "android");
For api level <11 the package should be your application's package and not the plataform's package "android"
I have a button that I want to set the background of using a png file from internal storage. For android api 16 and up, this works fine:
filePath = getActivity().getFileStreamPath(colorCodes.get(i-1));
temp.setBackground(Drawable.createFromPath(filePath.toString()));
When running on an android tablet with 4.0.4, this part crashes the app with a nosuchmethod error (setBackground). After a little research, I see that setBackground is only available for api 16+. After looking around on SO and a few other places, it looks like I need to use setBackgroundDrawable (deprecated) or setBackgroundResource. I tried this:
filePath = getActivity().getFileStreamPath(colorCodes.get(i-1));
if (android.os.Build.VERSION.SDK_INT < 16) {
temp.setBackgroundDrawable(Drawable.createFromPath(filePath.toString()));
} else {
temp.setBackground(Drawable.createFromPath(filePath.toString()));
}
When logging it out, it shows that setBackgroundDrawable is running and not setBackground, but I get the same nosuchmethod error (setBackground).
The other option is setBackgroundResource, but it accepts an int and not a drawable. Can I convert from drawable to int for this purpose?
What can I do here to set the background of the button to a file in internal storage for APIs < 16?
Thanks.
***EDIT - ok, this is working. just missed a little part elsewhere in the code that had the same problem. However, is using a deprecated method really the only way?
Deprecation is a status applied to a computer software feature,
characteristic, or practice indicating it should be avoided, typically
because of it being superseded. The term is also sometimes used for a
feature, design, or practice that is permitted but no longer
recommended in other areas, such as hardware design or compliance to
building codes. (source link)
Now we can answer your question.
Before API level 16 there is a method named setBackgroundDrawable. After API Level 16 google decided to write a new method setBackground for same purpose and recommend us to use new method. (Reason of this may be found by googling.)
You can use setBackgroundDrawable method for all api levels. There aren't any constraint for this. But using new method setBackground is recommended after API Level 16.
But you can only use setBackground method for devices which is running on API Level 16 or higher. So if you only implement setBackground method in your code, you are going to get MethodNotFoundException for devices which run below API Level 16.
To sum up; it is a best practice(for me it is a must) to use new methods then deprecated ones with supportted api version check such as;
if (android.os.Build.VERSION.SDK_INT < 16) {
temp.setBackgroundDrawable(Drawable.createFromPath(filePath.toString()));
} else {
temp.setBackground(Drawable.createFromPath(filePath.toString()));
}
I am not quite sure whether it is the only way to achieve this but in my opinion it is the correct one. Because the annotation #Deprecated defines the method to be superseded (in most cases) it automatically implies you can (I would even say should) use it to address older versions which are the targeted versions of this method.
I'm trying to set a DropDown Background Color for a autocompleteTextView, because the standart Values seem to be different during different Android Versions. For example, everything works fine starting with android 3.2, but previous Versions seem to not accept the android:textColor="#color/black" in the xml, cause it is not working for me. Android 2.3 for example just shows the items in the list and the ones I picked in white, which isn't working for me, cause the background is white too. So I decided to change the background Color determing on the android version using this:
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB){
// Do something for Honeycomb and above versions
//everything is right
} else{
// do something for phones running an SDK before froyo
box_Kurs.setDropDownBackgroundResource(Color.BLUE);
box_Teacher.setDropDownBackgroundResource(Color.BLUE);
}
But when I start my app it crashes and shows resource not found exception:
11-19 15:40:17.225: E/AndroidRuntime(450): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.shr.khg/com.shr.khg.AddActivity}: android.content.res.Resources$NotFoundException: Resource ID #0xff0000ff
What am I doing wrong? I alread cleaned my project since that what other people suggested. Or is there any easier way to deal with my issue?
Thank you!
The problem is that the setDropDownBackgroundResource() is expecting the id of the Color resource Drawable, not an int that defines a Color. If you look at the Exception you can see that Android is trying to find a component with id #0xff0000ff, this is the hex code for a completely opaque blue which is the value of Color.BLUE
Replce these two lines:
box_Kurs.setDropDownBackgroundResource(Color.parseColor("#0000ff"));
box_Teacher.setDropDownBackgroundResource(Color.parseColor("#0000ff"));