How to save my ListView when app closes - java

I've tried using both SharedPrefrences and also saving to internal storage but I cannot get the results I want. The only results I have achieved are crashes.
I have an app that generates a custom password based on user options, it then enters those password into an Arraylist if the user clicks a button to save the password. However, when the app closes all data is lost.
How do I save the populated ArrayList or ListView so when the user clicks views passwords they can see their previously saved passwords?
* MAIN ACTIVITY JAVA *
package com.jrfapplications.passgen;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import static com.jrfapplications.passgen.SettingsPage.CustPass;
import static com.jrfapplications.passgen.SettingsPage.FBPass;
import static com.jrfapplications.passgen.SettingsPage.custword;
import static com.jrfapplications.passgen.SettingsPage.custwordend;
import static com.jrfapplications.passgen.SettingsPage.isEndWordChecked;
import static com.jrfapplications.passgen.SettingsPage.isHighCaseChecked;
import static com.jrfapplications.passgen.SettingsPage.isNumbChecked;
import static com.jrfapplications.passgen.SettingsPage.isSpecChecked;
import static com.jrfapplications.passgen.SettingsPage.isStartCustWordChecked;
import static com.jrfapplications.passgen.SettingsPage.passLength;
public class MainActivity extends AppCompatActivity implements Serializable {
//Buttons
Button btnGoToSet;
Button btnGenPass;
Button btnViewPass;
Button btnSavePass;
//TextView
TextView passView;
//Saved Pass Array
static ArrayList<String> SavedCustomPasswords = new ArrayList<>();
static ArrayList<String> SavedFacebookPasswords = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Find Buttons
btnGoToSet = (Button) findViewById(R.id.settingsbtn);
btnGenPass = (Button) findViewById(R.id.genpass);
btnViewPass = (Button) findViewById(R.id.viewpassbtn);
btnSavePass = (Button) findViewById(R.id.SavePassBtn);
//Find TextView
passView = (TextView) findViewById(R.id.pwEditTxt);
//Button Functions
btnGoToSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, SettingsPage.class));
}
});
btnGenPass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
generatePassword(generateCharSet());
}
});
btnSavePass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (CustPass == 1){
if (SavedCustomPasswords.contains(passView.getText().toString())){
Toast.makeText(getApplicationContext(), "Password Already Saved", Toast.LENGTH_SHORT).show();
}else{
SavedCustomPasswords.add(passView.getText().toString());
Toast.makeText(getApplicationContext(), "Password Saved", Toast.LENGTH_SHORT).show();
}
}
if (FBPass == 1){
if (SavedFacebookPasswords.contains(passView.getText().toString())){
Toast.makeText(getApplicationContext(), "Password Already Saved", Toast.LENGTH_SHORT).show();
}else{
SavedFacebookPasswords.add(passView.getText().toString());
Toast.makeText(getApplicationContext(), "Password Saved", Toast.LENGTH_SHORT).show();
}
}
}
});
btnViewPass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, view_pass.class));
}
});
}
public char[] generateCharSet() {
String numbers = "0123456789";
String special = "!£$%^&*()";
String alphabetsLower = "abcdefghijklmnopqrstuvwxyz";
String alphabetsUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Add lower alphabets by default
StringBuilder finalCharset = new StringBuilder(alphabetsLower);
// Add special chars if option is selected
if (isSpecChecked == 1) {
finalCharset.append(special);
}
// Add upper case chars if option is selected
if (isHighCaseChecked == 1) {
finalCharset.append(alphabetsUpper);
}
// Add numbers if option is selected
if (isNumbChecked == 1) {
finalCharset.append(numbers);
}
// build the final character set
return finalCharset.toString().toCharArray();
}
public void generatePassword(char[] charset) {
final StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < passLength; i++) {
char c = charset[random.nextInt(charset.length)];
sb.append(c);
}
if (isStartCustWordChecked == 1 && isEndWordChecked == 1){
final String output = custword + sb.toString() + custwordend;
passView.setText(output);
}else if (isStartCustWordChecked == 1){
final String output = custword + sb.toString();
passView.setText(output);
}else if (isEndWordChecked == 1){
final String output = sb.toString() + custwordend;
passView.setText(output);
}else
{
final String output = sb.toString();
passView.setText(output);
}
}
}
* VIEW PASS JAVA *
package com.jrfapplications.passgen;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class view_pass extends AppCompatActivity {
private ListView mListView1, mListView2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pass);
mListView1 = (ListView)findViewById(R.id.listView1);
mListView2 = (ListView)findViewById(R.id.listView2);
mListView1.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MainActivity.SavedCustomPasswords));
mListView2.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MainActivity.SavedFacebookPasswords));
ListUtils.setDynamicHeight(mListView1);
ListUtils.setDynamicHeight(mListView2);
}
public static class ListUtils {
public static void setDynamicHeight(ListView mListView) {
ListAdapter mListAdapter = mListView.getAdapter();
if (mListAdapter == null) {
// when adapter is null
return;
}
int height = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(mListView.getWidth(), View.MeasureSpec.UNSPECIFIED);
for (int i = 0; i < mListAdapter.getCount(); i++) {
View listItem = mListAdapter.getView(i, null, mListView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
height += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = mListView.getLayoutParams();
params.height = height + (mListView.getDividerHeight() * (mListAdapter.getCount() - 1));
mListView.setLayoutParams(params);
mListView.requestLayout();
}
}
}

This can be done by simply storing the generated password into sqlite database. https://developer.android.com/training/basics/data-storage/databases.html
You can also use cursor loaders for a better performance.
https://developer.android.com/guide/components/loaders.html

Try using a DBMS, if you want it stored locally, I would recommend SQL, or cloud-based system like Firebase

Shared preferences and Gson, much simple.

I used shared preferences to to save my ArrayLists on close thanks for the direction guys!
Using this for my answer:
Android: keep values in list after app shutdown
static ArrayList<String> SavedCustomPasswords = new ArrayList<>();
SavedCustomPasswords = getArray();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, SavedCustomPasswords);
adapter.notifyDataSetChanged();
public boolean saveArray() {
SharedPreferences sp = this.getSharedPreferences(SHARED_PREFS_NAME, Activity.MODE_PRIVATE);
SharedPreferences.Editor mEdit1 = sp.edit();
Set<String> set = new HashSet<String>();
set.addAll(SavedCustomPasswords);
mEdit1.putStringSet("list", set);
return mEdit1.commit();
}
public void onStop() {
saveArray();
super.onStop();
}
public ArrayList<String> getArray() {
SharedPreferences sp = this.getSharedPreferences(SHARED_PREFS_NAME, Activity.MODE_PRIVATE);
//NOTE: if shared preference is null, the method return empty Hashset and not null
Set<String> set = sp.getStringSet("list", new HashSet<String>());
return new ArrayList<String>(set);
}

