Resource Mirror

Additional

Language
Java
Version
1.0.0 (Jun 3, 2017)
Created
Mar 15, 2015
Updated
Nov 17, 2017 (Retired)
Owner
Alexandros Schillings (alt236)
Contributor
Alexandros Schillings (alt236)
1
Activity
Badge
Generate
Download
Source code

Resource Mirror

Were you ever in a situation where you had to access android Resources based on their names (for example if the names are stored in a DB) and you had to write long lookup tables converting the names into R.XXXX.ids? And maintaining them?

This library is offering a way around it by using reflection to access the Resource directly by name.

You only need to include them as normal into your Res folder tree. It uses LRU caching to mitigate the reflection time overhead. It also includes a few convenience functions to help change Drawable colour based on a hex colour value.

In essence, this is a suped up version of https://github.com/alt236/Reflective-Drawable-Loader---Android that deals with all Resource types instead of just Drawables.

Usage

This project is available as an artifact for use with Gradle. To use that, add the following blocks to your build.gradle file:

 repositories {
  maven {
   url "https://dl.bintray.com/alt236/maven"
  }
 }

 dependencies {
    compile 'uk.co.alt236:resource-mirror-android:1.0.0'
 }

Usage

Quick and easy

The most common use case would be to call on of the following:

Mirror.of(Context).getXXX().getResourceId("resourceName");
or
Mirror.of(Context).getXXX().optResourceId("resourceName", R.xxx.fallbackResource);

where XXX is the reource type (String, Drawable, Layout, etc.) The difference between the two calls are as follows:

Method Effect
getXXXId() will throw a android.content.res.Resources.NotFoundException if the resource is missing
optXXXId() will return the fallback resource passed as a parameter if the resource is missing

Accessing a different package

You can access the resources of a different package by calling

Mirror.of("packageNameBeforeR");

for example: Mirror.of("android") will give you access to the android.R.* Resources.

Additional Methods

You can also use the following method to get a Resource:

Mirror.of(Context).getReflector(ResourceType.XXX) where ResourceType is an enum.

If you only have the type of a Resource as a String, you can use the ResourceType.fromString() method to get its enum value.

For example the following command will try to fetch the id of a string called "hello"

Mirror.of(Context).get(ResourceType.fromString("string")).getResourceId("hello");

Geting a list of all resource names of a type

Simply call: Mirror.of(Context).getXXX().getResourceList()

Note that this will not add the found resources to the LRU cache

Resource families

The library is using a concept of resource families to distinguish between different variations of similar resoueces (of the same type). For example, icons in Android can come in a Holo Light and Holo Dark variant.

So, if you call optDrawableId("submarine", "yellow", R.drawable.ic_list_fallback) then the library will try to look for an icon called yellow_submarine and return its Id if it exists, or R.drawable.ic_list_fallback otherwise.

Similarly, if you call optDrawableId("submarine", null, R.drawable.ic_list_fallback) or getDrawableId("submarine", R.drawable.ic_list_fallback) then the library will try to look for an icon called submarine and return its Id if it exists, or R.drawable.ic_list_fallback otherwise.

Of course, nothing stops you from calling optDrawableId("yellow_submarine", null, R.drawable.ic_list_fallback) to get the yellow_submarine icon as well.

Helper methods for Drawables

In addition to the normal methods above, there are a number of helper methods for drawables.

Convenience Functions and Drawable naming conventions

The convenience functions in the library assume that Drawables are named using the convention described here Icon Design Guidelines.

So for example,

If you call getListDrawableId("submarine", "yellow", R.drawable.ic_list_fallback); then the library will try to look for an icon called ic_list_yellow_submarine and return its Id if it exists, or R.drawable.ic_list_fallback otherwise.

Colorising Drawables

If you ask for a Colorised Icon by calling getColorisedListDrawable("table", "furniture", "#c0c0c0", R.drawable.ic_list_fallback); instead of an Id you will get a DrawableResourceContainer object which will contain the Id of the Drawable to use, the colour to use as and Integer and a couple convenience functions to use to colourise the Drawable. If there was an error parsing the colour, the Integer will be null.

Also, the convenience functions do not apply the colorFilter to the Drawable directly, but to the ImageView holding it.

Feel free to expand the DrawableResourceContainer to add other colour filters or behaviours.

ProGuard

Proguard normally strips code that appears unused, and that includes fields under R.class that are only accessed reflectively. As a result, users must ensure that the R class, its inner R class and all fields are not obfuscated for the runtime reflection to work. Add the following to your your proguard-project.txt file:

    -keepattributes InnerClasses

    -keep class **.R
    -keep class **.R$* {
        <fields>;
    }

Changelog

  • v0.0.1 First public release
  • v1.0.0 Added Javadoc, android resource annotations, bugfixes

Permission Explanation

  • No permissions required

Links

Credits

Author: Alexandros Schillings.

Based on code by Jeff Gilfelt, who showed me that contrary to my academic reservations, reflectively loading resources is not that bad :)

All logos are the property of their respective owners.

The icons used for the example app were downloaded from here: Android Design

The code in this project is licensed under the Apache Software License 2.0.

Copyright (c) 2017 Alexandros Schillings.