Null Pointer Exception When Checking If SharedPrefs Equals Null - android

I am making an Android app that captures a user's e-mail through the displayEmailCaptureFragment() method. If I already captured the user's e-mail, I do not want to prompt the user to enter their e-mail again.
I declare the customerEmailAddress String right after my MainActivity but before the onCreate method:
public class MainActivity extends FragmentActivity implements View.OnClickListener, BillingProcessor.IBillingHandler,
EmailCapturedListener {
private MyPagerAdapter pageAdapter;
private Button mDownloadResumeButton;
private ImageButton mRightArrow, mLeftArrow;
private static final String EMAILKEY = "email_key";
public static final String EDITSKU = "professional_editing_service_1499";
public static final String EMAILSKU = "resume_template_pro_99";
private static final String RBPEMAIL = "rbproeditor#gmail.com";
private static final String RBPPASSWORD = "Redhawks123";
public String customerEmailAddress;
I then have an OnClick() method based on a user's response action within the app. Essentially, I am try to allow for a certain activity after the onClick if the user already entered their e-mail address. If they did not enter their e-mail address, then I prompt them to enter their e-mail and save it to shared preferences. I use a basic if - else statement, however I am still generating a null pointer exception even though I assign the customerEmailAddress string:
#Override
public void onClick(View v) {
int currentPosition = pager.getCurrentItem();
switch (v.getId()) {
case R.id.right_arrow:
pager.setCurrentItem(currentPosition + 1);
break;
case R.id.left_arrow:
pager.setCurrentItem(currentPosition - 1);
break;
case R.id.download_resume_button:
customerEmailAddress = mPrefs.getString(EMAILKEY, null);
if (customerEmailAddress.equals(null)){
displayEmailCaptureFragment();
}
else {
showPurchaseDialog();
}
break;
}
}
Any help is appreciated!

This code is wrong - you can't call equals(...) or any other method on a null object.
...
customerEmailAddress = mPrefs.getString(EMAILKEY, null);
if (customerEmailAddress.equals(null)){
...
Do like this instead:
customerEmailAddress = mPrefs.getString(EMAILKEY, null);
if (customerEmailAddress == null){
...
OR use TextUtils:
customerEmailAddress = mPrefs.getString(EMAILKEY, null);
if (TextUtils.isEmpty(customerEmailAddress)){
...

Related

How to use few buttons, with dependencies between them? Android Studio

I have 4 buttons, that each one of them doe's a different action (lets say each action takes 2 minutes)
When I click both buttons (with few minutes between them), both of them still get inside the 'if' part, although the flag i put.
Here is part of my code:
southToNorth.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
north.incCounter();
north.setWaitingState(true);
pushToQueue(1);
if (isWorking==0) {
isWorking++;
start();
}
}
});
westToEast.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
east.incCounter();
east.setWaitingState(true);
pushToQueue(2);
if (isWorking==0) {
isWorking++;
start();
}
}
});
I Don't think that is a synchronization problem, i even put this code at the top of the start function:
private void start() {
if(isWorking>1)
return;
but still, both of them doe's all of the start function, what I'm trying to avoid.
(I have a global flag "int isWorking" initialized to zero )
Why both of them are getting inside the if part? How can I solve it?
Thank you very much!
A global flag should do it. You say you've tried it, but you haven't actually provided how you tried it, so I can't specifically help with that.
Make two variables and some static fields:
private static final int ACTION_NONE = -1;
private static final int ACTION_ONE = 0;
private static final int ACTION_TWO = 1;
private static final int ACTION_THREE = 2;
private static final int ACTION_FOUR = 3;
private boolean actionRunning = false;
private int queuedAction = ACTION_NONE;
When you try to run an action, check if there's currently an action running:
if (actionRunning) {
queuedAction = /* the corresponding static field */;
} else {
queuedAction = ACTION_NONE;
actionRunning = true;
}
Then, when whatever action you're using completes, run the appropriate queued action:
switch (queuedAction) {
case ACTION_ONE:
//run action 1
break;
case ACTION_TWO:
//etc
...
}

Null pointer exception when validating email in android

In my android app, I take the input from the edit text when the login button is clicked and pass it to my presenter. The presenter then validates it using the LoginValidator utility class, depending on the result it either continues with the normal login flow or sends a message to the activity notifying that the email or/and password is/are invalid.
In the test class for the LoginValidator I do the following:
public class LoginValidatorTest {
private static final String INVALID_EMAIL = "ewksd";
private static final String VALID_EMAIL = "tom.finet#gmail.com";
private static final String INVALID_PASSWORD = "sjadsaA";
private static final String VALID_PASSWORD = "Asdfgh1d";
#Test
public void shouldValidateInvalidEmail() {
Assert.assertEquals(LoginValidator.validateEmail(INVALID_EMAIL), false);
}
#Test
public void shouldValidateValidEmail() {
Assert.assertEquals(LoginValidator.validateEmail(VALID_EMAIL), true);
}
#Test
public void shouldValidateInvalidPassword() {
Assert.assertEquals(LoginValidator.validatePassword(INVALID_PASSWORD), false);
}
#Test
public void shouldValidateValidPassword() {
Assert.assertEquals(LoginValidator.validatePassword(VALID_PASSWORD), true);
}
}
Here is the LoginValidator class which the test calls:
public class LoginValidator {
/**
* #param email the email to be validated
* #return true if the email is valid
*/
public static boolean validateEmail(String email) {
return email != null && Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
/**
*
* #param password the password to be validated
* #return true if the password is valid
*/
public static boolean validatePassword(String password) {
if (password == null)
return false;
else if (password.length() < 6)
return false;
else if (!password.contains("^[0-9]"))
return false;
else if (!password.contains("[A-Z]+"))
return false;
return true;
}
}
When the tests are running these are the results:
How do I fix my code to make all the tests pass?
UPDATE:
Here is what the regex for the password validation looks like:
From further analysis, I have concluded that the code Patterns.EMAIL_ADDRESS is null and hence when calling .matcher(email) on it causes a NullPointerException. Why the hell is Patterns.EMAIL_ADDRESS returning null?
Try using Mockito and mock LoginValidator as follows :
// If you want to create an instance
LoginValidator loginValidator = mock(LoginValidator.class);
// If you need to access static methods from that class
mock(LoginValidator.class);
Not sure about the mail check but you have an error in your password check.
Assuming that you want just check if the password contains a number you should change it from:
public static boolean validatePassword(String password) {
if (password == null)
return false;
else if (password.length() < 6)
return false;
else if (!password.matches(".*[0-9]+.*"))
return false;
else if (!password.matches(".*[A-Z]+.*"))
return false;
return true;
}
The capital also was incorrect as contains does not accept regex. One of the options would be to use matches.
public static boolean validatePassword(String pwd) {
return pwd != null && pwd.matches("((?=.*\\d)(?=.*[A-Z]).{6,})");
}
"((?=.*\\d)(?=.*[A-Z]).{6,})" is the regex for at least one number, at least one cap, and at least 6 characters.
Had this this problem, it's caused by Patterns.EMAIL_ADDRESS.matcher, this is an Android method so you can neither use it in a unit test (it's always null) nor mock it. You can't mock it because Mockito does not mock android classes. A solution would be making your own regex for emails.

How to make Human Activity Recognition less sensitive in Android

I am developing an Android app that is recognising the activity the user us doing every 3 seconds (has to be that frequent by design) (e.g. static, walking, running). I have an Activity table in my database that increments the following values:
private int activeTime;
private int longestInactivityInterval;
private int currentInactivityInterval;
private int averageInactInterval;
Those are presented in a fragment. Currently, it is very "sensitive". For example, if the user is static (i.e. laying on their bed) and they pull their phone out of the pocket it will recognise activity like "walking". The history of recognised activities would look like that:
static
static
walking
static
static
How can I make sure that this incidental "walking" recognised activity is recognised as "static". Is there a way how I can correct that?
This is the class that is doing the Activity monitoring (incrementing values depending on what activity is recognised.
public class ActivityMonitor implements Observer, IActivityMonitor {
private User mUser;
private IActivityDataManager mDataManager;
public ActivityMonitor(IActivityDataManager dataManager) {
mDataManager = dataManager;
}
#Override
public void update(Observable observable, Object activity) {
monitorActivity(activity);
}
private void monitorActivity(Object activityClass) {
switch ((int) activityClass) {
case 0:
//activity = "walking";
case 1:
//activity = "running";
case 3:
//activity = "cycling";
mDataManager.incActiveTime();
mDataManager.clearCurrentInacInterval();
break;
case 2:
//activity = "static";
mDataManager.incCurrentInacInterval();
break;
}
}
I found a solution to the problem myself. I am using apache's common CircularFifoQueue with set size to 2.
This is how my solution looks like:
private void monitorActivity(Object activityClass) {
int activityInt = (int) activityClass;
correctionList.add(activityInt);
int correctResult = applyCorrection(activityInt);
if (correctResult == correctionList.size()) {
mDataManager.incActiveTime();
mDataManager.clearCurrentInacInterval();
} else {
mDataManager.incCurrentInacInterval();
}
}
private int applyCorrection(int classInt) {
int count = 0;
for (int item : correctionList) {
if (item == 0 || item == 1 || item == 3) {
count++;
}
}
return count;
}
Basically, it adds the classInt which could be (0,1,2 or 3) - walking = 0, running = 1, cycling = 3 and static = 2. The applyCorrection method looks through the queue with size 2 (this plays the role of the factor, 2 works great for me) and counts and checks the integers. If the returned count correctResult is 2 that means that the activity is for sure of time ACTIVE (1,2,3) and not STATIC (2).

In libgdx on Android, how do I save game state in case app is killed?

In Android, we usually save all of our state variables in the onSaveInstanceState() callback by putting them in the Bundle provided.
How do people deal with saving/loading game state variables with libGDX as the classes can't use/return a Bundle object?
This is quit simple! You can use Preferences for that. You can store values in the Preferences. On android the backend uses the SharedPreferences from Android itself. On desktop its saved as an xml somewhere in the user folder.
I wrote a simple Helper to save options and get the options of my game. Here is some code out of it. (Note, dont forget to flush after saving something)
public class PreferencesHelper {
public final static String PREF_NAME_OPTION = "options";
private final static String VOLUMEN = "volumen";
private final static String VIBRATE = "vibrate";
private final static String EFFECT_VOLUMEN = "effect";
private final static String FIRST_START = "start";
private Preferences optionPref = Gdx.app.getPreferences(PREF_NAME_OPTION);;
public PreferencesHelper() {
optionPref = Gdx.app.getPreferences(PREF_NAME_OPTION);
}
public float getVolumen() {
return optionPref.getFloat(VOLUMEN);
}
public void setVolumen(float vol) {
optionPref.putFloat(VOLUMEN, vol);
optionPref.flush();
}
public boolean getVibrate() {
return optionPref.getBoolean(VIBRATE);
}
public void setVibrate(boolean vibr) {
optionPref.putBoolean(VIBRATE, vibr);
optionPref.flush();
}
public float getEffectVolumen() {
return optionPref.getFloat(EFFECT_VOLUMEN);
}
public void setEffectVolumen(float eff) {
optionPref.putFloat(EFFECT_VOLUMEN, eff);
optionPref.flush();
}
}
This is how i save my options. To save an character you do the same but save all importand stuff you need, to recreate your character when loading the game again. You can also have more than one prefrerence!
I hope this helped.

Pass a string between activities

Hi i want to pass a string through two ativities I've been looking for it in another answers and tried this one:
public class GlobalVars extends Activity {
private static String winename;
public static String getWineName(){
return winename;
}
public static void setWineName(String s){
winename=s;
}
}
And set the string in activity 1 as this:
EditText searchbox=(EditText) findViewById(R.id.buscarmainText);
String searchb=searchbox.getText().toString();
GlobalVars.setWineName(searchb);
But, when I call the getWineName method in activity 2 it seems that the string winename is empty, is called like this:
public String sbuscar=GlobalVars.getWineName();
Don't know what am I doing wrong.
Its better to pass string between activities with intents
In your first activity class:
Intent i = new Intent(this, activity2.class);
i.putExtra("KEY",YourData);
In next activity class
Bundle extras = getIntent().getExtras();
if(extras !=null) {
String value = extras.getString("KEY");
}
You should put your global vars on a holder class like this.
public class GlobalVars {
public static final String KEY_WINENAME = "winename";
private static HashMap<String, String> globalVars = new HashMap<String, String>();
public static String getGlobalVariable(String key) {
return globalVars.get(key);
}
}
Then from any component from your app you can make a call to GlobalVars.getGlobalVariable(GlobalVars.KEY_WINENAME);
If you just want to pass the String from one activity to the next one you should use an Intent as Ram kiran has answered. Usually it's the best practice.
Also you should look at where this piece of code is getting called:
EditText searchbox=(EditText) findViewById(R.id.buscarmainText);
String searchb = searchbox.getText().toString();
GlobalVars.setWineName(searchb);
For instance, if you change the orientation you may be not maintaining the EditText state, so that the text inside it get empty again and your code is called again emptying the variable. If you are unsure put a log line inside setWinename() to check if it's been called twice.

Categories

Resources