NullPointerException trying to access a String resource - java

I have the following /res/values/uris.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="bladder">blahblah</string>
</resources>
I am accessing it in code:
private String bladderUrl= getString(R.string.bladder);
But it is returning null. I'm not sure why?

My guess you placed bladderUrl smth like this:
public class YourActivity extends Activity {
private String bladderUrl = getString(R.string.bladder);
#Override
public void onCreate(Bundle savedInstanceState) {
...
However you need to do smth like this:
public class YourActivity extends Activity {
private String bladderUrl;
#Override
public void onCreate(Bundle savedInstanceState) {
bladderUrl = getString(R.string.bladder);
...

First of all to clear that up. You don't have to have all your strings in strings.xml. Period.
Emmanuels answer is partially right. You have to get the string inside your onCreate() method when the context is initialized. His answer is only partially correct since he also mentioned that you have to have the strings inside the strings.xml which is not true.

First, make sure these values are in the file strings.xml.
Also, you can't access the strings from the constructor. The application context is not yet initialized. You should do it in onCreate().
Emmanuel

Related

Android, why I cant call my stringarray inside a method outside of onCreate?

Outside my onCreate method my stringarray isnt able to be called , why is that ?
I tried to initialize the stringarray again in the method outside onCreate with getResources(); but I cant call that either,
im guessing there is some fundemental knowledge im lacking as im fairly new in the programming world, can u help me or explain why the string array can't be called outside onCreate and/or how to work around it ?
example inside onCreate :
final String[] list = res.getStringArray(R.array.fact);
outside onCreate :
public void facts(){
getResources();
final String[] list = res.getStringArray(R.array.fact);
}// marked res. in red saying "qualifier must be an expression" and without that I cant call "list"..
I believe your issue is variable scope. You've declared your string array in the onCreate() method, giving it "method scope" and then you're tying to access it in another method. I would suggest declaring your string array as a class level variable so that you can access it from any method within that class.
To avoid the NullPointerException issue pointed out by Ben P. in a comment, you could initialize your array variable in the onResume() method so that you have it ready to go before you need to use it anywhere else.
Make sure to take a look at the reference links below the code example. I think they'll help explain "why" better than I can in a quick answer here.
public class MainActivity extends AppCompatActivity {
private static String[] list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
// onResume() runs after onCreate() and onStart() in the Android Activity lifecycle.
// If your array has not been initialized yet, do it now.
if (list == null || list.length == 0) {
list = getResources().getStringArray(R.array.fact);
}
}
public void facts() {
// Do something with your array...
for (String arrayItem : list) {
String fact = arrayItem.toUpperCase();
}
}
}
References:
The Activity Lifecycle: https://developer.android.com/guide/components/activities/activity-lifecycle
Variable scope: https://www.java-made-easy.com/variable-scope.html
Replace
final String[] list = res.getStringArray(R.array.fact);
by
final String[] list = getResources().getStringArray(R.array.fact);

Using getIdentifier() to Find ID of Image

I am trying to get id of an image by using following code.
public class MovieActivity extends ActionBarActivity {
private Context con;
String name = "test";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
con = MovieActivity.this;
setContentView(R.layout.activity_movie);
}
public void updateScreen(){
int imageResource = con.getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
}
}
When I run it, I get exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
I thought the problem was Context so I added con variable which gets context when code runs. I made some researches and tried another methods but I got same exception every time. Can anyone help me?
EDIT: When I use the same code line in MainActivity, it works perfectly. But in another class, it fails.
public class SomeMovie extends MovieActivity { }
public class MainActivity extends ActionBarActivity {
protected void onCreate(Bundle savedInstanceState) {
SomeMovie movie = new SomeMovie();
movie.updateScreen();
}
}
SomeMovie class is child of MovieActivity class. I call the method on that. I debugged the code and noticed that Context is null when code gets into updateScreen() method. Is it wrong to use inheritance on activity classes?
Change
int imageResource = con.getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
to
int imageResource = getResources().getIdentifier("drawable/" + name , null, con.getPackageName());
You are already in an Activity's context, so use it. (No need to use the this keyword to refer to it)
EDIT:
You are not defining a layout for the SomeMovie Activity, so its context is always null.
You have to define the activity's layout in its onCreate method :
public class SomeMovie extends MovieActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.somemoviexml);
...
}
}