Related

Send Data to Firebase

I'm developing a program that generates random passwords, but I'm bad at databases. I can generate password, but I want to send the generated password to realtime database with Firebase, but I can't. What should I do?
My code in mainactivity is like this :
import androidx.appcompat.app.AppCompatActivity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
Button button;
TextView textView;
CheckBox num;
CheckBox upper;
CheckBox lower;
CheckBox sym;
EditText max_lenght;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button5);
button = (Button)findViewById(R.id.button5);
textView = (TextView)findViewById(R.id.textView) ;
textView=(TextView)findViewById(R.id.textView2);
num= (CheckBox)findViewById(R.id.num);
upper=(CheckBox)findViewById(R.id.upper) ;
lower=(CheckBox)findViewById(R.id.lower) ;
sym=(CheckBox)findViewById(R.id.sym) ;
max_lenght=(EditText) findViewById(R.id.editTextNumberSigned);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View pas) {
String pass = randompassword(Integer.parseInt(max_lenght.getText().toString()),upper.isChecked(),lower.isChecked(),num.isChecked(),sym.isChecked());
if (pass.isEmpty()){
Toast.makeText(getApplicationContext(),"Lütfen Veri Giriniz !!",Toast.LENGTH_SHORT).show();
}
else {
ClipboardManager clipboardManager = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("Veri",pass);
clipboardManager.setPrimaryClip(clipData);
Toast.makeText(getApplicationContext(),"Sifreniz Olusturuldu... ",Toast.LENGTH_LONG).show();
}
textView.setText(pass);
}
});
}
private static String randompassword(int max_lenght, boolean upperCase, boolean lowerCase, boolean numbers, boolean specialCharacters)
{
String upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String lowerCaseChars = "abcdefghijklmnopqrstuvwxyz";
String numberChars = "0123456789";
String specialChars = "!##$%^&*()_-+=<>?/{}~|";
String allowedChars = "";
Random rn = new Random();
StringBuilder sb = new StringBuilder(max_lenght);
if (upperCase){
allowedChars+=upperCaseChars;
sb.append(upperCaseChars.charAt(rn.nextInt(upperCaseChars.length()-1)));
}
if(lowerCase){
allowedChars+=lowerCaseChars;
sb.append(lowerCaseChars.charAt(rn.nextInt(lowerCaseChars.length()-1)));
}
if (numbers){
allowedChars+=numberChars;
sb.append(numberChars.charAt(rn.nextInt(numberChars.length()-1)));
}
if (specialCharacters){
allowedChars+=specialChars;
sb.append(specialChars.charAt(rn.nextInt(specialChars.length()-1)));
}
sb.append(allowedChars.charAt(rn.nextInt(allowedChars.length()-1)));
for(int i=sb.length();i < max_lenght; ++i){
sb.append(allowedChars.charAt(rn.nextInt(allowedChars.length())));
}
return sb.toString();
}
}
I have defined the things required for firebase, but I don't know where to write in the main part.
After generating the random password, you can send to the database in the following way:
private DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("passwords").child(/*how so ever you want to nest data*/).setValue(password);
This is just a snippet to get you started, you can read more Read and write data.

