35

I'm trying to put configuration, such as URLs/etc, into a resource folder for a utility class to use. However, I don't want to pass the Context from the activities everywhere. I would like to be able to access a resource via a path name (seems like assets/ was designed for this use), without using a context to access the resource.

In this particular case, I want a singleton to use something in configuration when it's instantiated. It has no need for anything from resources besides that one time during instantiation. Therefore, having to pass in a Context every time getInstance() is called would be a complete waste.

Also, this is specific to the App's configuration, and should not be in stored in a shared system file or anything like that.

Gangnus
  • 24,044
  • 16
  • 90
  • 149
mnemy
  • 669
  • 1
  • 9
  • 19

5 Answers5

91

Use

Resources.getSystem().getString(android.R.string.someuniversalstuff)

You can use it ABSOLUTELY EVERYWHERE in your application, even in static constants declaration! But for system resources only.

For local resources use that solution.

Gangnus
  • 24,044
  • 16
  • 90
  • 149
  • 54
    **But for system resources only.** – Youngjae Nov 18 '15 at 14:40
  • @Youngjae yes. And for local ones follow the reference. – Gangnus Nov 19 '15 at 00:07
  • I got an exception: android.content.res.Resources$NotFoundException: String resource ID – vinidog May 29 '16 at 18:50
  • 6
    this answer is misleading, the question was referring to local resources – Abhijit Jun 02 '16 at 17:13
  • @Abhijit There are two answers. If you don't like the first, follow the reference to the second one. So, it is not MISleading, on the contrary, it leads you to the correct solution. – Gangnus Jun 03 '16 at 17:00
  • I don't understand why this has so many upvotes and is the accepted answer when it answers a completely different question. – blimpse Apr 04 '23 at 14:33
  • @blimpse The question post contains two questions, one - in the header, and another - in the body. I am answering the first one and giving the reference to the best answer for the second one. It is totally up to the rules and customs of SO. Of course, the first, my answer, got pluses being a joke in fact. It is formally correct, but useful in rather special cases. :-) And it helps to understand Android better. – Gangnus Apr 26 '23 at 23:34
16

You could extend the main application class and provide universal helpers there to access resources. This relieves the need for context as the application would provide the context instead of the caller. The application class is singleton style and should always be available while any portion of your application is running (including services).

public class MyApplication extends Application {
 protected static MyApplication instance;

 @Override
 public void onCreate() {
  super.onCreate();
  instance = this;
 }

 public static Resources getResources() {
  return instance.getResources();
 }
}

This provides you access to:

MyApplication.getResources()....

Be sure to declare your custom application in your manifest to gain access to this. Assuming your custom application is in the root of your application's namespace:

<application
 android:name=".MyApplication"
 ... >
SandWyrm
  • 713
  • 9
  • 7
2

I would recommend doing the following: Rather than passing context everywhere make your activity class a singleton class with a public function that returns the context:

private static ActivityMain instance;

Initialize inside onCreate() before super.onCreate():

instance = this;

Then add these public functions to your activity:

/** Get singleton instance of activity **/
public static ActivityMain getInstance() {
    return instance;
}

/** Returns context of this activity **/
public static Context getContext(){
    return instance.getApplicationContext();
}

Now you can use the following anywhere in any class:

Context context = AntiMorphActivity.getContext();
String packageName = context.getPackageName();
int id = context.getResources().getIdentifier("web_page", "raw", packageName);
dwp4ge
  • 1,963
  • 22
  • 27
1

Unfortunately I don't think there is a real way around this. I lay mine out something like this, and also pass in the getApplicationContext() instead of the activity context.

public static AppController getAppController(Context context){
    if(self == null) {
        //Create instance
        self = new AppController();
    }

    return self;
}

And then:

appController = AppController.getAppController(getApplicationContext());
sgarman
  • 6,152
  • 5
  • 40
  • 44
  • Ohh well, I was afraid that was going to be the answer. It seems like pretty bad design to only be able to access app resources from contexts. I'm sure there are reasons for it... but it's annoying none-the-less. Thanks for confirming it =) – mnemy Apr 07 '11 at 00:50
  • 1
    My team and I complain all the time. It makes it hard to write uncoupled modular code. – sgarman Apr 07 '11 at 01:18
0

The stackoverflow answer to the question below shows how to use POJO to obtain a stream to a resource, if you supply its path. This might be useful in cases you need to select a specific resource from one of many.

Is it possible to read a raw text file without Context reference in an Android library project

Community
  • 1
  • 1
andrew pate
  • 3,833
  • 36
  • 28