Let me start by describing my problem. I am working on a large Android application that has a large number of layouts and strings (all in strings.xml). A new requirement has been made that requires some of the strings to be different depending on a condition at startup (think all instances of "cat" being replaced with "dog"). This condition does NOT depend on anything with the device (locale, size, resolution, etc.): it only depends on something within the business logic.
The simplest approach would be to create new copies of all the layout files that use the strings that have "cat", and in those new layout copies instead use strings that have "dog". However, this is not entirely feasible due to the number of layouts, as well as future maintenance concerns of basically duplicated layouts.
I know this isn't a discussion forum, so I have an approach I'd like to focus on. It seems to me the problem is closely related to normal resource configuration/locale, where different resources are provided due to attributes of the device. Is there a way to get this working for my situation? The differences are the desired configuration is only known at runtime and there isn't an existing resource qualifier that makes sense (we might translate into French, for example, so I don't want to piggyback on that). I can't imagine my problem is unique, though.
If there's another approach I should use let me know, although I don't want to go too far in the discussion route because SO frowns upon it. Frankly it's probably risky even asking this here, but I don't know where else to ask it.
I can think on several solutions:
You can set the string on runtime like yourTextView.setText(R.string.any_string) with:
1) A To have some resources strings for you business logic.
2) A placeholder string,
getResources().getString(R.string.tempale, "your value")
3) Get the string from web service if that posible
Related
Right now they are just stored on a class called Globals as static fields.
I'm not the one who made the app, but I am considering putting them in localized strings.xml files, such as <string name="API_URL">http://someurl</string>. Is this good or bad practice?
UPDATE:
I chose the answer that I feel answers the question most comprehensibly.
But after some re-thinking, I have chosen a different solution alltogether.
Given that URLs are actually based on the country which the app should be distributed for, it doesn't make sense to switch them based on locale, as the URLs should stay the same regardless of the language on the phone.
Instead, I have implemented Gradle Flavors, which create different APKs based on different settings and such. It allows you to create variations of the same app with the small changes that you need. :) So now I have the URLs in a flavor-specific file.
Thank you to everyone who took their time to comment and help me.
I agree with puneet, it's neither good nor bad. It depends on what you are doing with the API Urls.
Are you going to append them later with user input? If so I would suggest you keep them as global variables that way you can modify the API URL programatically as needed.
If the API Url are complete and will not need to be appended then putting them in the strings.xml would be fine. Just remember that you would still have to create a local String variable in the java to hold the text from the API_URL in the string.xml, which seems inefficient if what you're aiming for is to write less code.
Neither good nor bad.If your concern is the security then none of them provide the security as decompilation is possible.
I am attempting to create a free, configurable version of my EGMaps Android app which anyone can use to easily create their own map-based apps. The goal is to provide a framework so people with little programming knowledge can just fill in blanks, provide their data, and have it work.
There are two apps involved:
App #1 (EGMaps) does pretty much all the work. It needs access to data provided, or pointed to, by other App #2. I'm the only one working on this one.
App #2 will be created by multiple, maybe lots of other people, all with different app signatures. This is a very small, simple app which does very little other than passing data to EGMaps. I'll be providing source code and instructions on what to fill in. The other programmers can either use it directly, or modify it however they want for their app, which will then eventually call EGMaps.
App #2 needs to pass a lot of data like GPS coordinates, GPS tracks, marker locations, etc, which it's already doing. It also needs to pass an unknown, but potentially large number of small drawables. Due to space considerations, I'd prefer to use the drawables directly from the calling app, rather than copying them over or downloading and storing them inside of EGMaps. These drawables will eventually be Google Maps Marker icons.
Since the apps are written by different programmers, the app signatures are different, so setting the same user ID doesn't help.
This is as close as I've come:
iconString=callingPackage+":drawable/"+iconName;
iconValue=getResources().getIdentifier(iconString, "drawable", null);
callingPackage = name of calling app (ie: App #2). I have verified this is correct.
iconName = name of icon, as found in the drawable resources.
Without the callingPackage part, and with the drawables saved directly in the app, this works fine. It's just accessing the external drawable that doesn't work. iconValue always returns 0. I have also tried putting callingPackage into the third parameter of getIdentifier, with and without adding it to iconString, but that didn't make any difference.
Is there any way to directly (or indirectly, I suppose) access these drawables from the calling app without actually copying them from somewhere?
I would have expected getResources().getIdentifier(iconName, "drawable", callingPackage) to have worked, assuming that callingPackage is an actual package name.
You can try createPackageContext() and calling getResources() on it to get a Resources object referencing the other package.
This question already has answers here:
Why to use strings.xml?
(3 answers)
Closed 8 years ago.
In creation of UI in android projects ,why we have to refer values of string from the values folder's string.xml?
why eclipse shows warning if we assign values straight away?
I want to know the logic behind this,It's a very basic question but i couldn't find answer for this from google!
Another reason that is not covered in the older post pointed out by KenWolf, is that now when uploading your application to the Google Play Store, you can easily make your app more accessible to other languages/locations by uploading just your strings.xml to their new translation service announced at I/O 2013. This just has to do with localizing your resources like was stated here.
You can read more about it here.
There are many different advantages to using a string resource file, rather than hardcoding strings. While it may seem pointless and convoluted in small projects, it is incredibly useful in larger projects.
If you know that you want the same string to appear in multiple places, possible occurring in separate activities, the string resource file allows you to reference one source, rather than type the string over and over again.
If you decide to change a string in you app, or have a dynamically changing string, it is much easier to modify the resource file than it is to manually change all instances of that string in you app
It is great for localization and translation. If someone wants to port your app to a different language, all you have to do is substitute the strings.xml with a translated version
Thus, it may seem useless in small applications, but for large scale applications, it makes your life much simpler and allows you to more easily reach foreign language users.
The reason we are referring from String.xml is we can reuse the same string where ever we want.
I have released an android app downloadable in the UK, but I wish to release a (very slightly different) version of the app for the U.S. Currently I believe I need to do the following for the new version of the app ...
1. Change the 'package' attribute in the manifest file to something different.
2. Ensure that on Google Play only the US can download the app.
Is there anything else I am yet to discover I need to do, or any other problems I am yet to consider?
Edit 19th July 13:19 GMT - I am currently warming towards using TelephonyManager.getNetworkCountryIso() as an initial country guess, and falling back on the locale if this fails (because of no SIM card). What do people think? Using GPS is also an option though, but is that overkill?
Since you say you're just changing a couple of strings (we'll think of the URL as just a string, too), I would suggest the following:
Create the resource directories res/values and res/values-en-rUS.
In each of these, create a strings.xml resource file
Define your default (UK specific) string values in the res/values directory, and your US specific string values in the res/values-en-rUS folder.
Then, to refer to these strings, simply use #string/my_string_name when referring to them from an XML document, or getResources().getString(R.string.my_string_name) when referring to them from code.
For more details on the types of resource qualifiers, check out this page, also for the list of qualified country codes you can use, see this page.
I'm sure anyone determined enough could change their region to US -- I'm honestly not sure offhand how the region is determined -- but for all intents and purposes this should do the trick without having to maintain two separate applications. I would just evaluate how critical it is that UK users be unable to access the US specific functions of the application, and with that in mind determine whether it is worth the maintenance of two applications.
EDIT Some more additional searching leads me to believe the region is locked into the build.prop file, which is not editable outside of rooting your device (i.e. it is not going to happen accidentally). That said, if it's still imperative that they have the correct option, I might suggest a popup dialog only on the first run of the application that confirms the locale with the user, saves it as a SharedPreference, and then choose your Strings programmatically based on that preference. That way you're still only maintaining one application, but you still have the flexibility of handling the two regions.
This is correct. The Play Store goes off of two things for who can download and if they can update. The first is the packagename com.andya.myukapp -> com.andya.myusapp should work, as long as none of your existing customers are expecting to switch freely between the two (assuming it's a paid app)
I eventually decided that the best policy was to use TelephonyManager to check the country of the Network.
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String networkCountryCode = tm.getNetworkCountryIso();
If that failed, I got the locale.
String locale = context.getResources().getConfiguration().locale.getCountry();
This would happen once at the start of the app. The results of this would then be saved and be configurable in the settings screen.
I'm wondering what some good ways of organizing Android projects are. I'm building a little recipe application and have already made dozens of layouts, drawable resources, menus, etc., not to mention Java source code.
Android does not allow sub-folders for resources, so is there a way to organize them? Right now I'm trying to organize them through naming conventions (e.g. new_list_ingredient_edit) but I'm wondering if there is a better way, as the names will probably get pretty long and cumbersome.
Same thing with resources such as string values. As I understand it, I can create multiple resource files (e.g. strings_new_ingredient.xml, drawables_new_instructions.xml, etc.) but all my resources across files have still have to have unique names, which again is cumbersome.
Although android doesn't allow sub-folders for resources, it does for assets, but this is much more cumbersome to use.
A possible option would be to use a sql database with all of your strings, but this approach is probably too much work and more cumbersome anyway.
Your naming convention method is probably your best option. You could think of some of the seperated words as directories if you want, which should keep it organized enough.
user864684,
I normally try to use heirarchy in my naming. If it is a layout for dialog, i will start with dialog_sharing or something like that.
As for graphics, I will start with btn or bg or txt or ic_menu depending on what they are for. Other than that, you just get used to it as you dev more for Android.
Make sure you also have a support folder on your drive for your local resources. I mimic the android layout so i keep my graphics sorted in res/... on my local drive too. I keep the psd and graphic files there and then just copy the pngs to eclipse.
Hope this kinda of helps. There is no real standard but you will pick up a style.
Specifically with respect to organizing drawable resources, I would advise choosing names that describe the drawables structurally, not functionally.
For example, if you have a gray circle shape resource that you are using as a placeholder for an image, I would avoid naming it *image_placeholder*. Instead, I would call it *gray_circle_1*.
My advice comes from having had the experience on multiple occasions of having given things names like *image_placeholder*, forgetting what they actually contained, and then rewriting the same exact thing in a separate resource file without realizing it.
Don't do what I did.