I recently came across the deprecation of clipRect(Rect,Region.Op), which I would like to use with DIFFERENCE. This was replaced with clipOutRect(Rect) and thus I implemented:
#Suppress("DEPRECATION")
fun clipOutRect(canvas: Canvas, rect: Rect) =
if (SDK_INT >= O) canvas.clipOutRect(rect)
else canvas.clipRect(rect, DIFFERENCE)
Now this looks like it could be a compatibility method in AndroidX, but for some reason I was not able to figure out, where I could find it exactly.
Is there a class already providing a compatibility method for clipOutRect(Rect)?
Short answer is - no. The only thing related to Canvas in AndroidX is this file: https://github.com/aosp-mirror/platform_frameworks_support/blob/androidx-master-dev/core/core-ktx/src/main/java/androidx/core/graphics/Canvas.kt
Long answer.
First of all, Canvas is passed to view by native code, so it will be awkward to have something like onDrawCompat(canvas: CanvasCompat) in ViewCompat class. And I think there is no reason to do that at all.
Also, it's really not that type of deprecation you should worry about.
For example WifiManager.startScan() is noted with
This method was deprecated in API level 28. The ability for apps to
trigger scan requests will be removed in a future release.
That says Change this code now, or it will be broken year later
That not the case with clipRect, it will be kept for backward compatibility with apps that won't be ever updated for years or even tenth of years. Deprecation warning for this is just like Hey, we have new method with better functionality/name, if you target minimum is API 26 you can use that
Related
I have read the dozens of questions here on SO regarding recycling TypedArrays, but I guess they are a bit too old and written before we could widely use try-with-resource statements, so none of them talk about using the AutoCloseable implementation of the TypedArray, which is present since API Level 31
So the question remains: is this a false positive in Lint?
If anything, that warning should be a minSDK warning if applicable, right?
Can we simply write the following since the full try-with support (if we do it after SDK Level >= 31 check)?
try (TypedArray array = getContext().obtainStyledAttributes(attrs) {
// Do someting
}
// End of method
My guess is yes, as this is the AutoCloseable implementation of TypedArray
So the question remains: is this a false positive in Lint?
No, it is not. Because close method in AutoCloseable interface is not magically called when using try/catch.
Instead you have to use use method and then and only then you can get rid of try/catch like following:
getContext().obtainStyledAttributes(attrs).use({
// Do something
});
But, be aware that use method from TypedArray class is available only since Android 31
If you prefer a backwards compatible solution, you can use use method from androidx.core:core-ktx library.
As TypedArray also provides of a use method you will have to take care of adding the following import:
import androidx.core.content.res.use
I wonder if it's possible to implement multiple methods to support different API levels and call the right one without if(android.os.Build.VERSION.SDK_INT >= ...) else if...?
I want to use android platform's newer features like streams etc. and still support backwards.
Example:
wrote a method
public void myMethod24() {
// some logic requires api level N(24) and above
}
but my app supports lower apis, so i need another method that's compatible with them.
here is a method compatible for older versions:
public void myMethod21() {
// the same logic, requires api level LOLLIPOP(21) and above
}
How to use the correct method for current running version without doing this ugly if else:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
myMethod24();
} else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
myMethod21();
}
Maybe annotate my methods with #RequiresApi(), #TargetApi or something else..?
i saw this question but the answer there is with if else.
How to use the correct method for current running version without doing this ugly if else
You can't. Somewhere, something needs to do the version check and route to the appropriate logic.
Maybe annotate my methods with #RequiresApi(), #TargetApi or something else..?
Those are there to help advise the compiler that you know what you are doing. They do not code-generate the version comparisons.
Depending on what you are doing, existing ...Compat classes might handle the version checks for you (e.g., NotificationCompat.Builder). If you were using Kotlin, we could come up with some funky code that hides the if checks. And there might be a third-party library that offers some annotation-based code generator that code-generates the if checks.
So I just had to up my min API level to 11 for the Preference (addpreferenceresource was depreciated) - turns out 9-10 takes out like 50% of the market. So my question is, is it better to just suppress the warning to cater to the Gingerbread market or is there a different way to make my preference reference without using Preference Fragments?
I would implement both types (the one that works in 11+ and the one that works in 10-), then use conditional checks for them. This is written in quite a bit of detail in this answer.
Basically, you end up setting up OtherPreferencesActivity with PreferenceFragment, and then PreferencesActivity with the deprecated PreferenceActivity. (Your APK will not break by including this deprecated code, as long as you use a version check so that if/when it's removed in the future, it doesn't try to find it.)
if (Build.VERSION.SDK_INT < 11) {
startActivity(new Intent(this, PreferencesActivity.class);
} else {
startActivity(new Intent(this, OtherPreferencesActivity.class);
}
Keep in mind, you will want to have them use each others' methods as much as possible so that you don't end up duplicating code.
Last tip: #TargetApi(11) and #SuppressWarnings("deprecation") will come in handy here. Just be careful that you're not ignoring other deprecations by doing so.
"depreciated" doesn't mean you can't use it and will break your system if you run the code. It means that it is officially not recommended to use and this method maybe removed from the api. In the future but we don't know when. So I would say it is save to use in this case for now.
I have issues in my app regarding StrictMode and added the code snippet that basically disables the StrictModeHelper. However, Lint complains about setThreadPolicy() now and proposes to either add
#SuppressLint 'NewApi'
or
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
to the onCreate() event of the view.
Which method is prefered ..or are they basically doing the same?
I have issues in my app regarding StrictMode and added the code snippet that basically disables the StrictModeHelper
Please fix the networking bug.
Which method is prefered ..or are they basically doing the same?
#TargetApi and #SuppressLint have the same core effect: they suppress the Lint error.
The difference is that with #TargetApi, you declare, via the parameter, what API level you have addressed in your code, so that the error can pop up again if you later modify the method to try referencing something newer than the API level cited in #TargetApi.
For example, suppose that, instead of blocking the StrictMode complaints about your networking bug, you were trying to work around the issue of AsyncTask being serialized on newer versions of Android. You have a method like this in your code to opt into the thread pool on newer devices and use the default multithread behavior on older devices:
#TargetApi(11)
static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task,
T... params) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}
else {
task.execute(params);
}
}
Having #TargetApi(11) means that if Lint detects that I am using something newer than my android:minSdkVersion, but up to API Level 11, Lint will not complain. In this case, that works. If, however, I modified this method to reference something that wasn't added until API Level 14, then the Lint error would appear again, because my #TargetApi(11) annotation says that I only fixed the code to work on API Level 11 and below above, not API Level 14 and below above.
Using #SuppressLint('NewApi'), I would lose the Lint error for any API level, regardless of what my code references and what my code is set up to handle.
Hence, #TargetApi is the preferred annotation, as it allows you to tell the build tools "OK, I fixed this category of problems" in a more fine-grained fashion.
How can i call perspectiveM static method in Matrix class?
As said here:
http://developer.android.com/reference/android/opengl/Matrix.html
Сode completion suggests me frustumM, invertM, length, multiplyMM, multiplyMV, orthoM and others and no perspectiveM.
Details that could be important: last eclipse and java, android 2.3 as target, last sdk updates.
p.s. i know that i can tune matrix manually. it's just really interesting where method is.
The method is api lvl 14. If you scroll down to perspectiveM on the page you linked, you'll see in faint grey writing the api level where the method was included from: