I'm trying to follow a tutorial from Udacity to build a chat app with Firebase. Though I followed every instructions, I'm having trouble to write data to the firebase realtime database on button press.
App is running perfectly on the simulator. But whenever I hit the send button, no data shows up in the database. Check the screenshot of the app.
App Screenshot
Added the google services json file.
Added all the dependencies that needed and applied google services plugin in the Build.gradle (app) file.
Added google services classpath in the Build.grade (project) file.
Changed the firebase security rules to the test mode.
What am I doing wrong? Please help.
MainActivity.java file looks like this:
package com.google.firebase.udacity.friendlychat;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.ProgressBar;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.DatabaseReference;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final String ANONYMOUS = "anonymous";
public static final int DEFAULT_MSG_LENGTH_LIMIT = 1000;
private ListView mMessageListView;
private MessageAdapter mMessageAdapter;
private ProgressBar mProgressBar;
private ImageButton mPhotoPickerButton;
private EditText mMessageEditText;
private Button mSendButton;
private String mUsername;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mMessagesDatabaseReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsername = ANONYMOUS;
mFirebaseDatabase = FirebaseDatabase.getInstance();
mMessagesDatabaseReference = mFirebaseDatabase.getReference().child("messages");
// Initialize references to views
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mMessageListView = (ListView) findViewById(R.id.messageListView);
mPhotoPickerButton = (ImageButton) findViewById(R.id.photoPickerButton);
mMessageEditText = (EditText) findViewById(R.id.messageEditText);
mSendButton = (Button) findViewById(R.id.sendButton);
// Initialize message ListView and its adapter
List<FriendlyMessage> friendlyMessages = new ArrayList<>();
mMessageAdapter = new MessageAdapter(this, R.layout.item_message, friendlyMessages);
mMessageListView.setAdapter(mMessageAdapter);
// Initialize progress bar
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
// ImagePickerButton shows an image picker to upload a image for a message
mPhotoPickerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// TODO: Fire an intent to show an image picker
}
});
// Enable Send button when there's text to send
mMessageEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().trim().length() > 0) {
mSendButton.setEnabled(true);
} else {
mSendButton.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
mMessageEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(DEFAULT_MSG_LENGTH_LIMIT)});
// Send button sends a message and clears the EditText
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FriendlyMessage friendlyMessage = new FriendlyMessage(mMessageEditText.getText().toString(), mUsername, null);
// Clear input box
mMessageEditText.setText("");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
}
Nothing goes into your database because you aren't writing something in it at all. You are creating an object of FriendlyMessage class but you aren't doing something with it. To solve this, write that object to Firebase database using the following lines of code:
mMessagesDatabaseReference.push().setValue(friendlyMessage);
You should place this line of code, right after the declaration of your friendlyMessage object.
// Send button sends a message and clears the EditText
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FriendlyMessage friendlyMessage = new FriendlyMessage(mMessageEditText.getText().toString(), mUsername, null);
// here you have to write code for save to firebase DB
mMessagesDatabaseReference.push().setValue(friendlyMessage);
// Clear input box
mMessageEditText.setText("");
}
});
after that you have to read data from firebase and add it to your
list.
Related
I have XML layout like this:
[....textedit....][addbutton]
=======list1=========
=======list2=========
=======list3=========
=======list4=========
What to do if I want to Load and Show the list onCreate from SharePreferences, be able to Add "item" to the list, and save it to SharedPreferences? Any extra simple beginner explanation are welcome since I'm a total newb.
My code below is a big mess, and I got it 100% from stitching from one example to another example that I got from anywhere.
package com.mycompany.myapp;
import android.app.*;
import android.os.*;
import android.widget.EditText;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ListAdapter;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.Toast;
import android.view.View;
import android.content.SharedPreferences;
import android.content.Context;
public class MainActivity extends Activity {
String FileName = "myFile";
Button BtnSave;
EditText editName;
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
BtnSave = findViewById(R.id.btn1);
BtnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveFile();
}
});
lv = (ListView) findViewById(R.id.list1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,empty);
lv.setAdapter(adapter);
//Setting onClickListener on ListView
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(),"Item Clicked: "+i,Toast.LENGTH_SHORT).show();
}
});
editName = findViewById(R.id.edit1);
}
private void saveFile() {
String strName = editName.getText().toString();
SharedPreferences sharedPref = getSharedPreferences(FileName,Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("name", strName);
editor.commit();
Toast.makeText(this,"Data Saved Successfully",Toast.LENGTH_SHORT).show();
}
}
I think this should help you.
fun addProduct(productsItem: Product) {
sharedPreferences=context.getSharedPreferences(TAG,Context.MODE_PRIVATE)
var gson=Gson()
var cartProduct=getAllProducts()
cartProduct.add(productsItem)
var json=gson.toJson(cartProduct)
println(json)
sharedPreferences.edit().putString("cart_products",json).apply()
}
fun getAllProducts(): ArrayList<Product?> {
sharedPreferences=context.getSharedPreferences(TAG,Context.MODE_PRIVATE)
val listType =
object : TypeToken<List<Product?>?>() {}.type
var productsItemList:ArrayList<Product?> = ArrayList();
val json=sharedPreferences.getString("cart_products",null)
if (json !=null){
var gson=Gson()
productsItemList=gson.fromJson(json,listType)
}
return productsItemList
}
Okay, so you need to:
1)input some word in EditText
2) show it in ListView
3) save it to preferences
right?
I think you must do next steps:
Create private ArrayList<String> list = new ArrayList();
When you input something in EditText and clicked on button, call list.add(editName.getText.toString()); and then call saveFile and save list.toString();
When you need to load file, create function
private void loadFile() {
SharedPreferences sharedPref = getSharedPreferences(FileName,Context.MODE_PRIVATE);
String string = sharedPref.getString("name", "");
ArrayList<String> newList = new ArrayList<String>(Arrays.asList(string.split(", ")));
}
Load in adapter your newList.
I have the following code in Android Studio. I'm able to open a popup whenever the "+ New Semester" button is clicked and a new semester is added to the Main Activity once the user types in the semester name in the popup and clicks on the "Done" button. Now, I want to implement a method that removes semesters that are no longer wanted. I made a method called removeSemesters() that I think that does what I want it to do, I haven't been able to test it because I'm not sure where I need to call that method in order to do what I want it to do. Any help would be appreciated! Thank you!
package com.example.gradecalculator;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// Private Fields
private Dialog d;
private EditText semesterName;
private ListView semesterList;
private ArrayList<String> semesterArray = new ArrayList<String>();
private ArrayAdapter<String> semesterAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
d = new Dialog(this);
}
// When user clicks on "+ New Semester" button open a popup where the user is prompted to
// type in the Semester Name and when "Done" is clicked the new semester appears in the Main
// Activity
public void newSemesterPopup(View v) {
TextView closePopup;
ImageButton doneButton;
d.setContentView(R.layout.new_semester_popup);
semesterName = (EditText) d.findViewById(R.id.editTextSemesterName);
semesterList = (ListView) findViewById(R.id.semesterList);
doneButton = (ImageButton) d.findViewById(R.id.doneButton);
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addSemesters();
}
});
closePopup = (TextView) d.findViewById(R.id.exitButton);
closePopup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d.dismiss();
}
});
d.show();
}
// Adds semesters to Main Activity
public void addSemesters() {
String getSemesterName = semesterName.getText().toString();
if(semesterArray.contains(getSemesterName)) {
Toast.makeText(getBaseContext(), "Semester Name already exists.", Toast.LENGTH_LONG).show();
}
else if(getSemesterName == null || getSemesterName.trim().equals("")) {
Toast.makeText(getBaseContext(), "Cannot add empty Semester Name", Toast.LENGTH_LONG).show();
}
else {
semesterAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_multiple_choice, semesterArray);
semesterList.setAdapter(semesterAdapter);
semesterAdapter.add(getSemesterName);
d.dismiss();
}
}
// Removes unwanted semesters from Main Activity
public void removeSemesters() {
semesterList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
SparseBooleanArray positionChecker = semesterList.getCheckedItemPositions();
int counter = semesterList.getCount();
for(int i = counter - 1; i > 1; i--) {
if(positionChecker.get(i)) {
semesterAdapter.remove(semesterArray.get(i));
Toast.makeText(MainActivity.this, "Semester deleted successfully.", Toast.LENGTH_LONG).show();
}
}
positionChecker.clear();
semesterAdapter.notifyDataSetChanged();
return false;
}
});
}
// Opens Main Activity
public void openMainActivity() {
Intent main = new Intent(this, MainActivity.class);
startActivity(main);
}
}
I was able to fix this by myself so in case anyone needs the answer in the future I'll leave it here.
I added the following to the onCreate method and it fixed my problem:
semesterName = (EditText) d.findViewById(R.id.editTextSemesterName);
semesterList = (ListView) findViewById(R.id.semesterList);
removeSemesters();
Not a hard fix, I thought of it right after posting the questions. Don't know if this is the most efficient way to do it. If not, feel free to give another answer.
I'm developing a Grade/GPA Calculator app on Android during my free time. What the app basically does until now is let the user add Semesters in the Main Activity and when the user clicks on a certain Semester the user is redirected to another Activity where the user can add new Courses for that specific semester. The problem I'm having is that when the user hits on the back button to go to to the Main Activity where the Semesters are located the courses that were added in that semester are erased. The same happens when I go to the phone's homepage and re-launch the app, everything that the user had created has been deleted.
I'm pretty sure my problem is that I'm not saving the data that the user creates to the phone's storage/app's storage, but I can't seem to figure out on how to do this. If anyone can point me in the right direction I would appreciate it. Thanks!
This is my MainActivity class's code: (My MainActivity is where Semesters are added)
package com.example.gradecalculator;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import java.util.ArrayList;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
// Private Fields
private Dialog d;
private EditText semesterName;
private ListView semesterListView;
private ArrayList<String> semesterArray = new ArrayList<String>();
private SemesterAdapter customSemesterAdapter;
private ArrayList<Semester> mySemesters = new ArrayList<>();
private ArrayList<String> semesterBackgrounds = new ArrayList<String>();
private String getSemesterName;
private int randomBackground[] = new int[7];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initiating toolbar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Making a new dialog
d = new Dialog(this);
// Initializing variables
semesterName = (EditText) d.findViewById(R.id.editTextSemesterName);
semesterListView = (ListView) findViewById(R.id.semesterList);
// Calling the removeSemesters() method
removeSemesters();
// Adding backgrounds to the backgrounds ArrayList
semesterBackgrounds.add("orange_background");
semesterBackgrounds.add("green_background");
semesterBackgrounds.add("aqua_background");
semesterBackgrounds.add("blue_background");
semesterBackgrounds.add("pink_background");
semesterBackgrounds.add("purple_background");
semesterBackgrounds.add("red_background");
semesterBackgrounds.add("yellow_background");
}
// Creating a custom Menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.top_menu, menu);
return true;
}
// Buttons in the custom Menu
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.editButton:
Toast.makeText(this, "Delete the desired Semesters by clicking on the trash button located to the right of each Semester", Toast.LENGTH_LONG).show();
return true;
}
return super.onOptionsItemSelected(item);
}
// When user clicks on "+New Semester" button open a popup where the user is prompted to
// type in the Semester Name and when "Done" is clicked the new semester appears in the Main
// Activity
public void newSemesterPopup(View v) {
TextView closePopup;
ImageButton doneButton;
d.setContentView(R.layout.new_semester_popup);
semesterName = (EditText) d.findViewById(R.id.editTextSemesterName);
semesterListView = (ListView) findViewById(R.id.semesterList);
doneButton = (ImageButton) d.findViewById(R.id.doneButton);
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addSemesters();
}
});
closePopup = (TextView) d.findViewById(R.id.exitButton);
closePopup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d.dismiss();
}
});
d.show();
}
// Adds semesters to Main Activity
public void addSemesters() {
getSemesterName = semesterName.getText().toString();
if (semesterArray.contains(getSemesterName)) {
Toast.makeText(getBaseContext(), "Semester Name Already Exists", Toast.LENGTH_SHORT).show();
} else if (getSemesterName == null || getSemesterName.trim().equals("")) {
Toast.makeText(getBaseContext(), "Cannot Add Empty Semester Name", Toast.LENGTH_SHORT).show();
} else {
semesterArray.add(getSemesterName);
mySemesters.add(new Semester(getSemesterName, semesterBackgrounds.get(new Random().nextInt(randomBackground.length))));
customSemesterAdapter = new SemesterAdapter(getApplicationContext(), R.layout.semester_row, mySemesters);
semesterListView.setAdapter(customSemesterAdapter);
d.dismiss();
}
}
// Removes unwanted semesters from Main Activity
public void removeSemesters() {
semesterListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder deleteAlert = new AlertDialog.Builder(MainActivity.this);
deleteAlert.setTitle("Semester Deletion Process");
deleteAlert.setMessage("Are you sure you want to delete the selected Semesters?");
deleteAlert.setNegativeButton("No! Cancel", null);
deleteAlert.setPositiveButton("Yes! Delete", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
customSemesterAdapter.remove(customSemesterAdapter.getItem(position));
semesterArray.remove(position);
customSemesterAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "Semester Deleted Successfully.", Toast.LENGTH_SHORT).show();
}
});
deleteAlert.show();
return false;
}
});
openSemestersActivity();
}
// Open the SemesterActivity and uses .putExtra to pass data to the SemesterActivity to tell it what semester to render
// data accordingly
public void openSemestersActivity() {
final Intent semester = new Intent(this, SemesterActivity.class);
semesterListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
semester.putExtra("semester", semesterName.getText().toString());
startActivity(semester);
}
});
}
}
This is my SemesterActivity code: (My SemestersActivity is where Courses are added)
package com.example.gradecalculator;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import java.util.ArrayList;
import java.util.Random;
public class SemesterActivity extends AppCompatActivity {
// Private Fields
private Dialog d;
private EditText courseName;
private EditText courseCode;
private EditText courseCredits;
private ListView courseListView;
private ArrayList<String> courseArray = new ArrayList<String>();
private CourseAdapter customCourseAdapter;
private ArrayList<Course> myCourses = new ArrayList<>();
private ArrayList<String> coursesBackgrounds = new ArrayList<String>();
private String getCourseName;
private String getCourseCode;
private String getCourseCredits;
private int randomBackground[] = new int[7];
private TextView courseNameView;
private TextView courseCodeView;
private TextView courseCreditsView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_semester);
d = new Dialog(this);
courseNameView = (TextView) d.findViewById(R.id.editTextCourseName);
courseCodeView = (TextView) d.findViewById(R.id.editTextCourseCode);
courseCreditsView = (TextView) d.findViewById(R.id.editTextCourseCredits);
courseListView = (ListView) findViewById(R.id.coursesList);
// Retrieving the Extra and determining the semester we want to load
Intent myIntent = getIntent();
String semester = myIntent.getStringExtra("semester");
removeCourses();
// Initiating toolbar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Adding backgrounds to the backgrounds ArrayList
coursesBackgrounds.add("orange_background_big");
coursesBackgrounds.add("green_background_big");
coursesBackgrounds.add("aqua_background_big");
coursesBackgrounds.add("blue_background_big");
coursesBackgrounds.add("pink_background_big");
coursesBackgrounds.add("purple_background_big");
coursesBackgrounds.add("red_background_big");
coursesBackgrounds.add("yellow_background_big");
}
// Creating a custom Menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.top_menu, menu);
return true;
}
// Buttons in the custom Menu
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.editButton:
Toast.makeText(this, "Delete the desired Courses by clicking on the trash button located to the right of each Semester", Toast.LENGTH_LONG).show();
return true;
}
return super.onOptionsItemSelected(item);
}
// New course popup
public void newCoursePopup(View v) {
TextView closePopup;
ImageButton doneButton;
d.setContentView(R.layout.new_course_popup);
courseName = (EditText) d.findViewById(R.id.editTextCourseName);
courseCode = (EditText) d.findViewById(R.id.editTextCourseCode);
courseCredits = (EditText) d.findViewById(R.id.editTextCourseCredits);
doneButton = (ImageButton) d.findViewById(R.id.doneButton);
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addCourses();
}
});
closePopup = (TextView) d.findViewById(R.id.exitButton);
closePopup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d.dismiss();
}
});
d.show();
}
// Adding courses to the Semester
public void addCourses() {
getCourseName = courseName.getText().toString();
getCourseCode = courseCode.getText().toString();
getCourseCredits = courseCredits.getText().toString();
if(courseArray.contains(getCourseName)) {
Toast.makeText(getBaseContext(), "Course Name Already Exists", Toast.LENGTH_SHORT).show();
}
else if(getCourseName == null || getCourseName.trim().equals("")) {
Toast.makeText(getBaseContext(), "Cannot Add Empty Course Name", Toast.LENGTH_SHORT).show();
}
else {
courseArray.add(getCourseName);
myCourses.add(new Course(getCourseName, getCourseCode, getCourseCredits, coursesBackgrounds.get(new Random().nextInt(randomBackground.length))));
customCourseAdapter = new CourseAdapter(getApplicationContext(), R.layout.course_row, myCourses);
courseListView.setAdapter(customCourseAdapter);
d.dismiss();
}
}
// Removing courses from the Semester
public void removeCourses() {
courseListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
AlertDialog.Builder deleteAlert = new AlertDialog.Builder(SemesterActivity.this);
deleteAlert.setTitle("Course Deletion Process");
deleteAlert.setMessage("Are you sure you want to delete the selected Courses?");
deleteAlert.setNegativeButton("No! Cancel", null);
deleteAlert.setPositiveButton("Yes! Delete", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
customCourseAdapter.remove(customCourseAdapter.getItem(position));
courseArray.remove(position);
customCourseAdapter.notifyDataSetInvalidated();
Toast.makeText(SemesterActivity.this, "Course Deleted Successfully", Toast.LENGTH_SHORT).show();
}
});
deleteAlert.show();
return false;
}
});
}
}
There are a couple of databases you can look into; You can use Room or Realm. You can also check out online DBs like Firestore by Firebase. The beauty about having an online db a user(Student) can access their data from a different phone if they lose or replace their current one. A recommended way to go is to have both to cover both scenarios.
I'm still new with both Java and android
My problem is that the recycleview only gets updated and adds the new added tag if I closed the app and run it again. How can I get the app to update the recycle view instantly to display the new tags.
java code
package com.deitel.favoritesites;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.DialogPreference;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TextInputLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Adapter;
import android.widget.EditText;
import android.widget.TextView;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String SITES="Sites";
private EditText urlEditText; //where user enters the URL
private EditText tagEditText;
private FloatingActionButton saveFloatingActionButton;
private SharedPreferences savedSites;
private List<String> tags;
private SitesAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
urlEditText = ((TextInputLayout) findViewById(
R.id.URLTextInputLayout)).getEditText();
urlEditText.addTextChangedListener(textWatcher);
tagEditText=((TextInputLayout)findViewById(R.id.tagTextInputLayout)).getEditText();
tagEditText.addTextChangedListener(textWatcher);
//get the shared prefrences containing the user saved URLs
savedSites = getSharedPreferences(SITES, MODE_PRIVATE);
//get the shared tags in an ArrayList then sort them
tags = new ArrayList<>(savedSites.getAll().keySet());
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
//get reference to the recycle to configure it
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
//use a linerlayout to display items in a vertical list
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//create recyclerView.Adopter to bind tags to the RecyclerView
adapter = new SitesAdapter(tags, itemClickListener, itemLongClickListener);
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new ItemDivider(this));
//register listner to save a new or edit search
saveFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
saveFloatingActionButton.setOnClickListener(saveButtonListener);
updateSaveFAB();
}
private final TextWatcher textWatcher= new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateSaveFAB();
}
#Override
public void afterTextChanged(Editable s) {
}
};
//show or hide the saveFloatingActionButton
private void updateSaveFAB() {
//check if there is input in both EditButton
if (urlEditText.getText().toString().isEmpty() || tagEditText.getText().toString().isEmpty())
saveFloatingActionButton.hide();
else
saveFloatingActionButton.show();
}
//saveButtonListener save a tag query pair into sharedPrefrece
private final OnClickListener saveButtonListener=new OnClickListener() {
#Override
public void onClick(View view) {
String query = urlEditText.getText().toString();
String tag = tagEditText.getText().toString();
if (!query.isEmpty() && !tag.isEmpty()) {
//hide the virtual keyboard
((InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(view.getWindowToken(),0);
addTaggedSites(tag, query);//add/update the search
urlEditText.setText("");//Clear queryEditText
tagEditText.setText("");//clear tagEditText
urlEditText.requestFocus();
}
}
};
//add new search to file then refresh all button
private void addTaggedSites(String tag, String query) {
//get a sharedprefrence editor to store new tag/query pair
SharedPreferences.Editor preferencesEditor = savedSites.edit();
preferencesEditor.putString(tag, query);
preferencesEditor.apply();
//if tag is new> add and sort tags then display update
if (!tag.contains(tag)) {
tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
}
//itemClickListener launches web broswer to display search results
private final OnClickListener itemClickListener=new OnClickListener() {
#Override
public void onClick(View view) {
//get query string and create a URL represeting the search
String tag= ((TextView) view).getText().toString();
String urlString=getString(R.string.search_URL)+Uri.encode(savedSites.getString(tag,""),"UTF-8");
//create an intent to lanuch a web broswer
Intent webIntent= new Intent(Intent.ACTION_VIEW,Uri.parse(urlString));
startActivity(webIntent);
}
};
//itemLongClickListener displays a dialog allowing the user to share edit or delete a saved search
private final OnLongClickListener itemLongClickListener= new OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
//get the tag that the user long touched
final String tag = ((TextView) view).getText().toString();
//creatw a new AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
//set the alertDialog title
builder.setTitle(getString(R.string.share_edit_delete_title, tag));
//set list of items to display and create event handler
builder.setItems(R.array.dialog_items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0://share
shareSites(tag);
break;
case 1://edit
tagEditText.setText(tag);
urlEditText.setText(savedSites.getString(tag, ""));
break;
case 2: //delete
deleteSites(tag);
break;
}
}
}
);
//set the alertDialog negetive button
builder.setNegativeButton(getString(R.string.cancel), null);
builder.create().show();//display the alert dialog
return true;
}
};
//allow user to choose app for sharing URL of a saved search
private void shareSites(String tag){
//create the URL representing the search
String urlString= getString(R.string.search_URL)+Uri.encode(savedSites.getString(tag, ""), "UTF-8");
//create an intent to share urlString
Intent shareIntent= new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_subject));
shareIntent.putExtra(Intent.EXTRA_TEXT,getString(R.string.share_message,urlString));
shareIntent.setType("text/plain");
//display app that can share plain text
startActivity(Intent.createChooser(shareIntent,getString(R.string.share_search)));
}
//delete search after user confirms
private void deleteSites(final String tag){
//create a new AlertDialog and set its message
AlertDialog.Builder confirmBuilder= new AlertDialog.Builder(this);
confirmBuilder.setMessage(getString(R.string.confirm_message, tag));
//cancel button configration
confirmBuilder.setNegativeButton(getString(R.string.cancel), null);
//positive DELETE button
confirmBuilder.setPositiveButton(getString(R.string.delete),new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog , int id){
tags.remove(tag);
//remove sharedPerefrences.Editor from Sharedprefrences
SharedPreferences.Editor preferenceEditor= savedSites.edit();
preferenceEditor.remove(tag);
preferenceEditor.apply();
adapter.notifyDataSetChanged();
}
}
);
confirmBuilder.create().show();
}
}
This is my adopter code
package com.deitel.favoritesites;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class SitesAdapter extends RecyclerView.Adapter<SitesAdapter.ViewHolder> {
private final View.OnClickListener clickListener;
private final View.OnLongClickListener longClickListener;
private final List<String> tags;
public SitesAdapter(List<String> tags, View.OnClickListener clickListener, View.OnLongClickListener longClickListener) {
this.tags = tags;
this.clickListener = clickListener;
this.longClickListener = longClickListener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView textView;
public ViewHolder(View itemView, View.OnClickListener clickListener, View.OnLongClickListener longClickListener) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textView);
itemView.setOnClickListener(clickListener);
itemView.setOnLongClickListener(longClickListener);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return (new ViewHolder(view, clickListener, longClickListener));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(tags.get(position));
}
#Override
public int getItemCount() {
return tags.size();
}
}
Change your code into this
if (!tags.contains(tag)) {
tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
Because, this below condition is always false
if(!tag.contains(tag))
Its because you are checking if a value contains in that value itself. SO it will be always true.
If you are checking the tag exist in the List<String> tags you should do like this below.
if(!tags.contains(tag))
change your code to....
//add new search to file then refresh all button
private void addTaggedSites(String tag, String query) {
//get a sharedprefrence editor to store new tag/query pair
SharedPreferences.Editor preferencesEditor = savedSites.edit();
preferencesEditor.putString(tag, query);
preferencesEditor.apply();
//if tag is new> add and sort tags then display update
if (!this.tag.contains(tag)) {
this.tags.add(tag);
Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
adapter.notifyDataSetChanged();
}
}
This may help:
create a setter method within your adapter allowing you to set/update the adapter ArrayList.
Whenever you make a change to your list i.e. remove Tag, pass this updated list to your adapter via your new setter method.
call notifyDataSetChanged().
I have an alert dialog that allows user to edit a TextView. Currently, once the alert dialog closes, the user has to hit the back button and then re-enter the activity for the TextView to update. I've tried many solutions on SO but none seem to work. When the user clicks 'Save Changes', the TextView should update.
Calling activity:
package com.group1.workouttracker;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
public class DayActivity extends Activity {
//does not extend ListActivity, so list functions must be called by myList object
private String buttonClicked;
private String thisSummary;
private Intent intent;
DatabaseHelper db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_day);
db = DatabaseHelper.getInstance(getApplicationContext());
intent = getIntent();
buttonClicked = intent.getStringExtra("Day");
Button buttonCreateExercise = (Button) findViewById(R.id.buttonAddExercise);
buttonCreateExercise.setOnClickListener(new OnClickListenerCreateExercise(buttonClicked));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void readSummary(String buttonClicked) {
TextView textViewSummary = (TextView) findViewById(R.id.textViewSummary);
textViewSummary.setOnLongClickListener(new OnLongClickListenerEditSummary(buttonClicked));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
thisSummary = db.readSummary(buttonClicked).getSummary();
TextView summary = (TextView) findViewById(R.id.textViewSummary);
summary.setOnLongClickListener(new OnLongClickListenerEditSummary(buttonClicked));
summary.setText(thisSummary);
}
}
Alert Dialog that activates on a long press:
package com.group1.workouttracker;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.Toast;
public class OnLongClickListenerEditSummary implements View.OnLongClickListener {
Context context;
String dayClicked = "";
#Override
public boolean onLongClick(View view) {
context = view.getContext();
final DatabaseHelper db = DatabaseHelper.getInstance(context);
ObjectDay objectDay = db.readSummary(dayClicked);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View formElementsView = inflater.inflate(R.layout.edit_summary_form, null, false);
final long dayId = objectDay.getId();
final String dName = objectDay.getDayName();
final EditText editTextSummary = (EditText) formElementsView.findViewById(R.id.editTextSummary);
final CharSequence[] items = { "Edit", "Delete" };
new AlertDialog.Builder(context).setTitle("Exercise");
new AlertDialog.Builder(context)
.setView(formElementsView)
.setTitle("Edit Summary for " + dayClicked + ":")
.setPositiveButton("Save Changes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ObjectDay objectDay = new ObjectDay();
objectDay.setId(dayId);
objectDay.setDayName(dName);
objectDay.setSummary(editTextSummary.getText().toString());
boolean updateSuccessful = DatabaseHelper.getInstance(context).updateSummary(objectDay);
if(updateSuccessful) {
Toast.makeText(context, "Summary was updated.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(context, "Unable to update summary.", Toast.LENGTH_SHORT).show();
}
//dialog.cancel();
dialog.dismiss();
}
}).show();
return false;
}
public void editRecord(final String dName) {
final DatabaseHelper db = DatabaseHelper.getInstance(context);
ObjectDay objectDay = db.readSummary(dName);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View formElementsView = inflater.inflate(R.layout.edit_summary_form, null, false);
final EditText editTextDay = (EditText) formElementsView.findViewById(R.id.editTextSummary);
final EditText editTextSummary = (EditText) formElementsView.findViewById(R.id.editTextSummary);
editTextSummary.setText(objectDay.getSummary());
}
public OnLongClickListenerEditSummary(String dayClicked) {
this.dayClicked = dayClicked;
}
}
Edit: I was able to get this working correctly by adding the following code:
Activity:
public void passThrough(ObjectDay objDay) {
textViewSummary.setText(objDay.getSummary());
}
In .setpositive button:
((DayActivity) context).passThrough(objectDay);
Opening a dialog wont trigger the Activity's onPause/onResume (I'm not sure if that's true for dialog fragments). Instead you can apply an onDismissListener (which can be a member variable of the Activity or anonymous) to the dialog.
When the dialog is closed (by any means) you'll get some information and you can update your textfield. Alternatively you could do the same from the positive click listener.
Either
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//UPDATE FROM HERE (call a method or manipulate an Activity member var)
}
});
OR
alert.setOnDismissListener(new OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
//UPDATE FROM HERE (Check DialogInterface for positive if you want)
}
});
Edit, for your example:
class Whatever extends Activity {
private TextView mTextView;
private MyPassThroughListener mPassThroughListener = new MyPassThroughListener() {
#Override
public function passThrough(ObjectDay objDay) {
mTextView.setText(objDay.getSummary());
}
}
protected void onCreate(Bundle savedInstanceState) {
....
buttonCreateExercise.setOnClickListener(new OnClickListenerCreateExercise(mPassThroughListener ));
}
}
class OnLongClickListenerEditSummary {
MyPassThroughListener mPassThroughListener;
...
public OnLongClickListenerEditSummary (MyPassThroughListener passThroughListener) {
mPassThroughListener = passThroughListener;
}
#Override
public boolean onLongClick(View view) {
....
new AlertDialog.Builder(context)
.setPositiveButton("Save Changes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ObjectDay objectDay = new ObjectDay();
objectDay.setId(dayId);
objectDay.setDayName(dName);
objectDay.setSummary(editTextSummary.getText().toString());
mPassThroughListener.passThrough(objectDay);
dialog.dismiss();
}
...
}
}
public interface MyPassThroughListener {
public function passThrough(ObjectDay objDay);
}