Read assets of an app from a library (jar)

7

What a community. Let's see if someone gives me a hand in this. I happen to be working on organizing the repetitive and reusable codes in a library of my own and the intention is to distribute it in the factory in jar format as is normal. Everything is fine but I have a particular case with one of the classes that I am migrating; I have a class that is responsible for writing a series of reports of user activities of the system (a kind of monitoring), what I want to do is the following: make the name (among other things) of the logs file configurable, I thought about taking this configuration from a json file that is located in the assets of the project of whoever uses the library, not in the assets of the library.

EDIT: I edit my question so that it is better understood

In each each class that must register use events, an instance of the monitor is done in the following way:

public class MainActivity extends Activity {

Logit logger = Logit.getInstance(this.getClass());
...// onCreate(), etc ...
}

The instance is made even from classes that do not extend from Activity, for example from a SQLite DataBaseHelper.

The constructor of the Logit class is the following:

public static Logit getInstance(Class<?> clazz) {
    if (log == null)
        log = new Logit();

    try {
        AssetManager manager = Resources.getSystem().getAssets();
        InputStream is = manager.open("logit.cfg");
        String input = new Scanner(is, "UTF-8").useDelimiter("\A").next();
        JSONObject json = new JSONObject(input);
        String file = json.getString("filename");
        boolean showv = json.getBoolean("showAppVersion");
        log.setFileName(file);
        log.setShowVersion(showv);
        log.setClassName(clazz.getCanonicalName());
        return log;
    }catch(Exception e) {
        log.write(Logit.stringStackTrace(e));
        return log;
    }
}

What interests me is to keep the argument really necessary at the time of the instance ( Class<?> ) and the location of the line of the instance is not feasible to locate references to AssetManager of the host app to locate the resource , that's why my interest in finding a way to locate the repeatable configuration silently through a configuration file. The question is how can I from the library take a configuration that exists in the project that uses the library, specifically the assets? I do not like the idea that the developer has to open the jar to modify the settings to his liking. A clear example of the goal is to emulate a configuration like that of log4j. Greetings to all!

    
asked by Rosendo Ropher 21.01.2016 в 23:06
source

3 answers

4

We create a class to load the properties, I have done it for a file of type key-value like a properties, you do it for a JSON:

public class PropertiesLoader { 
  private Context context;
  private Properties properties;

  public PropertiesReader(Context context) { 
    this.context = context;
    properties = new Properties();
  }

  public Properties getProperties(String fileName) {
    try {    
      //Accede al directorio asset 
      AssetManager am = context.getAssets(); 
      InputStream inputStream = am.open(fileName); 
      properties.load(inputStream);
    } catch (IOException e) { 
       //traza el error
    }
    return properties;
  }
}

Now we adapt your Logit class to use this new class

public static Logit getInstance(Class<?> clazz, Context context) {
  if (log == null)
    log = new Logit();

  try {
    PropertiesLoader loader=new PropertiesLoader(context);
    Properties logitProperties=loader.getProperties(logit.cfg);

    // :TODO cargar propiedades en logit
    //yo lo hize para un fichero tipo properties tu hazlo para un fichero JSON
    ......
    return log;
  } catch(Exception e) {
    log.write(Logit.stringStackTrace(e));
    return log;
  }
}

This class will be implemented by the developer

public class MainActivity extends Activity {

  //Añadimos el nuevo parametro al constructor
  Logit logger = Logit.getInstance(this.getClass(),this);
  ...// onCreate(), etc ...
}

I hope it works for you ...

    
answered by 13.04.2016 в 12:32
0

I searched the web, try that

getResources().getIdentifier("res_name", "res_type", "com.library.package");

a R.id.settings is accessed:

getResources().getIdentifier("settings", "id", "com.library.package");

Extracted from StackOverflow

    
answered by 13.04.2016 в 11:50
0

You may find these methods useful.

public class MainActivity extends AppCompatActivity {

    BufferedReader br;

    EditText editTextName;

    private final String FILENAME = "properties.xml";
    Properties properties;


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.editTextName = (EditText) this.findViewById(R.id.editTextName);

        this.loadAssetFile();
        this.loadRawFile();

        this.properties = new Properties();

        File file = new File(getFilesDir(), FILENAME);
        try {
            if(file.exists()) {
                FileInputStream fis = openFileInput(FILENAME);
                this.properties.loadFromXML(fis);
                fis.close();
            } else {
                this.saveToStorage();
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public void saveToStorage() throws Exception {
        FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
        this.properties.storeToXML(fos, null);
        fos.close();
    }

    public void saveToProperties(View v) {
        this.properties.setProperty("name", this.editTextName.getText().toString());
        Toast.makeText(this, "Saved", Toast.LENGTH_SHORT).show();
    }

    public void loadFromProperties(View v) {
        this.textViewName.setText("Welcome " + this.properties.getProperty("name") + "!");
    }

    public void loadAssetFile() {
        try {
            AssetManager manager = getApplicationContext().getAssets();
            InputStream is = manager.open("asset.txt");
            InputStreamReader isr = new InputStreamReader(is);
            this.br = new BufferedReader(isr);
            String currentLine;
            if((currentLine = this.br.readLine()) != null)
                this.greetingAsset.setText(currentLine);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void loadRawFile() {
        try {
            InputStream is = getResources().openRawResource(R.raw.raw);
            InputStreamReader isr = new InputStreamReader(is);
            this.br = new BufferedReader(isr);
            String currentLine;
            if((currentLine = this.br.readLine()) != null)
                this.greetingRes.setText(currentLine);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
    
answered by 19.10.2016 в 19:44