Is there a way to save the data on SharedPreference?

I am trying to save data on button toggle, so that if pokemon is caught, when i run the application again, pokemon is caugt, and when released, It toggles back to "catch". But all my pokemon are displaying caught (button shows "release")
package com.example.pokedex;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class PokemonActivity extends AppCompatActivity {
private TextView nameTextView;
private TextView numberTextView;
private TextView type1TextView;
private TextView type2TextView;
private String url;
private RequestQueue requestQueue;
Button button;
SharedPreferences sharedpreferences;
public static final String mypreference = "mypref";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pokemon);
requestQueue = Volley.newRequestQueue(getApplicationContext());
url = getIntent().getStringExtra("url");
nameTextView = findViewById(R.id.pokedex_name);
numberTextView = findViewById(R.id.pokedex_number);
type1TextView = findViewById(R.id.pokedex_type);
type2TextView = findViewById(R.id.pokedex_type2);
button = findViewById(R.id.catcher);
sharedpreferences = getSharedPreferences(mypreference,
Context.MODE_PRIVATE);
load();
}
public void load() {
type1TextView.setText("");
type2TextView.setText("");
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, response -> {
try {
nameTextView.setText(response.getString("name"));
numberTextView.setText(String.format("#%03d", response.getInt("id")));
JSONArray typeEntries = response.getJSONArray("types");
for (int i = 0; i < typeEntries.length(); i++) {
JSONObject typeEntry = typeEntries.getJSONObject(i);
int slot = typeEntry.getInt("slot");
String type = typeEntry.getJSONObject("type").getString("name");
if (slot == 1) {
type1TextView.setText(type);
} else if (slot == 2) {
type2TextView.setText(type);
}
}
} catch (JSONException e) {
Log.e("cs50", "Pokemon json error", e);
}
}, error -> Log.e("cs50", "Pokemon details error", error));
requestQueue.add(request);
if (sharedpreferences.contains(nameTextView.getText().toString()))
button.setText("Release");
}
public void toggleCatch(View view) {
String name = nameTextView.getText().toString();
SharedPreferences.Editor editor = sharedpreferences.edit();
if (button.getText().toString().toLowerCase().equals("Catch".toLowerCase())) {
//editor.clear();
editor.putString(name, name);
editor.apply();
editor.commit();
button.setText("Release");
} else if (button.getText().toString().toLowerCase().equals("Release".toLowerCase())){
editor.remove(name);
editor.apply();
editor.commit();
button.setText("Catch");
}
}
}
I have tried everything i know how to, please help.
Unmodified source code at "https://cdn.cs50.net/2019/fall/tracks/android/pokedex/pokedex.zip"
The following line of code
if (sharedpreferences.contains(nameTextView.getText().toString()))
button.setText("Release");
should go into your onResponseListener() that is your response -> ....
Currently you are calling the if statement above synchronously. This means that you are searching for not any valid Pokemon name but "" (empty string) inside SharedPreferences. In one of your tests, you probably saved empty string as a key, and you cannot undo that because any transaction after you load your pokemons includes a non-empty string Pokemon name.
If taht is indeed the case, you can easily add a temporary code inside your activity onCreate() method to remove that entry from SharedPreferences.

Loading JSON data into alertdialog into spinner

