Why can't I use Resources.getSystem() without a Runtime error? - java

public class BobDatabase extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "bob.db";
private static final int DATABASE_VERSION = 1;
public static final String DEFAULT_PROFILE = "default_profile";
public BobDatabase(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database)
{
createProfileTable(database);
createTimeTable(database);
createEventTable(database);
createLocationTable(database);
}
/**
* Creates a table for Profile objects, executes the string create_profile_table_sql
* contained within strings.xml
* #param database
*/
public void createProfileTable(SQLiteDatabase database)
{
database.execSQL(Resources.getSystem().getString(R.string.create_profile_table_sql));
}}
I get this error
01-14 12:20:57.591: E/AndroidRuntime(1825): Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x7f040003
The code that causes the error is the single line inside createProfileTable specifically, Resources.getSystem().getString(R.string.create_profile_table_sql) if I use a class variable to hold a Context and do context.getString(R.string.create_profile_table_sql) I don't get any errors but I don't want to do that because I want to avoid memory leaks and according to what I know this should work. Any idea what's happening?

According to Android documentation, Resources.getSystem() only provides system-level resources, not application-level ones (like the resources inside your strings.xml file).
http://developer.android.com/reference/android/content/res/Resources.html#getSystem()
Try using the application's context if you really want to retrieve your strings this way, or take my suggestion in the comment to your question.

Using Resources.getSystem().getWhatEver() you can only access system-wide resources (you get the error because there is no system-wide resource with your ID). Since resource ID are not unique across applications you need to provide the application, when accessing a resource. In Android this is done using Context.
So if you want to access some resource you need to use it like this
context.getResources().getString(myID);
Apart from that Brandon's comment is correct.

You could get the context parametr in the function by parameter, or by a static variable, or by getApplicationContext() function.

Related

"Cannot resolve method getResources" when trying to execute getResources in non-activity method using method widely advocated here

I have been trying to use getResources in a non-activity class. I found some advice on how to do so here. To use one of the suggested ways, by Lilzilala, (there are multiple, but mostly suggest the same thing), I have created a special class, used this to specify the resources as "res", and then instantiated this class using "new" in a line which invokes "getResources".
However, I'm getting a "cannot resolve method getResources" error on "getResources". I'm a bit of a noob, but don't know why this is happening. From what I can tell, this error happens when there simply isn't a resource with that name available. Which makes me think maybe Resources doesn't contain getResources() by default?
class executeTrimmer<Resdefine> {
public class ResDefine {
private Resources res;
public ResDefine(Resources res)
{
this.res = res;
}}
Bitmap img1 = BitmapFactory.decodeResource(new ResDefine(getResources()),
R.drawable.bmpname);
}
EDIT - following suggestions that I add context, I have tried this:
class executeTrimmer<Resdefine> {
private static Context context;
public executeTrimmer(Context context){
this.context = context;
}
public class ResDefine {
private Resources res;
public ResDefine(Resources res)
{
this.res = res;
}}
Bitmap img1 = BitmapFactory.decodeResource(new ResDefine(executeTrimmer.context.getResources),
R.drawable.bmpname);
But this still brings up error "cannot resolve symbol getResources". I've tried multiple different ways to pass context to it, and consistently faced the same error.
As you can see in the official documentation, "getResources" is Context's method, therefore you can't call it out from nowhere, neither statically. This method requires a context instance.
In your case you must at least pass a context to your class to be able to invoke it as next:
context.getResources()
I think you got confused from seen it being directly called inside Activities without a prefixed context, but as all Activities are actually a context, this is why there is no prefix.
To clarify. When called inside an activity, this:
getResources()
is the same as this:
this.getResources()
where the prefix "this." refers to the activity, which in turn is a context by itself.
On the other hand your code should be like next, without the ResDefine class. And notice that the decodeResource call is required to be inside a method and not at class level scope (this is not allowed in Java). And in fact you don't even need to use a context, so pass instead the Resources instance from the caller's class which is supposed to hold the context:
public class executeTrimmer {
private final Resources res;
public executeTrimmer(final Resources res) {
this.res= res;
}
public void loadBitmap()
Bitmap img1 = BitmapFactory.decodeResource(this.res, R.drawable.bmpname);
........
}
}
And for the caller, next a very naive example, so may get an idea:
public class MainActivity extends Activity {
#Override
protected void onCreate(#Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new executeTrimmer(this.getResources()).loadBitmap();
}
}

Getting String Array in Android from .xml using Resources.getSystem()

