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.
Related
Button setTextAppearance(Context context, int resid) is deprecated
and setTextAppearance(int resid) - only available for API level 23
What should I use instead?
Deprecated means that support will be dropped for it sometimes in the future, but it is still working as expected. On older APIs, there is no alternative, since the new setTextAppearance(int resid) got only released with API level 23.
If you want to be safe for a long time, you can use the following code:
if (Build.VERSION.SDK_INT < 23) {
yourButton.setTextAppearance(context, resid);
} else {
yourButton.setTextAppearance(resid);
}
This code prefers the new version on phones with API level 23 or higher, but uses the old one when the API level 23 one isn't available.
I am going to say the same this as #Daniel Zolnai. But do not make the check Build.VERSION>SDK_INT < 23 in all the places in your code. Put this in one place, so it will be easy for you to remove this in the future or make changes to it. So how to do it? I will do this for the yourButton case.
Never use Button or any other view provided by android just like that. I say this, because in the future you will need to tweak something and hence it's better to have your own MyButton or something of that sort. So create MyButton extends Button.
Inside MyButton, put the below code:
public void setTextAppearance(Context context, int resId) {
if (Build.VERSION.SDK_INT < 23) {
super.setTextAppearance(context, resId);
} else {
super.setTextAppearance(resId);
}
}
This way you can always use setTextAppearance without needing to worry about checking for BUILD versions. If in future, you plan to remove this whole thing, then you have to refactor in just one place. This is a bit of work, but in the long run, this will help you a lot and will reduce some maintanance nightmares.
After testing my app on Android 5.0, I noticed that image.setAlpha() is not working on this Android version.
I tried with image.setImagealpha() function, but it returns this error:
"The method setImageAlpha(int) is undefined for the type Drawable"
The API level that I´m using on my app is 8
What can I do?
Update 2019:
With kotlin now we can do it like this:
imageView.post {imageView.alpha = 1.0f}
I have used View.post so that it get updated on immediate next UI updation cycle.
Without posting on UI thread sometimes setting alpha of TextViews doesn't reflect on UI as discussed here
ImageView has the method setAlpha(float) after API 11. Before API 11 it uses setAlpha(int). Since you want to support API 8 and above, you have to specify the different states. So to resolve this, use the following code:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
//For API 11 and above use a float such as 0.54.(54% transparency)
imageView.setAlpha(float);
}
else
//For API Below 11 use an int such as 54.
imageView.setAlpha(int);
I have my app that requires SDK 9+ with code containing setBackgroundDrawable() which is API level 16. I did not get any error while coding or building the apk. but I got about 50 reports of this error happening in google analytics and a few reports in my developers console.
When I run the lint checker It also doesn't warn me. I am using eclipse. Is there a reason why it doesn't fail to compile like usually when you add a method that's not supported by the minimum API or is it simply an eclipse bug?
First of all you get no error when building since you probably are building with SDK 16+ and the method is there. But if you install the apk to a 2.1 Android phone it will throw a MethodNotFound Exception. So in the future ALWAYS install your apk on a min-target device to see if you didn't forget something. Min-Target basically is only a filter for the PLAY store (and for lint warnings, etc.)
AFAIK moving from imageView.setBackground(...) to imageView.setBackgroundDrawable(...) was just an api style design choice. So if you look at the source of Android SDK 18 you will see:
/**
* Set the background to a given Drawable, or remove the background. If the
* background has padding, this View's padding is set to the background's
* padding. However, when a background is removed, this View's padding isn't
* touched. If setting the padding is desired, please use
* {#link #setPadding(int, int, int, int)}.
*
* #param background The Drawable to use as the background, or null to remove the
* background
*/
public void setBackground(Drawable background) {
//noinspection deprecation
setBackgroundDrawable(background);
}
So for now its absolutely irrelevant if you use one or the other - but of course this COULD change (but it's unlikely it does in the future since it would break nearly every app done before SDK 16) - basically it's fine to use setBackground() even on SDK 18+
So if you want to be on the future-proof but ugly side you could use a version fork depicted by the other answers
if(Build.VERSION.SDK_INT >= 16) {
//new code
} else {
//deprecated code
}
Just one thing, and maybe this is a personal style preference, I would not suppress Lint warnings with annotations like this:
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
I like to keep the warnings since maybe later if I want to refactor/move to higher SDK I could easily get rid of these ugly switches.
Update:
Google's v4 support library contains helper classes for sdk boiler plate code. In this instance you would use:
ViewCompat.setBackground(view,drawable);
which handles the SDK check for you.
Seems to be a bug in eclipse or your eclipse is not working perfectly. But you can try project clean and try. But code wise you can try something like this:
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
public void setImage(ImageView imageView, BitmapDrawable bd) {
if(Build.VERSION.SDK_INT > 16) {
imageView.setBackground(bd);
} else {
imageView.setBackgroundDrawable(bd);
}
}
You can call this function along with ImageView and bitmap drawable.
Is there any kind of conditional compiling for Android?
I had to make my project for Android 3 (API 11) just because ExifInterface has almost no useful attributes in Android 2.3 (API 10), despite the fact that it appeared in API 5 (!!??). I don't want to restrict my app to ICS users.
Thanks!
You can check dynamically the current API version of the device and do different stuff depending on that:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
}
But be careful that if you need to instantiate classes that are not available for all APIs then you should do it in a runnable or in a separate wrapper class, e.g:
if(Build.VERSION.SDK_INT < 14) {
// Crappy stuff for old devices
}
else {
// Do awesome stuff on ICS
new Runnable() {
new AmazingClassAvailableOnICS();
(...)
}.run();
}
import android.annotation.TargetApi;
and then use annotations:
#TargetApi(11)
public void methodUsesAPI11()
{
...
Using this trick does a very simple thing: it allows compiling some code which contains API level 11 calls (classes, methods, etc) and still set android:minSdkVersion="8" in the manifest. Nothing more, nothing else.
The rest is up to you. You must check platform version before you call methodUsesAPI11() or you handle exceptions in order to prevent app crash and perform other action on older platforms.
Checking Build.VERSION.SDK_INT or using annotations should suffice, however, this link I'd bookmarked might be relevant to your case:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html?m=1
You can use what they describe there to have classes that may not be compatible, but will never be loaded. It's not conditional compilation, but it may be what you need, however, it is a bit more complex.
I want to get current alpha of textview i am using the following code but i am getting an error that
java.lang.NoSuchMethodError: android.widget.TextView.getAlpha
Please guide me.
This method since API Level 11. Check your API version.
View.getAlpha() only exists since API level 11. You are trying to running your code on a too-old version of Android.
If you absolutely require this functionality, then update your app's minSdkVersion in AndroidManifest.xml to prevent it running on older Android versions. If you can live without it, do a runtime check to see if the API level is high enough.
you can use Alpha method like below
Textview tv_password;
tv_password =(TextView) findviewById(R.id.tv1);
tv_password.getBackground().setAlpha(50);
you can't use getAlpha() method with Textview
View.getAlpha() available from API level 11.But if you want to use this on older api then you may use NineOldAndroids library available for using the Honeycomb (Android 3.0) animation API on all versions of the platform back to 1.0!
So use need to change for e.g.
mAlpha = mView.getAlpha();
to
mAlpha = ViewHelper.getAlpha(mView);
where mView is your view.
Note : Don't forget to import com.nineoldandroids.view.ViewHelper;