I use a version switch to support older Android versions.
int sdk = Build.VERSION.SDK_INT;
if (sdk < Build.VERSION_CODES.HONEYCOMB) {
ColorDrawable colorDrawable = new ColorDrawable(shapeColor);
//noinspection deprecation
viewHolder.shape.setBackgroundDrawable(colorDrawable);
} else {
viewHolder.shape.setColor(shapeColor);
}
When build the project with Gradle from the command line the following warning is output by Lint:
app/src/main/java/com/example/MyApp/CustomListAdapter.java:92: warning:
[deprecation] setBackgroundDrawable(Drawable) in View has been deprecated
viewHolder.shape.setBackgroundDrawable(colorDrawable);
^
Can I annotate the specific line or method to mute the warning (since I do it on purpose)? I do not want to disable all warnings.
Case is important, use the following either inline or class-wide:
#Suppress("DEPRECATION")
This is in Kotlin.
I've noticed that the #SuppressLint("deprecated") inline annotation won't be picked up anymore - while #SuppressWarnings("deprecation") is being picked up.
one can disable the Deprecation checks for the Gradle linter with lintOptions within the module-level build.gradle file; while there is no chance to define individual files like that:
android {
lintOptions {
disable 'Deprecation'
}
}
or on can assign one rather detailed lint.xml configuration file with LintOptions:lintConfig (when settings showAll true, it will still show the warnings - no matter the provided XML configuration):
android {
lintOptions {
lintConfig file("lint.xml")
showAll false
}
}
where one can add individual files, by adding their paths:
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="Deprecation" severity="Error">
<ignore path="app/src/main/java/com/example/MyApp/CustomListAdapter.java" />
</issue>
</lint>
The source code of com.android.builder.model.LintOptions might explain, what actually happens there (and confirms about 50% of what I've wrote).
in order to get rid of the inline warnings in Android Studio... that linter appears to be another linter - and these annotations do not affect the linter of the Gradle build (it may be required to use this combined with one of the methods stated above, in order to ignore known deprecated classes and methods):
//noinspection deprecation
update The Android Studio 2.3 release notes mention a new feature:
Lint Baseline: With Android Studio 2.3, you can set unresolved lint warnings as a baseline in your project. From that point forward, Lint will report only new issues. This is helpful if you have many legacy lint issues in your app, but just want to focus on fixing new issues. Learn more about Lint baseline and the new Lint checks & annotations added in this release.
here it's explained, how to create a Lint warnings baseline - which records the detected warnings into an XML file and then mutes them (which is way better than to have the code annotations inline, distributed all over the place); I'd assume, that options lintConfig and baseline should be combine-able (depending on the requirements).
android {
lintOptions {
baseline file("lint-baseline.xml")
}
}
Just something new: Not sure about Android Studio, but, to remove this warning from this line, you can use:
//noinspection deprecation
This removes the warning from the next line.
E.g:
//noinspection deprecation
e.setBackgroundDrawable(editTextDrawable);
It won't show an error. However, as #JJD said, this still outputs the warning to the console. But at least you can have a nice error-less code which can be useful like for Git for example. And, this prevents the problem with #SupressWarnings, which is it ignores all warnings in the method. So if you have something deprecated that you are not aware of, #SupressWarnings will hide it and you will not be warned. That is the advantage of the //noinspection
I ran into a similar problem. First I got a compiler warning:
:compileDebugJava
Note: /path/file.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Which you can suppress with #SuppressWarnings("deprecation") or just ignore since it is a warning and does cause your build to fail.
Additionally I got the lint error (details in build/lint-results.html):
Call requires API level 13 (current min is 9)
This could be suppressed by adding #SuppressLint("NewApi"). Alternatively you could use #TargetApi(13) to hint that the method/class may use methods that depend on API version 13, rather than what you have set as minSdkVersion (e.g. 9).
The annotations can only be done at a class or function level, not for a single line. Also note that "deprecation" should not be capitalized, while that didn't seem to matter for "NewApi".
To avoid lint warnings, always split functions so one function deals with the old system and other one deals with the new system. The old can supress the warning safely. The new one should be annotated to be used only on newest api levels.
This is an example on how it should look:
#SuppressWarnings("deprecation")
private static int getVersionCode_old(#NonNull Context appContext) {
PackageInfo pInfo;
try {
pInfo = appContext.getPackageManager().getPackageInfo(appContext.getPackageName(), 0);
return pInfo.versionCode;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
#RequiresApi(api = Build.VERSION_CODES.P)
private static int getVersionCode_new(#NonNull Context appContext) {
PackageInfo pInfo ;
try {
pInfo = appContext.getPackageManager().getPackageInfo(appContext.getPackageName(), 0);
return (int) pInfo.getLongVersionCode();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public static int getVersionCodeUniversal(#NonNull Context appContext)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return getVersionCode_new(appContext);
}
else
{
return getVersionCode_old(appContext);
}
}
Another important hint to avoid lint warnings: if you are using a whole deprecated class then you should remove all explicit imports for that class. Then just access to that class directly using its full path, and only do it in the old versions of your functions.
And finally, you should consider start using androidX, the new Google libraries where you will find a lot of universal functions ready to use. Then you can save a lot of time with this kind of small problems. For example, you can remove all the code of the above example and simply use this new and universal androidX function:
PackageInfo.getLongVersionCode()
You need to create a lint.xml file to tell lint what to ignore.
http://tools.android.com/tips/lint/suppressing-lint-warnings see this for more details
yours might look a little like this
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<!-- Disable the given check in this project -->
<issue id="Deprecation">
<ignore path="app/src/main/java/com/example/MyApp/CustomListAdapter.java" />
</issue>
</lint>
To handle this in the source you should use something like
#SuppressLint("Deprecation")
Just use #SuppressWarnings("deprecation") above the function to suppress that specific warning for that function only.
Works like a charm!
#Blackd has the better answer. You should accept that!
Try to find a method from ViewCompat to replace the deprecated method.
In your case, use ViewCompat.setBackground(View, Drawable).
There are many classes named XXXCompat for cases like that, such as ContextCompat, ActivityCompat and so on.
Related
I am working on a project with minSdkVersion set to 25 (aka Android 7.1).
Since this version is quite high, there are a lot of methods I can use without worrying about backward compatibility.
For example, retrieving a drawable, from a Fragment, should be as simple as:
context?.getDrawable(R.drawable.my_drawable)
In the source code, what it does is:
return getResources().getDrawable(id, getTheme());
As far as I am concerned, such a method was introduced in API 21 (Android 5.0).
However, I get the following warning:
Looking at the source code of ContextCompat.getDrawable(...):
if (Build.VERSION.SDK_INT >= 21) {
return context.getDrawable(id);
} else if (Build.VERSION.SDK_INT >= 16) {
return context.getResources().getDrawable(id);
} else { ... }
Since the min SDK is set to 25, the first if will always be called, which then the same code I have written. So why the warning?
I could suppress it with the #SuppressLint("UseCompatLoadingForDrawables") but it kinds of defeat the purpose... or I could follow it...
Is this normal? Should I really use ContextCompat and its affiliates or is there a setting somewhere to remove such a false warning?
PS: the project is also using Android X.
Ran into the same issue. I would say it is a false positive when you have a minSdk >= 21. Since as you say you will always enter the if branch which calls getDrawable.
So suppressing/ignoring it is the way to go until someone can make the lint rule smart enough to detect that you are on minSdkVersion higher than 21. You can ignore it globally by doing this in your build.gradle:
android {
...
lintOptions {
ignore("UseCompatLoadingForDrawables")
}
}
Interestingly context.getColor(R.color.something) does not give a similar warning even though it has similar code in ContextCompat.getColor.
I am trying to implement custom lint checks (using Kotlin). I have set up a module for my custom checks and added classes to test my first lew lint check, mostly following these two tutorials here and here.
So I now have a module, I have a custom IssueRegistry, I've created an issue and a Detector class for it. So far it seems complete. I've added a test to check if my lint check works and it looks alright.
I have added my module to the project by referencing it in settings.gradle like this: include ':app', ':somemodule', ':mylintmodule'
Now if I run the linter using ./gradlew lint I get a lint result file telling me this:
Lint found an issue registry (com.myproject.mylintmodule) which requires a newer API level. That means that the custom lint checks are intended for a newer lint version; please upgrade
Lint can be extended with "custom checks": additional checks implemented by developers and libraries to for example enforce specific API usages required by a library or a company coding style guideline.
The Lint APIs are not yet stable, so these checks may either cause a performance degradation, or stop working, or provide wrong results.
This warning flags custom lint checks that are found to be using obsolete APIs and will need to be updated to run in the current lint environment.
It may also flag issues found to be using a newer version of the API, meaning that you need to use a newer version of lint (or Android Studio or Gradle plugin etc) to work with these checks.
To suppress this error, use the issue id "ObsoleteLintCustomCheck" as explained in the Suppressing Warnings and Errors section.
So it tells me that I am using a newer API verion in my custom lint check, right? This is my custom IssueRegistry (minus some parts not relevant for this problem):
class MyCustomIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
get() = listOf(ISSUE_NAMING_PATTERN)
override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
override val minApi: Int = 1
}
From googling this problem and finding this issue I figured I have to override and set the right API version (and maybe the min API?) by overriding these properties like I did above (this version is my last attempt, directly taken from that issue).
So this property can be set to values between -1 and 5, meaning this (taken right out of the lint.detector.api class):
/** Describes the given API level */
fun describeApi(api: Int): String {
return when (api) {
5 -> "3.5+" // 3.5.0-alpha07
4 -> "3.4" // 3.4.0-alpha03
3 -> "3.3" // 3.3.0-alpha12
2 -> "3.2" // 3.2.0-alpha07
1 -> "3.1" // Initial; 3.1.0-alpha4
0 -> "3.0 and older"
-1 -> "Not specified"
else -> "Future: $api"
}
I have tried all of them, plus the one above adding a minApi override too, and I keep getting the exact same result for each of them.
Also I am unable to locate what other API version this is compared with. Is there a place where this is set for the regular linter in an Android project?
It's also unclear to me what I have to do to make sure my changes got applied - is it enough to change some code, then run lint, or do I have to compile the project first, or build & clean?
Following the tutorials, I added my custom lint check by adding this to the app's build.gradle: lintChecks project(":mylintmodule")
Is that even right? The API issue on my registry class shows up no matter if my lint check is referenced (and hopefully used) like that or not. I have also tried the other method described in the first tutorial, adding this task to the linter module build.gradle:
defaultTasks 'assemble'
task copyLintJar(type: Copy) {
description = 'Copies the lint jar file into the {user.home}/.android/lint folder.'
from('build/libs/')
into(System.getProperty("user.home") + '/.android/lint')
include("*.jar")
}
// Runs the copyLintJar task after build has completed.
build.finalizedBy(copyLintJar)
But since I can't figure out how to see if my custom checks are actually run, I don't know if that works as intended either.
So how do I get this warning resolved (since I interpret the text as "As long as the versions don't match I will not try to run your lint check"), and how can I make sure my lint check is actually run by the linter?
I am trying to make my continuous integration fail the build when new lint warnings that aren't in the lint-baseline.xml file are introduced. I want to have all lint warnings treated as errors (so the build is aborted), but I'd like a way to specify certain lint checks to be treated as informational or warning level so that they still appear in the lint results, but don't cause the build to be aborted.
Here is an example of basically what I'd like to do (except this doesn't work, the build fails if any non-ignored warnings exist):
lintOptions {
lintConfig file("lint.xml")
baseline file("lint-baseline.xml")
checkAllWarnings true
warningsAsErrors true
abortOnError true
informational 'MissingTranslation, ...' // don't fail the build for these
}
Is there an easy way to treat all lint checks as errors, excluding certain ones? I thought about manually setting all 200+ lint checks to the error level, but that wouldn't be very future proof, since I'd have to update the list every time new lint checks were added.
You should be able to achieve what you want if you do not use the Gradle lintOptions (checkAllWarnings, warningsAsErrors, etc.) to configure which warnings should be treated as errors. Use lint.xml instead. There you can do the following:
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="MissingTranslation" severity="warning" />
<!-- The following must be at the bottom of your file!
All lint issues (not listed above) will be treated as errors. -->
<issue id="all" severity="error" />
</lint>
In my tests this seemed to work fine and all warnings were treated as errors except for those listed at the top of the lint.xml.
However, I've not tested it in combination with a lint-baseline.xml but I see no reason why it shouldn't work there as well.
For me, this configuration worked:
android {
lintOptions {
warningsAsErrors true
warning 'MissingTranslation', ...
}
}
It seems the options are evaluated in the "correct order" (aka "as I need it"), i.e. first all warnings are elevated to errors, then this settings is overriden again for a single issue id. Using warning instead of disable or ignore ensures the issues are still visible in the report or the IDE.
It doesnt seem informational is a real option from this doc, I suggest:
android {
lintOptions {
checkAllWarnings true
warningsAsErrors true
// use this line to check all rules except those listed
disable 'MissingTranslation', ...
//OR this line to check but not worry about result (i think this is what you want)
ignore 'MissingTranslation', ...
}
}
I am trying to add a following code.
if (Config.DEBUG) {
// do something
} else {
// do something
}
I realized that Config.DEBUG is deprecated in API 14. What is the alternative if it?
You could use:
if(BuildConfig.DEBUG){
// do something
}else{
// do something
}
It's not really documented anywhere but seems to work in both eclipse and Android Studio (latest versions respectively).
Returns true if the current build is a debug build and false if it's an release. Since it's not documented anywhere be wary of using it in production code since it may be stripped at any time (and there are reports of incorrectly attributing releases to debug builds).
i have a question regarding development environments settings.
i am trying to see if there is any possibility to make a compilation warning in a development environment(eclipse,android studio)for android applications using a deprecated feature(could be a method , constructor or whatever you can think of ). until now i am working manually to find the use of this deprecated features , and my boss asked me to look for an automatic settings in my idea ...
so lets say for a specific code :
protected void onPrepareDialog(int paramInt, Dialog paramDialog)
{
try
{
super.onPrepareDialog(paramInt, paramDialog);
AlertDialog localAlertDialog = (AlertDialog)paramDialog;
localAlertDialog.setTitle("Passphrase required");
((TextView)localAlertDialog.findViewById(2131230727)).setText(Preferences.getConfigName(this, getConfigFile()));
Button localButton = localAlertDialog.getButton(-3);
if (this.mOpenVpnService != null);
for (boolean bool = true; ; bool = false)
{
localButton.setEnabled(bool);
return;
}
i have several deprecated features here , and android studio declares it , but what i need is a configuration for this warning to be automated and save me the need of walking through each class manually ...
Select Analyze > Inspect Code to run lint on your project. It should detect any deprecated methods, as well as others common mistakes in your project.
You can select "Run inspection by name" and there you can find "Deprecated API usage" (Java / Code maturity issues).
For me the best solution is add this lines in the file build.gradle(project:appname)
allprojects {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
Then all the deprecated methods in the java files appear in the build tab:
deprecated api tab android studio
This works on gradle 5.1.1