Android: drawable id change after resources modify - android

I have an android application that use a gallery component to choose an icon and assign it to a button.
The icon set is located in res/drawable folder and is accessed in the gallery with the typical adapter of the guide:
private Integer[] Imgid = {
R.drawable.icon_home,
R.drawable.icon_home2,
...
}
After an icon choosing, i stored the settings in a db with id of the button and of the drawable.
All works done, but i've noticed that if i'll want to add or modify my icon set or resources in general of my application, ids of old resource could change, so the preferences in the db refers to wrong icon.
Is there a way to force the old id of R class so they didn't change in the future? Or is there another way to manage the item of the component galley with another attribute than id? (maybe string name and reflection?)
Thanks in advance

You can store the name of the drawable in the database if you don't plan to change that. getResourceEntryName returns the name from the resource id:
Resources resources = getResources();
String name = resources.getResourceEntryName(R.drawable.icon);
And you can get back the resource id from the name with getIdentifier:
int resId = resources.getIdentifier(name, "drawable", "your.package.name");

You can't use static int for resource identifier, however you should look at two methods od Resources class:
getIdentifier()
getresourceName()

You shouldn’t rely on the actual values of the R.drawable.* attributes.
Create your own ids instead (for example 1 correspond to R.drawable.icon_home and 2 correspond to R.drawable.icon_home2)
Edit:
String name and reflection should work too, but it’s probably a little overkill you have only a few icons.

Related

How to change images from mipmap folder dynamically without "direct description" in code?

I have a lot of images (more than 200) with various sizes in mipmap folders, and I need to set images in ImageView dynamically... but how to do this without "direct description" in my code of that R.mipmap.*int files?
There are flag images in mipmap folders, and my object has it's own String field "flagCountry" which consists of two characters. Names of flags in mipmap folders consist of same characters. So, that's a trouble - how to dynamically set setImageResource(R.mipmap.XXX) from flagCountry String variable?
I'm thinking that decision in "reflection", but how is it possible? )) Please help
You can use Resources.getIdentifier() to find the integer id for a resource given its name. It's like reflection for android resources.
int id = getResources().getIdentifier("XXX", "drawable", getPackageName());
Or something along those lines. This assumes the code is in an activity. Then you can call setImageResource(id) with that id.
As said by Doug, you can use Resources.getIdentifier() to find the integer id for a resource given its name. But you said you wanted the resource from mipmap. So do a simple change. Change the word "drawable" to "mipmap", and you'll get the image from mipmap. The changed code:
int id = getBaseContext()getResources().getIdentifier("XXX", "mipmap", getBaseContext().getPackageName());
image.setImageResource(id);

Programmatically loading images in Android

I would like to load images from my Drawable Resource folders without explicitly typing the identifiers for them. For example : Loading the images in drawable-mdpi using a 'for' loop and using the integer as an argument for the Bitmap Decoder. Which seems to work in theory, but my concern is: is the integer 0x7F020000 where drawable Int ID's seem to begin constant across all devices? or if I create code to load images this way will it not work on a different Android device than the one I am testing on?
Is there a better way to achieve what I have described?
You should not hard-code the id even you can get it from R file. From android API:
Although the R class is where resource IDs are specified, you should never need to look there to discover a resource ID.
R class will change its content when you update your resource, and clean and rebuilt. It means you cannot make sure the same name of resource will be assigned the same value after each built. However, IDs will be the same (not change) after apk released and installed in different devices.
Simple solution:
Create your images and name them sequentially like: img0.png, img1.png, ... and place them in drawable folder.
Get image id from its name by:
int imgID = getResources().getIdentifier("img00" , "drawable", getPackageName());
So if you want to use for loop, it should be something like:
for(int i=0; i < total_image_number; i++) {
int imgID = getResources().getIdentifier("img"+i , "drawable", getPackageName());
//do something else with our imgID here
//...
}

Android get resource type of id

I search for a way to say which resource type is behind a integer ID. For example i have the id of a drawable and another one for a color. I can load the drawable with Resource.getDrawable(id) and the color with Resource.getColor(ID) but how can i know which method is the right one for a given ID. I look for something like Resource.isColor(id)?
Has anybody a good idea. I wrote a image loader which loads images from web, filesystem and drawables but now also from hex color or color ID.
Check out this function from android Resources class. Resources.getResourceTypeName(int resid) (also this )
To find the resource type the safest solution is to use the below code
String viewName = findViewById(resourceId).toString();
String resourcetype = viewName.substring(0,viewName.indexOf("{"));
The resoucetype then contains the full classname for the resource, eg in case of EditText, it shows
android.widget.EditText
Tried some other ideas but noted that getResourceTypeName only returns 'id' as value and getTag() on View does not work in all conditions.

Where are the resources' IDs?

Android will allocate ids for each pics in the res/drawable directory. Where are they?
I want to dynamically choose one pic form the pool and show it. How can I do that?
They are stored in the res/drawable folder.
If the file name is demo.png, then they can be accessed by R.drawable.demo
If you want to access a random drawable, store all the resource identifiers in a Integer ArrayList, and programatically generate a random function using Random(), and get that particular item from the arraylist. Then you'll have a random drawable every time.
Autogenerated ids are in the gen file, but not advisable to use them. It would be better to use the filenames directly through some predefined array of R.drawable.filename and randomly pick them.
There IDs are stored in the R.java file, but you cannot edit it, as your changes are over written each time.
You can also access resources by name, which may be a viable approach to solving your problem if you know the names of the resources or can derive them according to some pre-defined naming scheme. (for example images are named in the sequence image1, image2 and so on.
You have to map the name to the identifier using the getIdentifier() method of the Resources class.
String name = "resource" + rng.nextInt(count);
int resource = getResources().getIdentifier(name, "drawable", "com.package");
The documentation for this method says:
Note: use of this function is
discouraged. It is much more efficient
to retrieve resources by identifier
than by name.
This is true but need not be a problem if you are doing it in code that isn't performance sensitive.
Alternatively, if you don't mind listing the resources in XML, you could create a typed array that you can then randomly select from.

how to iterate over all drawable of another APK's resources without knowing their resources name

I couldn't find how to list all drawable inside another app from my app.
I managed to get drawables if I know the name, but couldn't find how to do it with a simple loop from 1 to N.
Any of you could offer a code template to do this?
The following code already works:
mAndromedaAddonContext = createPackageContext( "com.demo.andromeda",
Context.CONTEXT_IGNORE_SECURITY );
mPlanetsResID[0] = mAndromedaAddonResources.getIdentifier( "planet20111007081421628", "drawable", "com.demo.andromeda" );
But I want to iterate without using the resource name.
Something along those lines:
for(int i=0; i
I do have the same sharedUserId and process in the manifest file, so I have the privilege to access the resources from the other app.
Thanks in advance.
First use mAndromedaAddonResources.getAssets() to get an instance of AssetManger for the app you are targeting.
see here:
https://developer.android.com/reference/android/content/res/Resources.html#getAssets()
Then you can use the
public final String[] list (String path)
method in AssetManager class to get a list of all assets at a given path( In your case, it would be the path of the res/drawable folder for the app you are targeting). This will give you a list of strings where each string is an asset name. Then you can simply use the same code you are using to obtain their identifiers.
For more info on AssetManager:
https://developer.android.com/reference/android/content/res/AssetManager.html

Categories

Resources