I'm trying to retrieve Json data into a spinner that's in an alertdialog , it only loads if the spinner in the same activity but if it's in an alertDialog it gives me this Error :
Attempt to invoke virtual method 'void android.widget.Spinner.setAdapter(android.widget.SpinnerAdapter)' on a null object reference
package exir.exir;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import exir.exir.Helpers.FormAdapter;
import exir.exir.Helpers.PatientsAdapter;
import exir.exir.Helpers.PricrMAdapter;
import exir.exir.Helpers.RequestHandler;
import exir.exir.Helpers.SharedPrefManager;
import exir.exir.Rertofit.MyLabAPI;
import exir.exir.Utils.Constants;
import exir.exir.model.Form;
import exir.exir.model.PMenus;
import exir.exir.model.PriceM;
import exir.exir.model.RPatient;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import static android.R.layout.simple_spinner_item;
public class AddPatient extends AppCompatActivity {
private EditText patientname, gender , age , agetype , tel ,
phone , total , notes , testno , testprice , testnotes , testname1 , testno1 , testprice1 , testnotes1 ;
private Button add ;
private String URLstring = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php";
String labId , labpriceMenuNO ;
private static ProgressDialog mProgressDialog;
private ArrayList<PMenus> goodModelArrayList;
private ArrayList<String> names = new ArrayList<String>();
private Spinner PmSpinner;
MyLabAPI myLabAPI ;
CompositeDisposable compositeDisposable = new CompositeDisposable();
List<PriceM> pricemenilist;
ArrayAdapter<String> adapter;
ListView FormList ;
EditText editThen , edtSdt;
Button btn_sua , btn_xoa , btn_then ;
ArrayList<Form> formArrayList ;
FormAdapter formAdapter;
FloatingActionButton newTest ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_patient);
testno = (EditText)findViewById(R.id.testno);
testprice = (EditText)findViewById(R.id.testprice);
testnotes = (EditText)findViewById(R.id.testnotes);
newTest = (FloatingActionButton)findViewById(R.id.
newTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showNewTestDialog();
}
});
myLabAPI = Constants.getAPI();
add =(Button)findViewById(R.id.addPatient);
}
private void showNewTestDialog() {
AlertDialog.Builder alertDialog = new
AlertDialog.Builder(AddPatient.this);
alertDialog.setTitle("Add New Test ");
alertDialog.setMessage("PLease fill the info ");
LayoutInflater inflater = this.getLayoutInflater();
View formLayout = inflater.inflate(R.layout.newtest_layout, null);
editThen = formLayout.findViewById(R.id.FName);
edtSdt = formLayout.findViewById(R.id.FPrice);
goodModelArrayList = new ArrayList<>();
PmSpinner = (Spinner)findViewById(R.id.testname);
PmSpinner.setAdapter(adapter);
PmSpinner.setOnItemSelectedListener(new
AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int
position, long id) {
String item = parent.getItemAtPosition(position).toString() ;
String testum = goodModelArrayList.get(position).getCity() ;
String price = goodModelArrayList.get(position).getCountry() ;
testnotes.setText(item);
testno.setText(testum);
testprice.setText(price);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
retrieveJSON();
alertDialog.setView(formLayout);
alertDialog.setIcon(R.drawable.ic_shopping_cart_black_24dp);
alertDialog.setPositiveButton("YES", new
DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
//some code
}
});
alertDialog.setNegativeButton("No", new
DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
alertDialog.show();
}
private void retrieveJSON() {
StringRequest stringRequest = new StringRequest(
Request.Method.GET,
URLstring,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("strrrrr", ">>" + response);
try {
JSONObject obj = new JSONObject(response);
goodModelArrayList = new ArrayList<>();
JSONArray dataArray = obj.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
PMenus playerModel = new PMenus();
JSONObject dataobj =
dataArray.getJSONObject(i);
playerModel.setName(dataobj.getString("name"));
playerModel.setCountry(dataobj.getString("country"));
playerModel.setCity(dataobj.getString("city"));
playerModel.setImgURL(dataobj.getString("imgURL"));
goodModelArrayList.add(playerModel);
}
for (int i = 0; i < goodModelArrayList.size();
i++){
names.add(goodModelArrayList.get(i).getName().toString());
}
ArrayAdapter<String> spinnerArrayAdapter = new
ArrayAdapter<String>(AddPatient.this, simple_spinner_item, names);
spinnerArrayAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item); // The drop down view
PmSpinner.setAdapter(spinnerArrayAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//displaying the error in toast if occurrs
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
// request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
Try this.....
JSONObject c = JSONfunctions.getJSONfromURL("http://192.168.1.104/OnlineTicketBooking/book_now1.php?movieid='72'");
try {
JSONArray jarray = c.getJSONArray("offer_detail");
ArrayList<String> xyz= new ArrayList<String>();
for(int i = 0; i < jarray.length(); i++){
JSONArray timeArray = jarray.getJSONObject(i).getJSONArray("showtime");
for(int j = 0; j < timeArray .length(); j++){
xyz.add(timeArray .getString(j));
Log.d("get value",timeArray .getString(j));`enter code here`
}
}

Google maps showing logo, but not displaying in Android emulator

My app is supposed to display a Google Map with a heatmap, but I can't even get the map to display. It's only showing the logo in the bottom left corner. There seems to be no errors. I also checked the gradle and all the necessary dependencies are there. I can't tell if this is due to an actual error or lack of memory/slow processing.
Here's the MainActivity
package com.example.alexlevine.oceanapp;
package com.example.alexlevine.oceanapp;
import android.app.Dialog;
import android.content.Intent;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.TileOverlayOptions;
import com.google.maps.android.heatmaps.HeatmapTileProvider;
import com.google.maps.android.heatmaps.WeightedLatLng;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import static com.example.alexlevine.oceanapp.R.id.seekBar;
import static com.example.alexlevine.oceanapp.fetchSOCATData.co2array;
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback {
public static SeekBar seekbar;
public static GoogleMap mGoogleMap;
private HeatmapTileProvider mProvider;
public static TextView minyear;
public static TextView maxyear;
public static TextView currentyeartext;
public static int displayyear;
public static boolean usingSOCAT;
public static String typeKey;
public static Spinner dropdown;
private String[] mNavigationDrawerItemTitles;
private DrawerLayout mDrawerLayout;
android.support.v7.app.ActionBarDrawerToggle mDrawerToggle;
Button b2;
Button b4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (googleServicesAvailable()) {
Toast.makeText(this, "Play services available", Toast.LENGTH_LONG).show();;
initMap();
b2 = (Button) findViewById(R.id.button2);
b4 = (Button) findViewById(R.id.button4);
b2.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.getId() == R.id.button2) {
Intent i = new Intent(MainActivity.this, CarbonCalcActivity.class);
startActivity(i);
finish();
}
}
});
b4.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v.getId() == R.id.button4) {
Intent i = new Intent(MainActivity.this, CalcData.class);
startActivity(i);
finish();
}
}
}
);
//get the spinner from the xml.
dropdown = (Spinner)findViewById(R.id.spinner);
//create a list of items for the spinner.
String[] items = new String[]{"Ocean CO2 Densities", "Land CO2 Emissions (all sources)", "Electricity CO2 Emissions", "Aviation CO2 Emissions", "Ocean Shipping CO2 Emissions"};
//create an adapter to describe how the items are displayed, adapters are used in several places in android.
//There are multiple variations of this, but this is the basic variant.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, items);
//set the spinners adapter to the previously created one.
dropdown.setAdapter(adapter);
currentyeartext = (TextView) findViewById(R.id.currentyear);
minyear = (TextView) findViewById(R.id.minyear);
maxyear = (TextView) findViewById(R.id.maxyear);
typeKey = "00totals";
dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
switch (position) {
case 0: {
usingSOCAT = true;
displayyear = 1991;
seekbar.setMax(24);
minyear.setText("1991");
maxyear.setText("2015");
break;
}
case 1: {
usingSOCAT = false;
displayyear = 1997;
minyear.setText("1997");
maxyear.setText("2010");
seekbar.setMax(14);
typeKey = "00totals";
break;
}
case 2: {
usingSOCAT = false;
displayyear = 1997;
minyear.setText("1997");
maxyear.setText("2010");
seekbar.setMax(14);
typeKey = "01elec";
// Whatever you want to happen when the thrid item gets selected
break;
}
case 3: {
usingSOCAT = false;
displayyear = 1997;
minyear.setText("1997");
maxyear.setText("2010");
seekbar.setMax(14);
typeKey = "11aviation";;
// Whatever you want to happen when the thrid item gets selected
break;
}
case 4: {
usingSOCAT = false;
displayyear = 1997;
minyear.setText("1997");
maxyear.setText("2010");
seekbar.setMax(14);
typeKey = "12shipping";
// Whatever you want to happen when the thrid item gets selected
break;
}
}
}
public void onNothingSelected(AdapterView<?> parent)
{
}
});
seekbar = (SeekBar) findViewById(seekBar);
seekbar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
displayyear = progress + 1991;
if(usingSOCAT)
{
displayyear = progress + 1991;
new fetchSOCATData().execute();
}
else
{
displayyear = progress + 1997;
new fetchFFDASData().execute();
//List<WeightedLatLng> calledData = fetchFFDASData.ffdasArray;
//createHeatMap(fetchFFDASData.ffdasArray);
minyear.setText((CharSequence) fetchFFDASData.ffdasArray);
}
currentyeartext.setText("Showing: " + displayyear);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
if(usingSOCAT) {
}
//new fetchSOCATData().execute();
/*minyear = (TextView) findViewById(R.id.minyear);
maxyear = (TextView) findViewById(R.id.maxyear);
minyear.setText("1957");
maxyear.setText("2015");*/
//fetchSOCATData process = new fetchSOCATData();
//process.execute();
} else {
//No maps layout
}
}
//#Override
public void onNothingSelected(AdapterView<?> parent) {
}
public void initMap() {
SupportMapFragment mapFragment = (SupportMapFragment) this.getSupportFragmentManager()
.findFragmentById(R.id.mapFragment);
if(mapFragment != null) {
mapFragment.getMapAsync((OnMapReadyCallback)this);
}
}
public void createHeatMap(List<WeightedLatLng> dataset)
{
List<WeightedLatLng> locations = dataset;
/*mProvider = new HeatmapTileProvider.Builder().weightedData(locations).build();
mProvider.setRadius( HeatmapTileProvider.DEFAULT_RADIUS );
mGoogleMap.addTileOverlay(new TileOverlayOptions().tileProvider(mProvider));
mProvider = new HeatmapTileProvider();
mProvider.setWeightedData(dataset);
mProvider = mProvider.build();*/
//for (LatLng coordinate : coordinates) {
//WeightedLatLng weightedCoordinate = new WeightedLatLng(coordinate);
//com.google.maps.android.geometry.Point point = weightedCoordinate.getPoint();
// Filter points at infinity
/* if (Double.isInfinite(point.x) || Double.isInfinite(point.y)) {
Log.w(TAG, "Attempted to add undefined point " + coordinate);
continue;
}
weightedCoordinates.add(weightedCoordinate);*/
//}
mProvider = new HeatmapTileProvider.Builder()
.weightedData(dataset)
.opacity(0.5)
.build();
mGoogleMap.addTileOverlay(new TileOverlayOptions().tileProvider(mProvider));
Toast.makeText(this, "working", Toast.LENGTH_SHORT).show();
}
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
//goToLocation(-65, -12);
}
public void goToLocation(double lat, double lng) {
LatLng ll = new LatLng(lat, lng);
CameraUpdate update = CameraUpdateFactory.newLatLng(ll);
mGoogleMap.moveCamera(update);
}
public boolean googleServicesAvailable() {
GoogleApiAvailability api = GoogleApiAvailability.getInstance();
int isAvailable = api.isGooglePlayServicesAvailable(this);
if (isAvailable == ConnectionResult.SUCCESS)
return true;
else if (api.isUserResolvableError(isAvailable)) {
Dialog dialog = api.getErrorDialog(this, isAvailable, 0);
dialog.show();
} else
Toast.makeText(this, "Can't connect to play services", Toast.LENGTH_LONG).show();
return false;
}
}
Here's my code to fetch the data for the heatmap:
package com.example.alexlevine.oceanapp;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import com.google.android.gms.maps.model.LatLng;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.maps.android.heatmaps.WeightedLatLng;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static com.example.alexlevine.oceanapp.MainActivity.displayyear;
import static com.example.alexlevine.oceanapp.MainActivity.minyear;
#RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
public class fetchSOCATData extends AsyncTask<Object, Object, ArrayList<WeightedLatLng>> {
//String data = "http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.geoJson?year%2Cmonth%2Cday%2Chour%2Cminute%2Csecond%2Clongitude%2Clatitude%2Csal%2CTemperature_equi%2CTemperature_atm%2CpCO2_atm_wet_actual%2Cdelta_fCO2%2Crelative_humidity%2Cspecific_humidity%2Cwind_speed_true%2Cwind_speed_rel%2Cwind_dir_true%2Cwind_dir_rel%2CfCO2_recommended%2Cregion_id%2Ctime&organization=%22%22";
//public static SOCATCO2DataPoint.FeaturesBean[] co2array;
public static List<WeightedLatLng> co2array;
#Override
protected ArrayList<WeightedLatLng> doInBackground(Object... params) {
co2array = new ArrayList<WeightedLatLng>();
int year = displayyear;
URL url = null;
try {
//url = new URL("http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.geoJson?year%2Cmonth%2Cday%2Chour%2Cminute%2Csecond%2Clongitude%2Clatitude%2Csal%2CTemperature_equi%2CTemperature_atm%2CpCO2_atm_wet_actual%2Cdelta_fCO2%2Crelative_humidity%2Cspecific_humidity%2Cwind_speed_true%2Cwind_speed_rel%2Cwind_dir_true%2Cwind_dir_rel%2CfCO2_recommended%2Cregion_id%2Ctime&organization=%22%22&year%3E=2015&month%3C=1&day%3C=1&hour%3C=1&minute%3C=1&second%3C=10");
//url = new URL("http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.json?year%2Clongitude%2Clatitude%2CfCO2_recommended%2Ctime&organization=%22%22&year%3E=" + year + "&year%3C=" + year);
//url = new URL("http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.json?year%2Clongitude%2Clatitude%2CfCO2_recommended%2Ctime&organization=%22%22&year%3E=2015&year%3C=2015&month%3E=1&month%3C=1&day%3E=1&day%3C=1&hour%3E=1&hour%3C=1");
//url = new URL("http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.geoJson?year%2Cmonth%2Cday%2Chour%2Cminute%2Csecond%2Clongitude%2Clatitude%2CfCO2_recommended%2Ctime&organization=%22%22&year%3E=" + year + "&year%3C=" + year);
url = new URL("http://ferret.pmel.noaa.gov/socat/erddap/tabledap/socat_v4_fulldata.json?longitude%2Clatitude%2CfCO2_recommended&organization=%22%22&year=" + displayyear + "&day=1&hour=1&minute%3C=5&second%3C=30&longitude!=NaN&longitude!=NaN&latitude!=NaN&latitude!=NaN");
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e1) {
e1.printStackTrace();
}
String result = null;
try {
result = response.body().string();
} catch (IOException e1) {
e1.printStackTrace();
}
//System.out.print("result" + result);
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<OfficialSOCATPoint.TableBean>>() {}.getType();
OfficialSOCATPoint enums = gson.fromJson(result, OfficialSOCATPoint.class);
//Collection<OfficialSOCATPoint.TableBean> enums = gson.fromJson(result, collectionType);
/*SOCATCO2DataPoint.FeaturesBean[] protoExtract = enums.toArray(new SOCATCO2DataPoint.FeaturesBean[enums.size()]);*/
OfficialSOCATPoint protoExtract = gson.fromJson(result, OfficialSOCATPoint.class);
//OfficialSOCATPoint.TableBean[] protoExtract = enums.toArray(new OfficialSOCATPoint.TableBean[enums.size()]);
List<List<String>> dataArray = (List<List<String>>) protoExtract.getTable().getRows();
//for (int i = 0; i < dataArray.size(); i++)
for (int i = 0; i < 2; i++)
{
if(dataArray.get(i).get(2) != "null" && dataArray.get(i).get(1) != "null" && dataArray.get(i).get(0) != "null")
{
//co2array.add(new WeightedLatLng(new LatLng(Double.parseDouble(dataArray.get(i).get(0)), Double.parseDouble(dataArray.get(i).get(1))), Double.parseDouble(dataArray.get(i).get(2))));
}
}
return (ArrayList<WeightedLatLng>) co2array;
}
//#Override
protected void onPostExecute(ArrayList<WeightedLatLng> fb) {
super.onPostExecute(fb);
}
}
Here's the logcat:
10-17 16:45:27.884 1583-1593/? W/WallpaperManagerService: Cannot extract colors because wallpaper could not be read.
10-17 16:45:27.886 1583-1593/? W/WallpaperManagerService: Cannot extract colors because wallpaper could not be read.
10-17 16:45:17.747 2160-2160/? W/zygote: Common causes for lock verification issues are non-optimized dex code
10-17 16:45:17.955 1583-1807/? W/WallpaperManagerService: Cannot extract colors because wallpaper could not be read.
10-17 16:45:19.896 2138-2227/? W/zygote: Common causes for lock verification issues are non-optimized dex code
10-17 16:45:28.114 2188-2312/? W/ErrorProcessor: onFatalError, processing error from engine(4)
com.google.android.apps.gsa.shared.speech.b.g: Error reading from input stream
at com.google.android.apps.gsa.staticplugins.recognizer.j.a.a(SourceFile:28)
at com.google.android.apps.gsa.staticplugins.recognizer.j.b.run(SourceFile:15)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at com.google.android.apps.gsa.shared.util.concurrent.a.ag.run(Unknown Source:4)
at com.google.android.apps.gsa.shared.util.concurrent.a.bo.run(SourceFile:4)
at com.google.android.apps.gsa.shared.util.concurrent.a.bo.run(SourceFile:4)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
at com.google.android.apps.gsa.shared.util.concurrent.a.ak.run(SourceFile:6)
Caused by: com.google.android.apps.gsa.shared.exception.GsaIOException: Error code: 393238 | Buffer overflow, no available space.
at com.google.android.apps.gsa.speech.audio.Tee.f(SourceFile:103)
at com.google.android.apps.gsa.speech.audio.au.read(SourceFile:2)
at java.io.InputStream.read(InputStream.java:101)
at com.google.android.apps.gsa.speech.audio.ao.run(SourceFile:18)
at com.google.android.apps.gsa.speech.audio.an.run(SourceFile:2)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) 
at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) 
at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
at com.google.android.apps.gsa.shared.util.concurrent.a.ag.run(Unknown Source:4) 
at com.google.android.apps.gsa.shared.util.concurrent.a.bo.run(SourceFile:4) 
at com.google.android.apps.gsa.shared.util.concurrent.a.bo.run(SourceFile:4) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
at java.lang.Thread.run(Thread.java:764) 
at com.google.android.apps.gsa.shared.util.concurrent.a.ak.run(SourceFile:6) 
10-17 16:45:38.815 2510-2510/? I/Finsky: [2] com.google.android.finsky.setup.VpaService.a(32): Should not show workaround PAI step because experiment disabled
10-17 16:45:48.416 1767-2047/? I/GCoreUlr: WorldUpdater:init: Ensuring that reporting is stopped because of reasons: (no Google accounts)
10-17 16:45:49.205 2069-2069/? I/MediaRouter: Unselecting the current route because it is no longer selectable: null
10-17 16:46:16.401 1767-2047/? W/NetworkScheduler: Immediate task was not started com.google.android.videos/.service.drm.RefreshLicenseTaskService{u=0 tag="refresh_license_forced" trigger=window{start=0s,end=1s,earliest=-1s,latest=0s} requirements=[NET_CONNECTED] attributes=[] scheduled=-1s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=MANCHEGO_GCM-10400000}. Rescheduling immediate tasks can cause excessive battery drain.
10-17 16:46:16.928 1767-2047/? W/NetworkScheduler: Immediate task was not started com.google.android.gms/.tapandpay.gcmtask.TapAndPayGcmTaskService{u=0 tag="immediate" trigger=window{start=0s,end=1s,earliest=-1s,latest=0s} requirements=[NET_CONNECTED] attributes=[] scheduled=-1s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=MANCHEGO_GCM-14366000}. Rescheduling immediate tasks can cause excessive battery drain.
Please help me with this. Thanks!