I am trying to convert string-array from strings.xml to array in Java class
(the model part of MVC), there-for I cannot use getResources().getStringArray(R.array.array_name);
(it works only in Android components such as activity, fragment and so on).
So I can use only Resources.getSystem().getStringArray(R.array.array_name);
but When I try to run it in the emulator, I get an exception.
I found similar questions that referred that problem here. but I didn't understand the solution.
Here my exception:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.danirg10000gmail.therpiststep1/com.danirg10000gmail.therpiststep1.MainActivity}: android.content.res.Resources$NotFoundException: String array resource ID #0x7f0b0000
(My exception is same as in the link above.)
In my code I have two classes one class represents questions, another class have a list of questions objects.
Here is my code:
public class QuestionM {
private String mQuestion;
private String mAnswer;
private String mExplanation;
//constructor
public QuestionM(String question,String explanation) {
mQuestion = question;
mExplanation = explanation;
}
public class QuestionnaireM {
private List<QuestionM> mQuestionsList;
//constructor
public QuestionnaireM(){
mQuestionsList = new ArrayList<>();
Resources resources = Resources.getSystem();
//when i creating object of that class android points the crush here
String [] questions = resources.getStringArray(R.array.test);
String [] questionExplanations = resources.getStringArray(R.array.test_a);
for (int i=0; i<questions.length; i++){
QuestionM question = new QuestionM(questions[i],questionExplanations[i]);
mQuestionsList.add(question);
}
}
also I didn't quite understand the difference between system-level resources, and application-level resources, I search it in androidDevelopers and in Google but not found any good explanation. can somebody please explain that?
One suggestion, not sure if it will work. But you can try and let me know. Why not get the context in QuestionM constructor and initialize your class level context variable with the received context. Now use this context to
mContext.getResources().getStringArray(R.array.array_name);
public class QuestionM {
private String mQuestion;
private String mAnswer;
private String mExplanation;
private Context mContext;
//constructor
public QuestionM(String question,String explanation, Context context) {
mQuestion = question;
mExplanation = explanation;
mContext = context;
}
public class QuestionnaireM {
private List<QuestionM> mQuestionsList;
//constructor
public QuestionnaireM(){
mQuestionsList = new ArrayList<>();
//when i creating object of that class android points the crush here
String [] questions = mContext.getResources().getStringArray(R.array.test);
String [] questionExplanations = mContext.getResources().getStringArray(R.array.test_a);
for (int i=0; i<questions.length; i++){
QuestionM question = new QuestionM(questions[i],questionExplanations[i]);
mQuestionsList.add(question);
}
}
According to the docs getSystem() does this:
Return a global shared Resources object that provides access to only
system resources (no application resources), and is not configured for
the current screen (can not use dimension units, does not change based
on orientation, etc).
Therefore calling getStringArray() with the resource Id R.array.test is totally useless since the id referenced is that of an Application resource.
If you want to load the contents of R.array.test, use getStringArray() from getResources().
You can pass a parameter of type Resources to the constructor or String[]. i.e. :
public QuestionnaireM(Resources resource) {
// stuffs
}

Android application creation of internal file that isn't in an activity

I am trying to create an internal file in an android application. I have generated the code that works fine with java, but in order to create the internal file I believe I must have the context to do so.
Example: File file = new File(Context.getFilesDir(), "somefile.txt");
The problem I am running into is that the file creation and checks if it is made are maintained in a singleton class that I have created. When using the following
Example: File file = new File("somefile.txt");
everything seems to compile and work, but after closing the application it seems the file wasn't created. This leads me to believe that I need the application directory using the 1st example given. The problem is how do I get the applications context within a single class?
The problem is how do I get the applications context within a single class?
From Android Docs:
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
Create your singleton like this:
// ...
private Context mAppContext = null;
private static MySingleton mSingleton = null;
// ...
private MySingleton(Context context) {
mAppContext = context;
// ... other initialization
}
public static MySingleton get(Context context) {
if (mSingleton == null) {
/*
* Get the global application context since this is an
* application-wide singleton
*/
mSingleton = new MySingleton(
context.getApplicationContext());
}
return mSingleton;
}
The each time you obtain your singleton from any activity, you have access to the global application context.
You can use it for your creation of files within your singleton like:
public void createFile(String filename) {
File file = new File(mAppContext.getFilesDir(), filename);
}
Or you can use the other ways mentioned here
Or you could extend Application class thats already a Singleton. It can be rather usefull :)
package com.example.myapp;
import android.app.Application;
import android.content.Context;
public class MyApp extends Application {
private static Context context;
private static MyApp my_instance;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
my_instance = this;
context = this;
}
public static synchronized MyApp getInstance() {
return my_instance;
}
public static synchronized Context getContext() {
return context;
}
}
The mehod:
new File("filename")
does not create a file on disk.
You need to open the file and write to it for the file to be created, or use
File.createNewFile

android: Use openOrCreateDatabase from within non activity class

I am creating a new class for database, the first function is to access the database
the problem is that I always get error on MODE_PRIVATE
I tried to pass the context as parameter but still shows error
anyone know how to access the database from a non activity class
public class DB {
public void OpenDB(Context ctx, SQLiteDatabase dataB)
{
dataB = openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
}
}
Change
dataB = openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
to
dataB = ctx.openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);
openOrCreateDatabase is a method of Context class so you need a object of Context to call it.
use context to open databse ctx.openOrCreateDatabase("Schlogger", ctx.MODE_PRIVATE,null);

Exporting SQLite Tables in XML

Situation: I am trying to export my SQLite Tables to a XML file and have followed this answer as well as a post deleted from here and also this question (apparently both last links from the same author :) )
Update-2: I already have another class named DBAdapter which extends the SQLiteOpenHelper. So I have this:
public DBAdapter(Context ctx) {
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/*...*/
onCreate()
/*...*/
onUpgrade()
/*...*/
}
already in my DBAdapter class file. How can I reuse this?
Also, I tried passing as:
DataXmlExporter dm = new DataXmlExporter(SQLiteDatabase
Database(getReadableDatabase ()));
But still got an error.
Update-1: I used the 2nd Link to implement my solution.
Problem: I am getting a Null Pointer Exception; I guess because I haven't initialized my object correctly. At the time of calling the DataXmlExporter / exportData method what is supplied as parameter? : DataXmlExporter dm = new DataXmlExporter(WHAT_IS_PASSED_HERE?);
Thanks..
looks like you need an SQLiteDatabase.
for example you can get one with getReadableDatabase() or with getWritableDatabase().
If you implemented DatabaseAssistant like in the first link you provided you have as constructor parameter a reference to a SQLiteDatabase....
You need to pass SQLiteDatabase Database ( getReadableDatabase () ):
As per constructor
public DataXmlExporter(final SQLiteDatabase db) {
this.db = db;
}
And as per comments:
Android DataExporter that allows the passed in SQLiteDatabase
to be exported to external storage (SD card) in an XML format
What I did was to extend the SQLiteOpenHelper inside the DatabaseAssistant class and used it.

Categories