what is the use of #SuppressLint("InlinedApi") - android

I encountered #SuppressLint("InlinedApi") in some code i was going through and could not find out any description of it online. I understand #SuppressLint("NewApi") is used to hide warnings when we write code that is higher than the minsdk mentioned in the manifest. But i am not able to figure out when "InlinedApi" should be used. Any ideas?

By executing lint --list (the lint tool is located in your sdk/tools directory) you can see a list of the valid issue id's. You can find the explanation of InlinedApi there :
"InlinedApi": Finds inlined fields that may or may not work on older
platforms

Here's an example from a Google codelab:
#SuppressLint("InlinedApi")
private void hideSystemUi() {
mPlayerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
If you comment out the #SuppressLint("InlinedApi"), you get this lint warning:
Field requires API level 19 (current min is 16): android.view.View#SYSTEM_UI_FLAG_IMMERSIVE_STICKY
So you're accessing a field that may not exist in the API of some of the devices that you've said you want to be able to run the device on. In that case, why is it just a lint warning instead of a fatal compile error?
The fuller description for the warning is nice and informative. You can see it in Android Studio if you press the "More" key combo (e.g. Cmd+F1) when the lint message popup is open. You can also get it via lint on the command line, similar to what #stan0 said but in more detail:
lint --show InlinedApi
Here's the detailed explanation:
InlinedApi
----------
Summary: Using inlined constants on older versions
Priority: 6 / 10
Severity: Warning
Category: Correctness
This check scans through all the Android API field references in the
application and flags certain constants, such as static final integers
and Strings, which were introduced in later versions. These will
actually be copied into the class files rather than being referenced,
which means that the value is available even when running on older
devices. In some cases that's fine, and in other cases it can result
in a runtime crash or incorrect behavior. It depends on the context,
so consider the code carefully and decide whether it's safe and can be
suppressed or whether the code needs to be guarded. [emphasis added]
If you really want to use this API and don't need to support older
devices just set the minSdkVersion in your build.gradle or
AndroidManifest.xml files. If your code is deliberately accessing
newer APIs, and you have ensured (e.g. with conditional execution)
that this code will only ever be called on a supported platform, then
you can annotate your class or method with the #TargetApi annotation
specifying the local minimum SDK to apply, such as #TargetApi(11),
such that this check considers 11 rather than your manifest file's
minimum SDK as the required API level.
(source)
Hopefully with that explanation, it's clear why this is not a fatal error (because the value of the constant gets copied into the class file instead of a reference), why it's still potentially dangerous, and when to suppress the warning. In the codelab example above, the author apparently decided that adding a flag that wouldn't be recognized on older devices was safe. Maybe he had information that unrecognized flags would be silently ignored, though I don't see that in the documentation.

I found this..
#SuppressLint("InlinedApi")
Indicates that Lint should ignore the specified warnings for the annotated element.
Exp:
SuppressLint
implements from Annotation Class.
android.annotation.SuppressLint like this..
Built-In Annotations
Java defines a set of annotations that are built into the language
Annotations applied to java code:
#Override - Checks that the method is an override. Causes a compile error if the method is not found in one of the parent classes or implemented interfaces.
#Deprecated - Marks the method as obsolete. Causes a compile warning if the method is used.
#SuppressWarnings - Instructs the compiler to suppress the compile time warnings specified in the annotation parameters
http://developer.android.com/reference/java/lang/annotation/Annotation.html
http://developer.android.com/reference/android/annotation/SuppressLint.html

Related

Linking errors when using functions from <complex.h> in using API level 22

I'm porting a C and C++ library that currently works on iOS to be used on an Android application. I'm down to these last 3 linker errors (obfuscated for privacy reasons):
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cexp'
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cpowf'
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10285: error: undefined reference to 'cabs'
Now I understand these normally come from linking with libm.so (-lm), but i'm doing that already. If I go and check the offending so with nm:
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.so | grep cpow
Nothing comes back. It DOES hoever, if I use api 28
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-28/arch-x86/usr/lib/libm.so | grep cpow
00003900 T cpow
00003910 T cpowf
00003920 T cpowl
Also, in the static library it does show, even on api 22:
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.a | grep cpow
s_cpow.o:
00000000 T cpow
s_cpowf.o:
00000000 T cpowf
s_cpowl.o:
00000000 T cpowl
The inconsistency is puzzling. Shouldn't it be missing from the header altogether if not supported? Why does the static lib have it and the dylib not?
Would it make sense to statically link against it? And if so, how would I do it, taking into account the right path for the current api version?
My other option seems to go steal an implementation of libm (say http://openlibm.org/) or just these 3 functions I'm using from it.
tl;dr: yes, static linking libm.a should be fine
Check the libm.map.txt file: https://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt#289
These functions weren't added to Android until O.
Also, in the static library it does show, even on api 22
The static library isn't an API 22 static library. It's actually a ToT build from AOSP. If you're going to static link something, there's no point in using something old.
The reason it (there's actually only one version of libc.a/libm.a per ABI) is duplicated into each API directory is because build systems made for old NDKs expect it. If you look at the unified toolchain in r19 (toolchains/llvm/prebuilts/$HOST), you'll see that there's only one copy per ABI.
The inconsistency is puzzling. Shouldn't it be missing from the header altogether if not supported? Why does the static lib have it and the dylib not?
The header has an ifdef guard that hides it: https://android.googlesource.com/platform/prebuilts/ndk/+/dev/platform/sysroot/usr/include/complex.h#237
If you had a declaration for these functions and you think you were building for API 22, there's something wrong with your build system.
Would it make sense to statically link against it? And if so, how would I do it, taking into account the right path for the current api version?
In general for these sorts of problems this isn't a good solution since the Zygote has already loaded a libc, and loading another one can lead to all sorts of issues since they can conflict. Additionally, much of libc's networking is actually dispatched to netd, and the protocol between libc and netd has changed in the past (and is unfortunately not a versioned protocol).
Building with libc.a is only viable with standalone executables (think strace and gdbserver) rather than apps, and even then only if you don't need networking.
That said, libm.a is much simpler. The complex interactions that make libc.a unusable for apps don't affect libm. The only time you'll end up actually running code in libm is when the compiler somehow failed to inline the operation. Static linking libm.a into your application should be fine.

'uiprintf' error in android PAC ROM compilation

I am getting this error while compiling PAC ROM.. I found printf error was discussed before and adviced to include . but this doesn't seems to work for uiPrintf.
This the exact line:
device/cyanogen/msm8916-common/recovery/recovery_updated.c:171.9: error: implicit declaration of function 'uiprintf'
Pls help..
Implicit declaration means using a function without declaring it before. Generally it used to give a warning for other cm based rom but pac makes this strict.
For your info,
uiprintf function's definition is in path "bootable/recovery/updater/install.h", and the datatypes used in the function are in updater.h. You may manually add the definitions but it will give an error after long time(almost at end) about redeclaration of uiprintf function.
To get along with this error just comment out that line in recovery-updater.c. It will not hurt anything (It's just for recovery ui printing).

Android TimePicker methods being stubs

(I am unsure if everyone else faces this problem, but I do)
I am accessing setHour(int) and getHour() (and the minute's getter and setter) of android.widget.TimePicker - IntelliJ doesn't complain of their inexistence, but when i run the program from my phone (or emulator) it crashes and i see an error log of java.lang.NoSuchMethodError android.widget.TimePicker.getHour. (Other minute/hour getter/setter include).
I tried accessing the definition for the TimePicker class (Ctrl+B) and I realised every method contained a line: throw RuntimeException("Stub");
So what's this; How can I move on?
IntelliJ doesn't complain of their inexistence
That is because you are compiling against API Level 23.
but when i run the program from my phone (or emulator) it crashes and i see an error log of java.lang.NoSuchMethodError android.widget.TimePicker.getHour
That is because getHour() was added in API Level 23, and your device or emulator is running Android 5.2 or below.
I don't use IntelliJ, but it should be complaining about your build. In Eclipse and Android Studio, you would get an error from Lint indicating that you are calling a method (getHour()) that exists in your compileSdkVersion (23) but does not exist in your minSdkVersion (whatever you have that set to, as the oldest API level that you are willing to support).
I tried accessing the definition for the TimePicker class (Ctrl+B) and I realised every method contained a line: throw RuntimeException("Stub")
That is because it is decompiling the android.jar that is in your compile-time classpath, which consists purely of stub implementations to satisfy the javac compiler. At runtime, your process' VM will have a version of that JAR that has actual implementations.
How can I move on?
Probably stop calling getHour(), unless you can get away with doing so only on Android 6.0+ devices.

Android Lint - NewApi check still fails despite suppression with #TargetApi

Following an unsuccessful Lint run, I attempted to fix an error by adding the #TargetApi(Build.VERSION_CODES.HONEYCOMB) attribute, but the next time Lint is run, the following error still shows for the getScaleX() function:
Can anyone shed some light on this?
The call to getScaleX() requires API level 11 (Honeycomb), as mentioned in the message window. The message also indicates that the minimum API level is 9 (as per the minSdkVersion setting).
The Lint tool is warning you that you are using a method supported only in newer SDK versions (11+), but have set to allow the application to run on devices that don't support this method (SDK versions 9 and 10).
See a more detailed description of what the NewApi Lint check does here: (search for NewApi) http://tools.android.com/tips/lint-checks
Suppress such warnings with caution, I'd suggest protecting the code with something like this:
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
...getScaleX()...
}

In-line annotations give syntax errors

I'm loving the new Lint API checks of ADT rev 17, but the new API Correctness Check has got me stumped. I have the following line of code:
listView.setOverScrollMode(OVER_SCROLL_NEVER);
Lint is reporting on this line:
Call requires API level 9 (current min is 4)
According to the documentation, I should just be able to add an annotation above the line, like so:
#TargetApi(9)
listView.setOverScrollMode(OVER_SCROLL_NEVER);
This, however, gives a syntax error in Java 1.6:
Syntax error on token(s), misplaced construct(s)
That's not allowed in Java (until/if JSR 308 gets added); you can only annotate classes, methods, fields, parameters and variable declarations. It's the latter that is shown in the docs. However, for bytecode based checks like the api check you may need to place it on a method or class (or anonymous/inner class). The Add Annotation quickfix for these warnings in lint should do the right thing.

Categories

Resources