Ways to avoid using getIdentifier to retrieve text resources? - android

I noticed that on the android developer page for getIdentifier it states:
Note: use of this function is discouraged. It is much more efficient to retrieve resources by identifier than by name.
I'd like to try to avoid using it but my current implementation depends on it.
In my database I have hundreds of prepopulated entries, for each entry there are 3 associated string resources and an image. In order to access the resources via the entry, I save the resource names as strings in the tuple and then use getIdentifier to load them.
In case my implementation is confusing here are some pictures and example code:
string resources file
database table
Example Code:
coin = model.getSelectedCoin()!!
binding.topMedia.setImageResource(
resources.getIdentifier(coin.imageAddress, "drawable", requireContext().packageName)
)
binding.descriptionText.text = resources.getString(
resources.getIdentifier(coin.description,"string", requireContext().packageName)
)
Is this bad practice? Is there a more efficient implementation that allows me to connect my database entries with their resources?

You can get text resource from assets folder or from res/raw folder in two ways (let's assume your file name is product_json.json)
You can put a file with file name product_json in res/raw folder and access as below.
val inputStream: InputStream = resources.openRawResource(R.raw.product_json)
Or, you can put your file in assets folder (if not exist already then you're welcome to create one!) as access as below.
val inputStream: InputStream = assets.open(getString("product_json")
Note: assets.open("file_name_with_extension)e.g., assets.open("product_json.json")
Using point number 1 above is faster than accessing resources using val inputStream: InputStream = resources.openRawResource( resources.getIdentifier(getString(R.string.product_json), "raw", packageName) as getIdentifier() has to go through the iteration over all the string resources. This is very slow and not recommended, thus, IDE static analyzers show the warning of "Use of this function is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code. It is much more efficient to retrieve resources by identifier (e.g. R.foo.bar) than by name (e.g. getIdentifier("bar", "foo", null))". Using val inputStream: InputStream = resources.openRawResource(R.raw.product_json) is better because system has to just iterate over raw resources.

Perhaps you could be setting those values outside of a database? Create an object that describes your level, and define the image and description on that object using their resourceIds. Those are basically UI-related values, they shouldn't be in a database at all.

Related

Resources.getIdentifier(), possible values of deftype argument?

I'm trying to understand an Android app that performs computations on investment portfolios. The portfolios are stored in res/values/portfolio.xml:
When a button is pressed in the app, the portfolio data is retrieved as follows:
String portfolioName = ((TextView) findViewById(R.id.portfolioName)).getText().toString();
Resources res = getResources();
String[] data = res.getStringArray(res.getIdentifier(portfolioName, "array", this.getPackageName()));
I found the Android documentation on the String Array resource type that explains the syntax of the portfolio.xml file, and it explains why the name attribute should be used as the first argument of getIdentifier():
“The filename is arbitrary. The <string-array> element's name will be used as the resource ID.”
But I haven't found any documentation that explains how you know what you're supposed to put for the defTypeargument of getIdentifier (other than that it's a string). In the provided example, "array" works, but where does it come from? And what are the possible values of 'defType' in general?
getIdentifier returns the id of the resource for the given resource name. typeDef refers to the type of the Resource (read more here). Keep in mind that the content of res is parsed at compile time and the R.java class is generated from the result of this parsing. In the end what you are looking for is a field declared in that class. I don't know the internal implementation, but if you provide array as res type, android will look up only on R.array, instead than on the whole R

Get resources by int number

I sometimes see this declarations in Android source code:
mContext.getString(2131361954);
Notification n = new Notification(2130837696, "123", System.currentTimeMillis());
// Example code - does not match together
I think the numbers are some resources from the project, right? Why sometimes people work with this numbers instead of using the R class? Is it faster or something else?
And how can I check which resource is assigned to that numbers? Is it possible to get number which is used if I only have the file or is this number random? Maybe with the file name or the MD5 hash of the file or something else?
There is no performance difference, as all members of the R class are static and final, and are directly swapped in during compile time. This is equivalent to any code that uses R.x.y, so the performance is the same.
I would strongly recommend against using the numbers directly in your project as they may change during the addition, removal and modification of resources.
You can check the resource to which that number corresponds by converting it to hex, opening up the R.java file and searching for that hex number and seeing what it is assigned to.
You can also use getResources().getResourceEntryName(int resid); and pass it the ID at runtime to retrieve the file name.

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

Sorting Images on Android

I need images to be sorted by folders. like drawable/Photos, drawable/items, drawable/photos. and put each folder to the registry or at least find way to get them out of there. all I want is something close to php like "../img/photos/photo0.jpg". is there way to do something like this. and folder with Images must contain in apk file.
possible solutions is make link in the R file but I didn't find how to do it, other solution is find command with logic like I will show you here:
ImageView img = (ImageView)CloningTable.findViewById(R.id.img);
String ImgPath = "com.test.test/img/img0.jpg";
img.setImageDrawable(Drawable.createFromPath(ImgPath));
OR
ImageView img = (ImageView)CloningTable.findViewById(R.id.img);
String ImgPath = "com.test.test/img/img0.jpg";
img.setImageResource(ImgPath);
please say me the best way to handle it. AND specify if it contain path how I can know path the file lies in.
File ImgFile = new File("test/test.jpg");
TextView testtext = (TextView)CloningTable.findViewById(R.id.testtext);
if (ImgFile.exists()) {
test.setImageBitmap(BitmapFactory.decodeFile(ImgFile.getPath()));
testtext.setText("asdasuidjasdk");
}
can any one say Why programm can't find file and file exist 100% = /?
filepath: Project> assets/test/test.jpg
found solution: Android Show image by path
It's hard to understand why you need to sort resources that will be static in your APK, but you should not access them directly using paths, but using the API for that purpose.
Take a look at the topics in the dev guide here:
http://developer.android.com/guide/topics/resources/accessing-resources.html
http://developer.android.com/guide/topics/resources/drawable-resource.html
Those will teach you how to access the resources. To create Bitmaps from them, the easiest way is to use the BitmapFactory class
Remember, you know which resources the APK has at building time, so you can work around it. If you want to work with Bitmaps created at runtime, then use the data storage methods instead.
In this case, you should put resources in assets folder, and you can access them by path!
So if you want to save the path string, the best way is creating a class, with 2 variants: 1 Bitmap to store data, and 1 String to store the path.
If not, just create a String array that you may access when you want.
In both case, you need to put the path into the Path String storage before you load the image.
Hope I understood your question.
EDIT: Final answer that meet your requirement:
There's no path for drawable, they are all converted into ID. If you put in asset folder, just call it by their name. For example, you have "Test.bmp" in asset folder, its path is "Test.bmp". If you have "SubTest.bmp" in "TestFolder" in asset folder, its path is "TestFolder/SubTest.bmp". Sorry for long time, I had to sleep, it was mid night at my time zone.

Categories

Resources