6

Is there any way I can add items in code to a String-Array resource? For instance, if I want to create a spinner that shows the user values, and I want to allow the user to add their own custom values.

Eliezer
  • 7,209
  • 12
  • 56
  • 103

2 Answers2

9

No. this is not supported because resources are packaged in the binary .apk and as such cannot be changed.

Don't follow this design pattern, change your approach.

JoxTraex
  • 13,423
  • 6
  • 32
  • 45
  • Would you suggest using a design where a database or file are used to store things like that? – Eliezer Feb 05 '12 at 14:19
  • 2
    A database would probably be the easiest to interface with, so yes, go with the database. It's what google does to save your previous searches and its how it brings them up in the list. – JoxTraex Feb 05 '12 at 19:31
5

probably JoxTraex has no idea on android framework or as they are saying:

when someone says this can't be done - there always is someone who doesn't know that and will do it :)

so to the point:

Resources is an open class is just a wrapper around ResourcesImpl class

(with depreciated constructor - but is available)

public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)

in app every call to it is made via Context

so:

1) you always can provide your own Resources implementation

2) or (when its enough) your own Context implementation (so sky is the limit)

... i now feel eyes on "Context implementation" - yeah you can even replace top most context in LoadedApk, Activity, etc.. yeah cool? but when, how? how: via reflections, when: good app designer knows that this place is where (before) first/any call to such object is made ...

But there is one dangerous catch here - in one case android straight unwrap Context to ContextImp and then you need to return those Context instead yours - where is the place that i'll keep as secret for those who like riddles :)

there is also in Resources

a) a hidden constructor (best entry point as it is not making any ReourceImpl (which can be set by method mentioned bellow)

public Resources(@Nullable ClassLoader classLoader) 

b) hidden method

setResImpl(ResourcesImpl) 

sum up:

so by calling

Resources.getStringArray(**not existing in APK resource id here**);

on our own implementation we could get whatcha want :)

even better we can add to our implementation

addResourceById(int,Object)

method and add new resources :) then with assign ability check on resource we will use and do a up casting to our implementation :) to use our newly added method :)

btw: if someone says to you "you shouldn't do it - blablabla" this is the best reason to do it! - if not permitted by law :)

enough the theory go to a practice:

example Context implementation forwards calls to getString:

    public class MyContext extends Context {
        ....
    // override context get resources method 
    @Override
    public android.content.res.Resources getResources() {
        // get super resources 
        android.content.res.Resources resources = super.getResources();
        // pull assets 
        android.content.res.AssetManager assets = resources.getAssets();
        // pull metrics 
        android.util.DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        // pull configuration 
        android.content.res.Configuration configuration = resources.getConfiguration();
        // construct new anon resource implementation 
        return new android.content.res.Resources(assets, displayMetrics, configuration) {

            // overrride interesting method 
            @android.support.annotation.NonNull
            @Override
            public String getString(int id) throws android.content.res.Resources.NotFoundException {
                return id == pl.ceph3us.base.common.R.string.my_sweet_google
                    ? "fck_you_google";
                    : super.getString(id);
            }
        };
    }

}
ceph3us
  • 7,326
  • 3
  • 36
  • 43
  • that's the spirit:D – eiran Jul 21 '19 at 23:42
  • Just because you can does not mean you should. You should consider the cost of maintaining such a enigmatic approach, which isn't directly supported. You can do anything, whether or not you should is what you should be asking. In this case, I can't say its worth the complexity. You also should consider that resources are used a part of resources access via AssetManager which is a framework built for resources, primarily static resources not dynamic. Keep in mind doing this may also break variations of resource qualifiers as well. Sounds too risky imo. – JoxTraex Aug 25 '19 at 02:20
  • @JoxTraex this is only the example that any door can be opened - but if it is worth to open them, which key use and how many resources it will cost you... but this is for another episode.... – ceph3us Aug 25 '19 at 05:09