I have 100 images in my application of different cities and I want to divide these pictures in different groups, lets say in evening, morning, sunny, raining etc…
We know that when we call an image from layout folder by calling R.layout.image_1, android generates integer number for each image
For example:
R.layout.image_1 (223344), R.layout.image_2 (556677),
R.layout.image_3 (778899),
I can create one table having evening, morning fields and I can assign group of pictures to each of them with integer IDs which are (223344,556677) and I can call evening or morning group and i can display all images related to these group.
My question is: Does Android generate same number every time. Are these numbers are fixed? When ever the application runs.
If its true then upper idea will work for me. If this idea is incorrect then kindly guide me what is the decent approach to handle hundreds of PNGs in application.
Those numbers are not fixed. R will be regenerated and can have completely different numbers if you change something. That is why when comparing ids, you compare by the name instead.
Eg instead of
if (i == 223344)
do
if (i == R.layout.image_1)
Since R.layout.image_1 references the integer id, the name won't change (unless you change the layout xml name.
If you want to get a resource id dynamically (by a string representing the name), you should have a look at this method - Resources#getIdentifier().
First of all we generally put images in the drawable folder.
Does Android generate same number every time?
No.
Are these numbers fixed whenever the application runs?
Yes.
In fact, once your project is built, the ids will remain the same for that same build.
In other words for a certain generated APK file, the ids won't change.
So how can you take advantage of that to group your resources?
You could have a static int array that holds the ids:
public static final int[] IMAGES_MORNING = {R.drawable.morning0, R.drawable.morning1, etc};
public static final int[] IMAGES_EVENING = {R.drawable.evening0, R.drawable.evening1, etc};
Although a more structured method would be to store them in a database on your app's first launch.
Or you could use what A--C suggests:
For example to get all the ids of morning images
for(int i = 0; i < numberOfMorningImages ; i++){
int id = getResources().getIdentifier("morning" + i, "drawable", getPackageName());
// do something with the id
}
No, there's no guarantee that integers will be the same every time, so the solution you've described won't work. Unfortunately, there's no proper way to group drawables inside the res/drawable folder. As a workaround, you can store them inside the assets folder, where you can group them as you like. However, Android won't be able to handle different resolutions this way. The choice is up to you. Hope this helps.
Related
In my app i want to be able to store resource id of some icons in database. I suppose it is not save to do, cause in the later stages (application upgrades) i may want to add new icons to the app, so all id's may change? What is the best practice to store resource in case i do not want to store icons as blobs?
As an example, let's say i have a game 1.0, where i let user to choose an avatar for his character from a list of avatars. I want to store this avatars id in DB and be sure that if i add more avatars in game 1.1 - user will still see his choice.
The best way (in my opinion) is to store the resource entry name.
String iconName = getResources().getResourceEntryName(R.drawable.your_icon);
So your SQLite database column where you want to store the icon will have type TEXT. You're right that storing resource IDs is a bad practice because they're recreated when you compile the app, so you can't rely on them not changing (I learned this the hard way, all my app's icons got messed up).
To get the resource ID from the String when you need it, call
int resID = getResources().getIdentifier(iconName, "drawable", getPackageName());
Note that both getResources() and getPackageName() are methods from Context, so you need to have reference to your application/activity Context to be able to call these methods.
I ask this because I have exceptions from reports (from users from the market), mentioning that I have duplicated views with id 0x2 (or 0x3).
Since all my generated ids are really big, I think that the views with duplicated ids are views with no specifically defined ids.
My question is what are the ids of the views, that the developer hasn't explicitly assigned ids to them.
Thanks in advance,
Danail
The AAPT constantly updates your R file to generate unique hexadecimal values for each of your own IDs. In terms of IDs YOU create, they only need to be unique within the parent viewgroup. As always please post your stacktrace.
According to the source code, a View for which you haven't set an ID, has an ID of -1.
public static final int NO_ID = -1;
I would say no id is created if you do not specify an id to a view. Try creating a very simple application and create components with no id's , you'll notice that no id's are created in the R.java file.
I have a simple program where I generate random numbers, and use these to return an element from an array. Based on this array element, I want to play a sound file. For example: The random element that was returned was "Am". I now want to play the file "am.ogg". But you cant just throw a string in for the resourceId. Any ideas?
This seems to be duplicate of this thread (which by the way is also duplicate). Except for using this method you can also use reflection on the R class (second also not good option). The best option is the one in which the list of ids you will be interested in can be determined in the code. Basically you define map mapping every string to the corresponding R.id variable (int). However, I am not quite sure this will be your case.
I've searched Google and this website many times, but can not find a solution to my question.
First, I understand, you can load images using something like:
int image = R.drawable.icon; (assuming there's a file called 'icon.png')
and I've read about, and tried using:
getResources().getIdentifier("resname", "restype", com.example.whatever);
But, here's what I'm unable to do:
I want to be able to have pictures in the /res/drawable folder (I believe that's the correct folder), WITHOUT KNOWING ANY OF THE NAMES OF THE FILES, and load them dynamically - at run-time.
One (of the many) things I've tried is (something like):
int[] images = new int[numberOfImages];
for( 0 to numberOfImages )
{
images[i] =
getResources().getIdentifier("resname", "restype", com.example.whatever);
}
This returns 0 EVERY TIME, so it's not going to work
I'd like to get the name and integer identifier for every picture in the /res/drawables folder. Can this be done WITHOUT KNOWING ANY FILE NAMES?
----------------------------------------------------------------------
[adding this after the question was resolved to help anyone that may run into the same issue in the future. It just shows that it does in fact work.]
Class resources = R.drawable.class;
Field[] fields = resources.getFields();
String[] imageName = new String[fields.length];
int index = 0;
for( Field field : fields )
{
imageName[index] = field.getName();
index++;
}
int result =
getResources().getIdentifier(imageName[10], "drawable", "com.example.name");
Well, if you have to do it, use reflection :)
Class resources = R.drawable.class;
Field[] fields = resources.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
However, in a way, you are still hard-coding stuff, since you will only be putting a fixed set of drawables in your app. :)
As you stated in the comments, if you want to add files to that folder after the app is installed you'll have to use a private folder. Data storage documentation.
Then use a service to download images and add them to the private folder.
If you want the user to download the app with some preloaded images and you don't want to wait for the service run for the time to download the initial set of images, you can always send some images in the /res/raw folder and in the first time your app runs, copy these to your private folder.
I have a few questions concerning the application I'm designing. I have many different routes I could try in order to get what I wanted, but I thought I would get suggestions instead of doing trial and error.
I'm developing a simple app that has one Game screen (activity) and a main menu to start the game. The game screen will have two buttons, "Next" and "Repeat". Every time "Next" is hit, a new sentence in a different language (with the english translation below it) will appear, audio will pronounce the sentence, and hopefully I can get a highlighter to highlight the part of the sentence being spoken. You can guess what the Repeat button does.
My question is, what do you guys think would be the best way to store these sentences so they can be randomly picked out? I thought about making an array of structures or classes with the English definition, audio, and sentence in each structure. Then using a random iterator to pick one out. However, it would take a long time to do this approach and I wanted to get some ideas before I tried it.
Also, I'm not sure how I would print the sentence and definition on the screen.
Thanks!
Using an array of structs/classes seems like that would be the normal way to go.
Not really sure what you mean by a random iterator, but when picking out random sentences from the array of sentences, you might want to avoid repeats until you've gone through all the elements. To do that, you can make a second array of indices, select one at random from those, use the element that corresponds to that index, and remove that number from the array of indices.
In Java, that would look something like
ArrayList<Sentence> sentences;
ArrayList<Integer> indices;
Random rand;
private void populateIndices() {
for(int i = 0; i < sentences.size(); i++)
indices.add(i);
}
public Sentence getNextSentence() {
if(indices.isEmpty())
populateIndices();
int idx = rand.nextInt(indices.size());
int val = indices.get(idx);
indices.remove(idx);
return sentences.get(val);
}
Quite frankly I would load out of copyright books from Project Gutenberg and randomly pull sentences from them. I would then pass the sentences into Google APIs to translate and pronounce the sentences. Relying on external services is at the very heart of what a connected OS like Android is made for. It would be a much more compelling use of the platform than a canned Rosetta Stone like CD solution and your ability to tap into a broader amount of content would be increased exponentially.