How do I get a string from string.xml in Java using Android SDK?

Before I ask, I've already looked at this post and tried all suggestions to no avail. My problem is that I can easily set a String using
getResources().getString(R.string.example)
within the onCreate method, but I want to set a public static final String to a value in string.xml using the same getResources() method. But, when I do this, I get a "Cannot make a static reference to the non-static method getResources() from the type ContextThemeWrapper". So I tried instantiating ContextThemeWrapper and also
this.getResources().getString(R.string.example)
which both clear the error, but both crash with a NullPointerException. Any solution to simply set a String from a resource would be much appreciated.
So far I have this:
public class MainActivity extends Activity {
ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper();
public final String CYPHER = contextThemeWrapper.getResources().getString(R.string.cypher_txt);
public static final int LAYERS = 7;
public static final int FLIP = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String appName = getResources().getString(R.string.app_name);
Toast.makeText(this, "Welcome to " + appName, Toast.LENGTH_SHORT).show();
}
What you need is a static Context object. For that, you can use the application context.
Assuming your application manifest is as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.app.package" ...
<application android:name=".MyApp" ...
1) Create an application class with a public static method to return this context.
package my.app.package; // This should match the package path in your Manifest
public class MyApp extends android.app.Application { // This should match the app name in your manifest
private static MyApp appContext;
public MyApp() { appContext = this; }
public static Context getAppContext() { return appContext; }
}
2) Then in your activity, you can make statically obtain the context and resolve the resource:
public final String CYPHER = MyApp.getContext().getResources.getString(R.string.cypher_txt);

Using Themes in Android