ArrayList to charsequence conversion issue when selecting an option

I populate an alerttdialog from a database. I store these values in an arrayList, convert them to an charsequence list then set them to my alertdialog builder. As shown:
This is a screenshot of my populated 'text template' options from my database:
At the moment when I click one of my options for example Call me. it displays as it should within a specified edittext. If I click on one of the other options such as 'Email me' this is ignored, only my first 'if' option Call me. will work as shown:
This leads me to believe for some reason only Call me has been added to my charsequence array but I'm not sure why. Here is my complete class. I am getting this issue at the longOnClick method. I have marked this issue area on the code below:
package com.example.flybase2;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class ContactsEmail extends Activity implements OnClickListener, OnLongClickListener{
String emailPassed;
String emailAdd;
String emailSub;
String emailMess;
EditText setEmailAddress;
EditText setEmailSubject;
EditText setEmailMessage;
Button btnSendEmail;
int i;
CharSequence[] items;
DBHandlerTempComms addTemp = new DBHandlerTempComms(this, null, null);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.emaillayout);
Bundle extras = getIntent().getExtras();
if (extras != null) {
emailPassed = extras.getString("passedEmailAdd");
}
setEmailAddress = (EditText) findViewById (R.id.inputEmailAddress);
setEmailAddress.setText(emailPassed);
setEmailSubject = (EditText) findViewById (R.id.inputEmailSubject);
setEmailMessage = (EditText) findViewById (R.id.inputEmailMessage);
btnSendEmail = (Button)findViewById(R.id.btnSendEmail);
btnSendEmail.setOnClickListener(this);
setEmailMessage.setOnLongClickListener(this);
}
#Override
public void onClick(View sendEmailClick) {
emailAdd = setEmailAddress.getText().toString();
emailSub = setEmailSubject.getText().toString();
emailMess = setEmailMessage.getText().toString();
Intent sendEmailIntent = new Intent(Intent.ACTION_SEND);
sendEmailIntent.setType("message/rfc822");
sendEmailIntent.putExtra(Intent.EXTRA_EMAIL,new String[] {emailAdd});
sendEmailIntent.putExtra(Intent.EXTRA_SUBJECT, emailSub);
sendEmailIntent.putExtra(Intent.EXTRA_TEXT, emailMess);
startActivity(Intent.createChooser(sendEmailIntent, "Send mail..."));
finish();
}
*********************ISSUE AREA********************
#Override
public boolean onLongClick(View v) {
addTemp.open();
Cursor getTemps = addTemp.setList();
addTemp.close();
if (getTemps != null) {
String[] from = new String[getTemps.getCount()];
startManagingCursor(getTemps);
if (getTemps.moveToFirst()) {
int count = 0;
do {
String userName = getTemps.getString(1);
from[count] = userName;
count++;
} while (getTemps.moveToNext());
}
ArrayList<String> content = new ArrayList<String>();
for (int a = 0; a < from.length; a ++)
{
content.add(from[a]);
}
items = content.toArray(new CharSequence[content.size()]);
}
Builder alertDialogBuilder = new AlertDialog.Builder(ContactsEmail.this);
alertDialogBuilder.setTitle("Message Templates:");
alertDialogBuilder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Call me.")) {
setEmailMessage.setText(items[item]);
}
else if (items[item].equals("Text me.")) {
setEmailMessage.setText(items[item]);
}
else if (items[item].equals("Leaving the house now.")) {
setEmailMessage.setText(items[item]);
}
else if (items[item].equals("Leaving work now.")) {
setEmailMessage.setText(items[item]);
}
else if (items[item].equals("Create New Template +")) {
AlertDialog.Builder builder = new AlertDialog.Builder(ContactsEmail.this);
builder.setTitle("Type New Template:");
final EditText input = new EditText(ContactsEmail.this);
builder.setView(input);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Editable value = input.getText();
setEmailMessage.setText(value);
String templateValue = (String)value.toString();
addTemp.open();
addTemp.insertTemplate(templateValue);
addTemp.close();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
builder.show();
}
}
});
alertDialogBuilder.show();
return true;
}
}
Slightly embarrassing but I've just realized I have different strings comparing my IFs to the strings stored in the charsequence, so it is now working!

Categories

Resources