I am working on an android project and I localized my app in two languages, the problem is that it works fine when I run my app directly from the android studio but when I upload my project in google play store and download the app from play store its localization is not working in some version of Android.
This is my java code that sets the local language.
private static Context updateResources(Context context) {
Locale locale = new Locale("fa","AF");
Locale.setDefault(locale);
Resources res = context.getResources();
Configuration config = new Configuration(res.getConfiguration());
if (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale);
context = context.createConfigurationContext(config);
} else {
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
This is my English layout file.
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="update">Update</string>
<string name="app_version_title">New version</string>
<string name="app_version_title_second">is now available</string>
<string name="logout_msg">Are you sure you want to logout?</string>
<string name="logout_title">Log Out?</string>
<string name="languages">Languages</string>
<string name="km">Km</string>
</resources>
This is my Persion layout file.
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="update">به روز رسانی </string>
<string name="app_version_title">نسخه جدید</string>
<string name="app_version_title_second">موجود است</string>
<string name="logout_msg">آیا مطمئین هستید که خارج میشوید؟ </string>
<string name="logout_title">خروج؟</string>
<string name="languages">زبانها</string>
<string name="km">کیلومتر</string>
</resources>
This is the structure of my Values folder.
values
strings.xml
values-fa-rAF
strings.xml
If you are using app bundle to publish in the play store the android app bundle feature will split the bundle into APK(s) based on the languages for optimizations and smaller sized APK file. Read more here. So only the APK which matches the user's locale will be installed on the device. Therefore changing the language dynamically will not work because the installed APK will contain only the language which is same as user phone's locale.
To prevent the split based on the language you need to add the following in your app build.gradle file like below.
android {
...
...
bundle {
language {
enableSplit = false
}
}
}
I experienced the exact same issue.
There is nothing wrong with your code.
It gave me hard times but I finally figured it out.
When you download an app from Google play - and you are trying to set a locale that does not exist in the Language list that the user defines in the Settings - the app will use the default strings.xml
ask from someone who experiences this issue to add Persian language to the Language list in the settings - then he must Uninstall the app - and re-Install it again - the app will use your strings.xml values-fa-rAF.
When you think about it - it has some sense in it.
Anyway - if it is critical you can consider checking on runtime the texts and show a message to the user and instruct him to solve the problem.
Good luck
I think when you gonna to Generate signed bundle or APK, you select "Android App Bundle", you must Select "APK", because you are using strings.xml localization, you can Read more here.
Related
In my Android Studio project I have a font file called 'cutive.xml'
The file path is: resources -> font -> cutive.xml
The file looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res/android" //Lint problem here
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="Cutive"
app:fontProviderCerts="#array/com_google_android_gms_fonts_certs">
As you can see, the app namespace is not formed correctly:
xmlns:app="http://schemas.android.com/apk/res/android"
In the MainActivity, I create a static Typeface object that references the font:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
typeface0024 = getResources().getFont(R.font.cutive); //app will crash if app namespace is corrected
else typeface0024 = Typeface.create(Typeface.SANS_SERIF,Typeface.BOLD_ITALIC);
The app loads correctly and finds the font, even though Lint claims that there is an error.
When I switch the app namespace to the correct form as such:
xmlns:app="http://schemas.android.com/apk/res-auto"
The app crashes on the line:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
typeface0024 = getResources().getFont(R.font.cutive);
the error logs gives the following reason: A RuntimeException
Caused by: android.content.res.Resources$NotFoundException: Font resource ID #0x7f090000
How can I fix the error given by Lint? Or, should I just suppress the error and even though the app namespace is not formed correctly the font and app will load correctly.
Any suggestions
I was able to fix the problem by using the 'android' namespace NOT the 'app' namespace.
According to the Android docs make sure you the have the following support library:
compile "com.android.support:support-compat:28.0.0"
Now it works and it looks like this:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
android:fontProviderAuthority="com.google.android.gms.fonts"
android:fontProviderPackage="com.google.android.gms"
android:fontProviderQuery="Cutive"
android:fontProviderCerts="#array/com_google_android_gms_fonts_certs">
</font-family>
I have just started learning recyclerview. In most tutorials I saw they store the array list in the Java. I want to know how can I bring out resources kept in string.xml to the java .
You can write this in String.xml and use this String of Array..
<array name="arrayName">
<item>item 1</item>
<item>item 2</item>
</array>
In short, this is how you define a static string array in an Android XML file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="my_books">
<item>Scala Cookbook</item>
<item>Play Framework Recipes</item>
<item>How I Sold My Business: A Personal Diary</item>
<item>A Survival Guide for New Consultants</item>
</string-array>
</resources>
Then inside an Activity, Fragment, or other Java class, you can create a string array in Java from that XML like this:
Resources res = getResources();
String[] myBooks = res.getStringArray(R.array.my_books);
i have a pojo class
run this code
Field[] fields = clazz.getDeclaredFields();
i got a field under Android Studio IDE :
its type is interface com.android.tools.fd.runtime.IncrementalChange
its name is $change
My Android Studio version is 2.0 Preview 4
the pojo class which i definded by myself didn't have $change field
when i run the code in eclipse, it works normal.
where did the field come from?
how can i avoid this field , is there some setting in Android Studio ?
Instead of turning off instant run we can resolve this issue by utilising synthetic modifier check. 'com.android.tools.fd.runtime.IncrementalChange' is synthetic so we can check whether the field is synthetic using isSynthetc method.
Field[] fields = objClass.getFields();
for (Field field : fields) {
String name = field.getName();
Object value;
if(field.isSynthetic()){
continue;
}
//add your code here
}
Most likely this field is added in order to support the Instant Run feature added in Android Studio 2.0, and will not appear if you turn off Instant Run.
I think diordna answer is best link。install run is Android Studio new function,I won't close it。
I use JsonTool link in my sdk library ,when I run my app with androidStudio2.2 JsonTooll.objectToJson() give me a bad json String ,I add code
if (name.contains("this$") || field.isSynthetic()) continue;
solve it
I have a project "CustomViews" that I'd like to use as a library in another project "Library Dependent". One of my views, ToolbarITI has a few custom attributes defined in a file which I handle in my ToolbarITI class:
attrs.xml
<resources>
<declare-styleable name="ToolbarITI">
<attr name="rightIconSrc" format="integer"/>
<attr name="leftIconSrc" format="integer"/>
<attr name="titleText" format="string"/>
<attr name="iconPadding" format="dimension"/>
<attr name="fontName" format="string"/>
</declare-styleable>
</resources>
When I add the custom view to a layout in my Library Dependent project, I am able to add these custom attributes in the xml file, and the attributes are applied. However, Android Studio does not recognize the custom: attributes pertaining to ToolbarITI when auto-filling which makes the process annoying. I have declared xmlns:custom at the top of my layout file.
I simply do not understand how these attributes are bundled with the library project and referenced by Android studio. If anyone can explain how this is done, please do provide an explanation!
I'll need someone to confirm that this was the root of the problem, but this is what I found.
I was uploading my .aar to com.tommcfarlin.lib, which with the "lib" results in resources being ignored (according to Android Studio). Though I'm not sure if this results in anything "breaking" when packaging it certainly decreases the functionality of Android Studio by not adding resource ids for autofill. Better be safe and not do this.
These are the steps I took that resulted in Android Studio recognizing the custom attributes.
1) I altered my build.gradle in my CustomViews project to:
note the com.tommcfarlin.customviews
def aarFile = file("build/${archivesBaseName}-${project.version}.aar")
artifacts {
archives aarFile
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file:///C:/Users/tmcfarlin/AndroidProjects/myrepo")
pom.groupId = 'com.tommcfarlin.customviews'
pom.artifactId = 'CustomViews'
pom.version = '0.1.0'
}
}
}
2) I ran "gradle uploadArchives" from the terminal
3) In my Library Dependent project I had the following lines in my build.gradle:
repositories {
maven { url 'file:///C:/Users/tmcfarlin/AndroidProjects/myrepo' }
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.tommcfarlin.customviews:CustomViews:0.1.0#aar'
}
4) I synced the project with gradle files. After this, I still couldn't see the attributes. I closed the Library Dependent project and reopened it voila!!! I could now have the following block where my custom view's attributes were filled in for me when I typed "custom:" and pressed Ctrl+Space
<com.tommcfarlin.customviews.ToolbarITI
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:fontName="helvetica.ttf">
</com.tommcfarlin.customviews.ToolbarITI>
This webpage has been immensely useful to me while learning how to set up a local repository. Just be sure not to use the "lib" directory!!! http://blog.glassdiary.com/post/67134169807/how-to-share-android-archive-library-aar-across
I searched for auto incrementing version number and found some solutions but I wonder which one is the most efficient and recent way? I do not know if there is a new feature or tool on Visual Studio 2012.
1st:
changing AssemblyInfo.cs file
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]
2nd:
codeplex (I don't know if it is compatible on VS2012)
3rd:
Project properties under Publish
4th:
Using T4 templates to manage assembly version information
Please suggest any other solutions or share your experience about versioning?
Download and install AssemblyInfoTask
You need to get this custom build task. Chris references the original source at gotdotnet.com which does not exist anymore. Either search for the text AssemblyInfoTaskvers with google or try this link
http://code.msdn.microsoft.com/AssemblyInfoTaskvers/Release/ProjectReleases.aspx?ReleaseId=232
It should redirect you to the download area on MSDN where you can get the lates setup release.
Import the task into your build project
Open Source Control in Visual Studio and make sure you have a local copy of the build project in your workspace. Then check out the TFSBuild.proj file (Unchanged, keep any existing lock) and open it. Add the following line right after the import of Microsoft.TeamFoundation.Build.targets:
<Import Project="$(MSBuildExtensionsPath)¥Microsoft¥AssemblyInfoTask¥Microsoft.VersionNumber.Targets"/>
Use a custom task for retrieving the revision number
Each buildnumber contains a revision: FooBar_20090128.3 What we want to do is using this revision number also as revision in our Assembly version. So we need to implement a custom build task that is able to extract the revision number from the buildnumber so that we can assign it to the Assemblys' revision number. At the end of this article, I will post the sources you will need.
Right after the import statement from above, register this custom build task by adding the following line:
<UsingTask TaskName="ExtractRevision.ExtractRevisionTask" AssemblyFile="ExtractRevision.dll"/>
To configure all assembly properties and format the number formats respectively, add the following lines to your project file:
<PropertyGroup>
<!– Assembly version properties. Add others here –>
<AssemblyMajorVersion>4</AssemblyMajorVersion>
<AssemblyMinorVersion>0</AssemblyMinorVersion>
<AssemblyBuildNumber>0</AssemblyBuildNumber>
<AssemblyRevision>0</AssemblyRevision>
<AssemblyFileMajorVersion>4</AssemblyFileMajorVersion>
<AssemblyFileMinorVersion>0</AssemblyFileMinorVersion>
<AssemblyFileBuildNumber>0</AssemblyFileBuildNumber>
<AssemblyFileRevision>0</AssemblyFileRevision>
<AssemblyBuildNumberType>DateString</AssemblyBuildNumberType>
<AssemblyBuildNumberFormat>MMdd</AssemblyBuildNumberFormat>
<AssemblyRevisionType>NoIncrement</AssemblyRevisionType>
<AssemblyRevisionFormat>0</AssemblyRevisionFormat>
<AssemblyFileBuildNumberType>DateString</AssemblyFileBuildNumberType>
<AssemblyFileBuildNumberFormat>MMdd</AssemblyFileBuildNumberFormat>
<AssemblyFileRevisionType>NoIncrement</AssemblyFileRevisionType>
<AssemblyFileRevisionFormat>0</AssemblyFileRevisionFormat>
<!– Dump the TFS BuildNumber to the Assembly Comment Prop –>
<AssemblyDescription>$(BuildNumber)</AssemblyDescription>
<!– TF.exe –>
<TF>"$(TeamBuildRefPath)¥..¥tf.exe"</TF>
<!– AssemblyInfo file –>
<AssemblyInfoSpec>AssemblyInfo.*</AssemblyInfoSpec>
</PropertyGroup>
Set the revision number
By altering the target CheckSettingsForEndToEndIteration, you can use the custom build task you have yet to implement for extracting the revision number from the buildnumber and add it to the assembly version:
<!–for 2008 use the GetBuildProperties Task to get the BuildNumber –>
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)">
<Output TaskParameter="BuildNumber" PropertyName="BuildNumber"></Output>
</GetBuildProperties>
<!– extract the BuildRevision –>
<ExtractRevisionTask BuildNumber="$(BuildNumber)">
<Output TaskParameter="BuildRevision" PropertyName="BuildRevision" />
</ExtractRevisionTask>
<!– update the AssemblyInfo Props –>
<CreateProperty Value="$(BuildRevision)">
<Output TaskParameter="Value" PropertyName="AssemblyRevision"/>
</CreateProperty>
<CreateProperty Value="$(BuildRevision)">
<Output TaskParameter="Value" PropertyName="AssemblyFileRevision"/>
</CreateProperty>
<!– just needed if you populate the AssemblyDescription too like in the sample –>
<CreateProperty Value="$(BuildNumber)">
<Output TaskParameter="Value" PropertyName="AssemblyDescription"/>
</CreateProperty>
Check out and back in all AssemblyInfo.[cs|vb] files from your workspaces
Before you can alter the AssemblyInfo files, you need to let Team Build check them out:
<!– Set the AssemblyInfoFiles items dynamically –>
<CreateItem Include="$(SolutionRoot)¥**¥$(AssemblyInfoSpec)">
<Output ItemName="AssemblyInfoFiles" TaskParameter="Include" />
</CreateItem>
<Message Text="These AssemblyInfo.* files were found:"/>
<Message Text ="#(AssemblyInfoFiles)"/>
<Exec WorkingDirectory="$(SolutionRoot)"
Command="$(TF) checkout "#(AssemblyInfoFiles, '" "')""/>
Right after the altered files have been compiled, you can check them back in:
Command="$(TF) checkin /comment:"Auto-Build: Version Update" /noprompt /override:"Auto-Build: Version Update" "#(AssemblyInfoFiles, '" "')""/>
Just in case anything bad happens, there is a way of undoing the changes:
<!– In case of Build failure, the AfterCompile target is not executed. Undo the changes –>
<Target Name="BeforeOnBuildBreak" Condition="'$(IsDesktopBuild)'!='true'">
<Exec WorkingDirectory="$(SolutionRoot)"
Command="$(TF) undo /noprompt "#(AssemblyInfoFiles, '" "')""/>
</Target>
Implement the ExtractRevision custom build task
Simply create a new C# library project with the following class (and add a strong name to it by signing it in the project properties):
namespace ExtractRevision
{
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public class ExtractRevisionTask : Task
{
public override bool Execute()
{
int indexOfDot = buildNumber.LastIndexOf(".");
if (indexOfDot != -1 & indexOfDot != buildNumber.Length – 1)
{
buildRevision = buildNumber.Substring(indexOfDot + 1, buildNumber.Length – (indexOfDot + 1));
}
else
{
//there is no char following the dot or we can't find a dot
buildRevision = "0″;
}
return true;
}
private string buildRevision;
private string buildNumber;
public string BuildNumber
{
set { buildNumber = value; }
}
[Output]
public string BuildRevision
{
get { return buildRevision; }
}
}
}
You need to check in the .dll file directly into your TeamBuildTypes folder on TFS.
External Link : http://devsid.blogspot.in/2010/06/automatically-increment-assemblys.html