Im trying to switch between Holo.Light and Holo (Dark) so everything in my application is changed to the theme the user sets in the preferences.
I've been looking at a few open source apps that this is done in and cant seem to make it work with my project, Any help on this would be greately appreciated.
The Current ISSUE im running into inside DashboardActivity.java is:
"I've having issues with "setTheme(Integer.parseInt( pref.getString("
DashboardActivity (Updated)
public class DashboardActivity extends Activity {
public static final int THEME_BLACK = R.style.DarkThemeAndroid;
public static final int THEME_WHITE = R.style.LightThemeAndroid;
public static final int THEME_WHITE_BLACK = android.R.style.Theme_Holo_Light_DarkActionBar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I've having issue with the "pref.getString" i've tried "Settings.getString" and get error about needing a getString method is needed in Settings.java
setTheme(Integer.parseInt( pref.getString("selectedTheme", String.valueOf(R.style.LightThemeAndroid) )));
setContentView(R.layout.dashboard_layout);
// the rest of my code
)
)
Settings (Updated)
public class Settings extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
final static String[] mThemeEntries = {
"Default (Light)",
"Dark"
};
final static String[] mThemeValues = {
String.valueOf(R.style.LightThemeAndroid),
String.valueOf(R.style.DarkThemeAndroid)
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Loads the XML preferences file.
addPreferencesFromResource(R.xml.settings);
// SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
ListPreference listPref = (ListPreference)findPreference("selectedTheme");
listPref.setEntries(mThemeEntries);
listPref.setEntryValues(mThemeValues);
listPref.setValue( pref.getString("selectedTheme", String.valueOf(mThemeValues[0]) ) );
XML Resources
Themes.xml
<style name="LightThemeAndroid" parent="android:style/Theme.Holo.Light">
</style>
<style name="DarkThemeAndroid" parent="android:style/Theme.Holo">
</style>
Settings.xml
<ListPreference
android:title="Themes"
android:summary="Change the UI of the application"
android:key="theme"
android:entries="#array/themesReturnValue"
android:entryValues="#array/themesDisplayWord"
android:defaultValue="Theme1" />
Arrays.xml
<string-array name="themesReturnValue">
<item>Light</item>
<item>Dark</item>
<item>LightActionBar</item>
</string-array>
<string-array name="themesDisplayWord">
<item>Theme1</item>
<item>Theme2</item>
<item>Theme3</item>
</string-array>
getTheme() is a non-static method and you are trying to call it in a static way (not from an instance variable). You need an instance of the object to call the non-static method. Also, the docs state
Note that this should be called before any views are instantiated in the Context (for example before calling setContentView(View) or inflate(int, ViewGroup)).
Docs
There exists non-static getTheme() method of the ContextThemeWrapper class that returns Theme object type. Change the name of the getTheme() method to a different one for example getThe() and you should be fine.
First like codeMagic said, you are calling getTheme in a non-static way, I would also put the theme related constants in 1 class. Try making getTheme a static method (Although i would probably create a seperate class just for theme). Apart from that, here is a solution I was working on 2 days ago as i couldn't find anywhere on google or here for an answer to a more dynamic fluid theme preference.
I start off with my preference fragment (in your case, activity). Then declare the themes and values into an array...
public class LayoutFragment extends PreferenceFragment {
final static String[] mThemeEntries = {
"Default (Light)",
"Dark"
};
final static String[] mThemeValues = {
String.valueOf(R.style.Theme_Default),
String.valueOf(R.style.Theme_Dark)
};
then in my oncreate method, i set these values (note, in the xml i do not set these values and there are no references to those values in the xml files)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_layout);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
ListPreference listPref = (ListPreference)findPreference("selectedTheme");
listPref.setEntries(mThemeEntries);
listPref.setEntryValues(mThemeValues);
listPref.setValue( pref.getString("selectedTheme", String.valueOf(mThemeValues[0]) ) );
}
Notice that i had converted these values to a string, dont ask why, but i was getting a whole lot of trouble trying to store the int value of those resource id's (this is also why xml values was not an option)...
now when ever i need to set a theme from the user preference... I just call
setTheme(Integer.parseInt( pref.getString("selectedTheme", String.valueOf(R.style.Theme_Default) )));
and off course you could provide a static method somewhere to do the castings etc without writing it for each activity.
EDIT: You don't need the array's to be static, I must off left them like that while I was trying different things to get it to work.

Android: Referring to a string resource when defining a log name

In my Android app, I want to use a single variable for the log name in multiple files. At the moment, I'm specifying it separately in each file, e.g.
public final String LOG_NAME = "LogName";
Log.d(LOG_NAME, "Logged output);
I've tried this:
public final String LOG_NAME = (String) getText(R.string.app_name_nospaces);
And while this works in generally most of my files, Eclipse complains about one of them:
The method getText(int) is undefined
for the type DatabaseManager
I've made sure I'm definitely importing android.content.Context in that file. If I tell it exactly where to find getText:
Multiple markers at this line
- Cannot make a static reference to the non-static method getText(int)
from the type Context
- The method getText(int) is undefined for the type DatabaseManager
I'm sure I've committed a glaringly obvious n00b error, but I just can't see it! Thanks for all help: if any other code snippets would help, let me know.
That's because getText is a method of Context. It does not matter if you import the Context class; what matters is that you invoke that method from a Context (for instance, the Activity class is a Context (it inherits Context)).
In that case, what I'd recommend, is creating a Application class that returns the context you want. Here I explain how to do it. After that you can do something like:
public final String LOG_NAME = (String) App.getContext().getText(R.string.app_name_nospaces);
Depending on what sort of 'files' you are using, you can define a TAG that is used.
For example, when I create an app, I like to create a base class for my Activity classes...
Suppose my app is called 'Wibble', and my package is com.mydomain.Wibble...I create my base Activity like so...
package com.mydomain.Wibble
public class WibbleActivity extends Activity {
final protected String TAG = this.getClass().getName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I'll explain how this next line works later
android.util.Log.d(TAG, "Entered onCreate()...");
}
}
Now suppose I derive an activity as follows...
package com.mydomain.Wibble
public class SomeActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeText");
}
}
Then I derive another Activity...
package com.mydomain.Wibble
public class SomeOtherActivity extends WibbleActivity {
#Override
protexted void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't Log "Entered onCreate()..." - WibbleActivity does it for me
android.util.Log.d(TAG, "SomeOtherText");
}
When onCreate() is called for SomeActivity, the output will be...
com.mydomain.Wibble.SomeActivity Entered onCreate()...
com.mydomain.Wibble.SomeActivity SomeText
...when onCreate() is called for SomeOtherActivity however, the output will be...
com.mydomain.Wibble.SomeOtherActivity Entered onCreate()...
com.mydomain.Wibble.SomeOtherActivity SomeOtherText
Neither activity needs to know specifics through an explicit string and the package name is prefixed. Obviously it will only work in certain situations but I find it useful.

Categories