web-dev-qa-db-fra.com

Comment puis-je obtenir un contenu de ressource à partir d'un contexte statique?

Je veux lire les chaînes d'un fichier xml avant de faire autre chose que setText sur des widgets. Comment puis-je le faire sans objet d'activité sur lequel appeler getResources()?

148
lost baby
  1. Créez une sous-classe de Application , par exemple public class App extends Application {
  2. Définissez l’attribut Android:name de votre balise <application> dans AndroidManifest.xml pour qu'il pointe vers votre nouvelle classe, par exemple. Android:name=".App"
  3. Dans la méthode onCreate() de votre instance d'application, enregistrez votre contexte (par exemple, this) dans un champ statique nommé mContext et créez une méthode statique qui renvoie ce champ, par exemple. getContext():

Voici à quoi cela devrait ressembler:

public class App extends Application{

    private static Context mContext;

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

    public static Context getContext(){
        return mContext;
    }
}

Vous pouvez maintenant utiliser: App.getContext() chaque fois que vous souhaitez obtenir un contexte, puis getResources() (ou App.getContext().getResources()).

345
Cristian

Utilisation

Resources.getSystem().getString(Android.R.string.cancel)

Vous pouvez les utiliser partout dans votre application, même dans les déclarations de constantes statiques! Mais uniquement pour les ressources système!

97
Gangnus

Il y a aussi une autre possibilité. Je charge les shaders OpenGl à partir de ressources comme ceci:

static private String vertexShaderCode;
static private String fragmentShaderCode;

static {
    vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
    fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}

private static String readResourceAsString(String path) {
    Exception innerException;
    Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
    InputStream inputStream = aClass.getResourceAsStream(path);

    byte[] bytes;
    try {
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        return new String(bytes);
    } catch (IOException e) {
        e.printStackTrace();
        innerException = e;
    }
    throw new RuntimeException("Cannot load shader code from resources.", innerException);
}

Comme vous pouvez le constater, vous pouvez accéder à n’importe quelle ressource du chemin /res/... Modifiez aClass en votre classe. Cela aussi comment je charge les ressources dans les tests (androidTests)

3
Gregory Stein

Le Singleton:

package com.domain.packagename;

import Android.content.Context;

/**
 * Created by Versa on 10.09.15.
 */
public class ApplicationContextSingleton {
    private static PrefsContextSingleton mInstance;
    private Context context;

    public static ApplicationContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized ApplicationContextSingleton getSync() {
        if (mInstance == null) mInstance = new PrefsContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }

}

Initialisez le singleton dans votre sous-classe Application:

package com.domain.packagename;

import Android.app.Application;

/**
 * Created by Versa on 25.08.15.
 */
public class mApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationContextSingleton.getInstance().initialize(this);
    }
}

Si je ne me trompe pas, cela vous accroche partout dans applicationContext, appelez-le avec ApplicationContextSingleton.getInstance.getApplicationContext();Vous ne devriez pas avoir à effacer cela à aucun moment.

N'oubliez pas de mettre à jour AndroidManifest.xml pour utiliser cette sous-classe Application:

<?xml version="1.0" encoding="utf-8"?>

<manifest
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="com.domain.packagename"
    >

<application
    Android:allowBackup="true"
    Android:name=".mApplication" <!-- This is the important line -->
    Android:label="@string/app_name"
    Android:theme="@style/AppTheme"
    Android:icon="@drawable/app_icon"
    >

Vous devriez maintenant pouvoir utiliser ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () de n'importe où, ainsi que des rares endroits où les sous-classes d'application ne peuvent pas.

S'il vous plaît laissez-moi savoir si vous voyez quelque chose de mal, merci. :)

3
Versa

Une autre solution:

Si vous avez une sous-classe statique dans une classe externe non statique, vous pouvez accéder aux ressources à partir de la sous-classe via des variables statiques de la classe externe, que vous initialisez à la création de la classe externe. Comme

