I am new to Android development and am wondering what happens if you use attributes on XML tags from an API level greater than your minSdkVersion.
For example having:
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="20" />
And then using this:
<activity android:logo="#drawable/iconwhatever"></activity>
The "android:logo" attribute is from API level 11.
In Android Studio it gives the following error, but I want to know what could happen if this is left alone:
Attribute "logo" is only used in API level 11 and higher. (Current min is 9)
Any help regarding this would be greatly appreciated.
Unsupported attributes are safely ignored.
From SDK documentation:
When parsing XML resources, Android ignores XML attributes that aren’t supported by the current device. So you can safely use XML attributes that are only supported by newer versions without worrying about older versions breaking when they encounter that code.
For XML attributes, its safe to use attributes from newer APIs (they will simply be ignored as the XML parser won't even look for them on older versions).
In this case, the manipulation of attributes that are different APIs must be made via code and not in XML.
In code, you can treat it.
For example:
if(Build.Version.SDK_INT > 10){
.... use an attribute
}
else{
.... use other
}
For your specific case, use "icon"
<activity android:icon="#drawable/iconwhatever"></activity>
Related
I've made an app, I've tested it and it was fine on my phone. But... when I gave the .apk to someone else whose phone language is RTL the whole layout broke and it messed up everything.
My question is - How can I force my app to use only LTR and disable the auto layout change which breaks my whole app design?
In your manifest file and inside the application tag add these two lines.
<manifest>
<application
.
.
.
android:supportsRtl="false"
tools:replace="android:supportsRtl" //(replace libraries' Rtl support with ours)
>
</application>
</manifest>
Note: (about second line)
Some libraries have support Rtl in their manifest file so if you want to use those libraries you must replace their manifest line of code with yours.
Android 4.2 added full native support for RTL layouts. To take advantage of RTL layout mirroring, simply make the following changes to your app:
Declare in your app manifest that your app supports RTL mirroring.
Specifically, add android:supportsRtl="true" to the
element in your manifest file.
Change all of your app's "left/right" layout properties to new
"start/end" equivalents. If you are targeting your app to Android 4.2
(the app's targetSdkVersion or minSdkVersion is 17 or higher), then
you should use “start” and “end” instead of “left” and “right”. For
example, android:paddingLeft should become android:paddingStart. If
you want your app to work with versions earlier than Android 4.2 (the
app's targetSdkVersion or minSdkVersion is 16 or less), then you
should add “start” and end” in addition to “left” and “right”. For
example, you’d use both android:paddingLeft and android:paddingStart.
For more precise control over your app UI in both LTR and RTL mode, Android 4.2 includes the following new APIs to help manage View components:
android:layoutDirection — attribute for setting the direction of a
component's layout.
android:textDirection — attribute for setting the
direction of a component's text.
android:textAlignment — attribute
for setting the alignment of a component's text.
getLayoutDirectionFromLocale() — method for getting the
Locale-specified direction
-- Source & Credits --
Just add the following to the manifest
android:supportsRtl="false"
tools:replace="android:supportsRtl"
Just add something like this in your App Theme Style:
<item name="android:layoutDirection">ltr</item>
or
<item name="android:layoutDirection">rtl</item>
For React Native adding the following line in the manifest file was enough:
// android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kidspodmobileclient">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:supportsRtl="false" // <== add this line here
It would be like the following screenshot:
RN version: 0.68.2
Sometimes, when I want to add SDK 21+ feature to my layout, I need to create whole layout in another file. It's heavy to me because I want to do or check everything in one layout. More of layouts are looking complex and hard to manage. Instead of having two layouts for different SDK versions, can I do something like this:
<ImageView
android:id="#+id/x"
android:layout_width="16dp"
android:layout_height="wrap_content"
<compatibility sdk_higher_than="21">
android:elevation="xdp" //my problem not about the elevation. Its just an example that pops in my mind about the compatibility.
</compatibility>
app:srcCompat="#drawable/ic_x" />
I can make this stuff programmatically but when I should see the view instantly on designer, making it programmatically is not a good way for me. If there is a good practice or idea for this problem can anybody illuminate me?
Yes you can do that by adding tool target API:
First add: <RootTag xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
Example:
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="14" >
or by name: tools:targetApi="jelly_bean"
If you want your layout directries to be use in different versions, name your files as:
/res/layout/layout.xml - (default directries)
/res/layout-v14/layout.xml
/res/layout-v17/layout.xml
Also, if you want to dynamically create element in your code:
You can also use annotations in your java code to make things easy:
First import: import android.annotation.TargetApi;
Then, use this annotation above your method:
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
There are more annotation that you can get help:
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
Above annotation to warn for methods that are used lower API level. Read more about requiresApi: Android API level annotation for Android libraries
Now, inside your method you can dynamically generate views.
Example from the doc:
private void setUpActionBar() {
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
Read doc for more details about annotations: https://developer.android.com/studio/write/annotations
You can not give your view elevation in your XML and check for your SDK version in your code - if it's over 21 give the view elevation programmatically.
For example:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
//the API level is above 21 and you can manipulate your view with all the features that available to API level 21+
}
I'm using API 17 and I'm looking for a way to set the whole app to rtl instead of using <android:layoutDirection="rtl"> in every single activity layout.
I had the same problem , all you need to do is just consider all your used parent container (LinearLayout , RelativeLayout , GridView , etc) and set the LayoutDirection to RTL you can approach this way programmtically thanks to ViewCompat class to include api lower than 17.
ViewCompat.setLayoutDirection(yourParentContainer,ViewCompat.LAYOUT_DIRECTION_RTL);
note that there is no need to set the Direction for childviews separately
Please check this text extract from android developers weblog:
To take advantage of RTL layout mirroring, simply make the following
changes to your app:
1- Declare in your app manifest that your app supports RTL mirroring.
Specifically, add android:supportsRtl="true" to the
element in your manifest file.
2- Change all of your app's "left/right" layout properties to new
"start/end" equivalents. If you are targeting your app to Android 4.2
(the app's targetSdkVersion or minSdkVersion is 17 or higher), then
you should use “start” and “end” instead of “left” and “right”. For
example, android:paddingLeft should become android:paddingStart.
If you want your app to work with versions earlier than Android 4.2
(the app's targetSdkVersion or minSdkVersion is 16 or less), then you
should add “start” and end” in addition to “left” and “right”. For
example, you’d use both android:paddingLeft and android:paddingStart.
the full text can be found here:
http://android-developers.blogspot.ca/2013/03/native-rtl-support-in-android-42.html
The easiest and best way
go to the app/res/values/styles and add below code to <style> tag, that you defined its name in android manifest
for example :
<style name"YourMainThemeName" parent="Parent Theme Of Your Choice">
<item name="android:layoutDirection">rtl</item>
</style>
and now go to the app/manifests/AndroidManifest.xml and add below line code to <application> tag :
<application
android:supportsRtl="true"
android:theme="#style/YourMainThemeName">
</application>
now your layout directions is rtl.
I needed to add a digital clock in the layout. My min-supported API level is 14. I found out that there is a digital clock widget for API level below 17 (After that it got deprecated), and there is a text clock for API 17 and above.
So one thing I can do is to add both layout in xml and dynamically set the visibility based on version number in the code. But the xml will continuously show me that I have used Text Clock while my min-supported level is 14. So:
Is there a way in the xml to specify to ignore the min-sdk error. Something like
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
That we use in the normal java code.
Is there a way in XML to specify to use a particular widget based on version number. Some kind of if else statement in the xml that says:
if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//Use text clock
} else {
// Use digital clock
}
you can use the tools target api
<item name="android:fontFamily" tools:targetApi="jelly_bean">sans-serif-light</item>
this will also work
<item name="android:fontFamily" tools:targetApi="17">sans-serif-light</item>
I know that you should be able to get the primary color of current theme by calling
getContext().getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
int color = typedValue.data;
However, even with AppCompat v7:21 this doesn't seem to work in pre 21 devices ("No such static field" at runtime). However if I try to declare such an attribute somewhere it says that it is already defined while compiling (the file it says to contain a definition doesn't contain such). So how on earth does on get access to themes color values from code (not in the layout files)?
Actually I was just being plain stupid. In order to use R.attr.colorPrimary in pre 21.
You cannot use android.R but rather the resources of your application.