public class Outerclass {

    static String resource1

    public onCreate() {
        resource1 = getString(R.string.text);
    }

    public static class Innerclass {

        public StringGetter (int num) {
            return resource1; 
        }
    }
}

Je l'ai utilisé pour la fonction getPageTitle (int position), fonction de FragmentPagerAdapter statique dans FragmentActivity, ce qui est utile en raison de I8N.

1
Stephan Brunker

Je charge shader pour OpenGL ES depuis une fonction statique.

N'oubliez pas que vous devez utiliser des minuscules pour votre nom de fichier et de répertoire, sinon l'opération échouera

public class MyGLRenderer implements GLSurfaceView.Renderer {

    ...

    public static int loadShader() {
        //    Read file as input stream
        InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");

        //    Convert input stream to string
        Scanner s = new Scanner(inputStream).useDelimiter("\\A");
        String shaderCode = s.hasNext() ? s.next() : "";
    }

    ...

}
0
user2174870

J'aime les raccourcis.

J'utilise App.getRes() au lieu de App.getContext().getResources() (comme @Cristian a répondu)

Quoi? Il est très simple d'utiliser n'importe où dans votre application!

Voici donc une solution unique grâce à laquelle vous pouvez accéder à des ressources n’importe où, comme Util class.

(1) Créez ou éditez votre classe Application.

import Android.app.Application;
import Android.content.res.Resources;

public class App extends Application {
    private static App mInstance;
    private static Resources res;


    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        res = getResources();
    }

    public static App getInstance() {
        return mInstance;
    }

    public static Resources getResourses() {
        return res;
    }

}

(2) Ajoutez un champ de nom à votre balise manifest.xml<application. (ou ignorer si c'est déjà fait)

<application
        Android:name=".App"
        ...
        >
        ...
    </application>

Maintenant vous êtes prêt à partir. Utilisez App.getRes().getString(R.string.some_id) n'importe où dans l'application.

0
Khemraj
public Static Resources mResources;

 @Override
     public void onCreate()
     {
           mResources = getResources();
     }
0
Makvin

Je pense qu’il ya plus de chemin possible… .. Mais parfois, j’utilise cette solution. (global complet):

    import Android.content.Context;

    import <your package>.R;

    public class XmlVar {

        private XmlVar() {
        }

        private static String _write_success;

        public static String write_success() {
            return _write_success;
        }


        public static void Init(Context c) {
            _write_success = c.getResources().getString(R.string.write_success);
        }
    }
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();
0
user2684935

Dans votre classe, où vous implémentez la fonction static , vous pouvez appeler une méthode private\public de cette classe. La méthode private\public peut accéder à getResources .

par exemple:

public class Text {

   public static void setColor(EditText et) {
      et.resetColor(); // it works

      // ERROR
      et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
   }

   // set the color to be black when reset
   private void resetColor() {
       setTextColor(getResources().getColor(R.color.Black));
   }
}

et depuis une autre classe\activité, vous pouvez appeler: 

Text.setColor('some EditText you initialized');
0
Erez Shmiel

J'utilise le niveau 27 de l'API et j'ai trouvé la meilleure solution après deux jours de difficultés. Si vous souhaitez lire un fichier XML à partir d'une classe qui ne dérive pas d'Activity ou Application, procédez comme suit. 

  1. Placez le fichier testdata.xml dans le répertoire assets.

  2. Écrivez le code suivant pour obtenir le document testdata analysé.

        InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml");
    
        // create a new DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // use the factory to create a documentbuilder
        DocumentBuilder builder = factory.newDocumentBuilder();
        // create a new document from input stream
        Document doc = builder.parse(inputStream);
    
0
Jnana

si vous avez un contexte, je veux dire à l'intérieur; 

public void onReceive(Context context, Intent intent){

}

vous pouvez utiliser ce code pour obtenir des ressources:

context.getResources().getString(R.string.app_name);
0
eren130