Android firebase real-time database only shows last submit - java

I've been following a tutorial on how to save data to the Firebase Realtime Database in Android.
With the tutorial i have managed to get this data to save etc however it only shows the last submitted item.
MainActivity code:
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class MainActivity extends AppCompatActivity {
// creating variables for
// EditText and buttons.
private EditText employeeNameEdt, employeePhoneEdt, employeeAddressEdt;
private Button sendDatabtn;
// creating a variable for our
// Firebase Database.
FirebaseDatabase firebaseDatabase;
// creating a variable for our Database
// Reference for Firebase.
DatabaseReference databaseReference;
// creating a variable for
// our object class
EmployeeInfo employeeInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing our edittext and button
employeeNameEdt = findViewById(R.id.idEdtEmployeeName);
employeePhoneEdt = findViewById(R.id.idEdtEmployeePhoneNumber);
employeeAddressEdt = findViewById(R.id.idEdtEmployeeAddress);
// below line is used to get the
// instance of our FIrebase database.
firebaseDatabase = FirebaseDatabase.getInstance();
// below line is used to get reference for our database.
databaseReference = firebaseDatabase.getReference("EmployeeInfo");
// initializing our object
// class variable.
employeeInfo = new EmployeeInfo();
sendDatabtn = findViewById(R.id.idBtnSendData);
// adding on click listener for our button.
sendDatabtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// getting text from our edittext fields.
String name = employeeNameEdt.getText().toString();
String phone = employeePhoneEdt.getText().toString();
String address = employeeAddressEdt.getText().toString();
// below line is for checking weather the
// edittext fields are empty or not.
if (TextUtils.isEmpty(name) && TextUtils.isEmpty(phone) && TextUtils.isEmpty(address)) {
// if the text fields are empty
// then show the below message.
Toast.makeText(MainActivity.this, "Please add some data.", Toast.LENGTH_SHORT).show();
} else {
// else call the method to add
// data to our database.
addDatatoFirebase(name, phone, address);
}
}
});
}
private void addDatatoFirebase(String name, String phone, String address) {
// below 3 lines of code is used to set
// data in our object class.
employeeInfo.setEmployeeName(name);
employeeInfo.setEmployeeContactNumber(phone);
employeeInfo.setEmployeeAddress(address);
// we are use add value event listener method
// which is called with database reference.
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// inside the method of on Data change we are setting
// our object class to our database reference.
// data base reference will sends data to firebase.
databaseReference.setValue(employeeInfo);
// after adding this data we are showing toast message.
Toast.makeText(MainActivity.this, "data added", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// if the data is not added or it is cancelled then
// we are displaying a failure toast message.
Toast.makeText(MainActivity.this, "Fail to add data " + error, Toast.LENGTH_SHORT).show();
}
});
}
}
EmployeeInfo code:
public class EmployeeInfo {
// string variable for
// storing employee name.
private String employeeName;
// string variable for storing
// employee contact number
private String employeeContactNumber;
// string variable for storing
// employee address.
private String employeeAddress;
// an empty constructor is
// required when using
// Firebase Realtime Database.
public EmployeeInfo() {
}
// created getter and setter methods
// for all our variables.
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeContactNumber() {
return employeeContactNumber;
}
public void setEmployeeContactNumber(String employeeContactNumber) {
this.employeeContactNumber = employeeContactNumber;
}
public String getEmployeeAddress() {
return employeeAddress;
}
public void setEmployeeAddress(String employeeAddress) {
this.employeeAddress = employeeAddress;
}
}
Has anyone ever encountered this in Firebase. I have been looking for other tutorials which had ended up exactly like this so I'm not sure whether it is something in the code that is wrong or with my Firebase database.

As firebase overwrites the previous data you have entered.
You can use a .push() function like this before your setValue.
DatabaseReference database = FirebaseDatabase.getInstance().getReference("EmployeeInfo");
Then,
database.push().setValue(employeeObject);
The .push() method creates a child with a unique key in your database.
Try checking firebase docs for more info
Save Data on Firebase
, Read and Write on firebase
The key is like this Firebase RTDB

Related

Firebase Realtime Database - Data from Code doesn't "reach" the database

I'm working with Firebase's realtime database in order to make a recipe application in android studio. The code runs fine and nothing crashes, but every time it's supposed to send information to the database, it does not. I attempted to create a shell for it to put data into, and instead, I saw it erase it once it got past the part where it was supposed to send the data. I've done all the required imports, implementations and dependencies according to their documentation, as well as wrote the code according to it too, but it doesn't seem to work.
Firebase Realtime Database before I send data, plus rules screenshot:
Firebase RD before
Firebase RD rules
After it runs the logic to send the data, I see it go red and disappear, like it was deleted, and nothing is left behind.
Here is my HomeScreen.java code:
package com.capteamfour.recipeappdatabase;
import android.content.Intent;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
public class HomeScreen extends AppCompatActivity {
final FirebaseDatabase mDatabase = FirebaseDatabase.getInstance();
DatabaseReference mDatabaseUsers = mDatabase.getReference("USERS");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
newUser(FirebaseAuth.getInstance().getCurrentUser().getDisplayName(),
FirebaseAuth.getInstance().getCurrentUser().getEmail());
String username = FirebaseAuth.getInstance().getCurrentUser().getDisplayName();
String email = FirebaseAuth.getInstance().getCurrentUser().getEmail();
TextView userWelcome = (TextView) findViewById(R.id.userWelcome);
FloatingActionButton addRecipe = (FloatingActionButton) findViewById(R.id.addRecipeButton);
ImageButton userProfile = (ImageButton) findViewById(R.id.userProfileButton);
// Welcomes the current user
userWelcome.setText("Welcome, " + username + "!");
// Creates a listener for the "add recipe" button; takes user to recipe form activity
addRecipe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent toRecipeForm = new Intent(HomeScreen.this, recipeForm.class);
startActivity(toRecipeForm);
}
});
// Creates a listener for the "user Profile Button" button; takes user to profile activity
userProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent ToProfile = new Intent(HomeScreen.this, Profile.class);
startActivity(ToProfile);
}
});
}
public void newUser(String name, String email)
{
userProfile user = new userProfile(name, email);
System.out.println("This is what I need to send: " + mDatabaseUsers.setValue(user));
mDatabaseUsers.setValue(user);
}
}
I declare a database instance and create a reference to the USERS path as global variables, and then made a function newUser(String name, String email) that creates an instance of a userProfile() class for me and is supposed to then send it to the database using the next line (the Sys.out was me trying to see what it was attempting to send if anything at all).
userProfile class code:
package com.capteamfour.recipeappdatabase;
import com.google.firebase.database.IgnoreExtraProperties;
import java.util.ArrayList;
import java.util.List;
#IgnoreExtraProperties
public class userProfile {
private String username;
private String email;
private List<Recipe> subRecipes = new ArrayList<>();
// Not yet implemented
private List<Recipe> favRecipes = new ArrayList<>();
private List<Recipe> savedRecipes = new ArrayList<>();
// A user profile will include their name, the recipes they've submitted, as well as recipes they've
// favorited or saved to their profile. Saved recipes are private to the user.
public userProfile() {
// Default constructor for DataSnapshot.getValue(userProfile.class) calls
}
public userProfile(String usernameIn, String emailIn)
{
this.username = username;
this.email = email;
}
public String getUsername () {
return this.username;
}
public String getEmail() {
return this.email;
}
/*
Each of these add functions will check the length of the given array and either
add to the end of it if there's already results, or just adds it on the empty array.
Example: array empty, then array[0] = recipe
array has values, then array[length + 1] = recipe
*/
public void addSubRecipe (Recipe recipe) {
int size = this.subRecipes.size();
if (size == 0) {
subRecipes.add(recipe);
}
else {
subRecipes.add(size+1, recipe);
}
}
public List<Recipe> getSubRecipes() {
return subRecipes.subList(0, (subRecipes.size()));
}
/*
These are commented out to prevent additional bugs and confusion while they're not implemented
public void addSavedRecipe (Recipe recipe) {
int size = this.savedRecipes.size();
if (size == 0) {
savedRecipes.add(recipe);
}
else {
savedRecipes.add(size + 1, recipe);
}
}
public List<Recipe> getSavedRecipes() {
return this.savedRecipes.subList(0, (subRecipes.size() + 1));
}
/*public void addFavRecipe (Recipe recipe) {
int size = this.favRecipes.size();
if (size == 0) {
favRecipes.add(recipe);
}
else {
favRecipes.add(size + 1, recipe);
}
}
public List<Recipe> getFavRecipes() {
return this.favRecipes.subList(0, (subRecipes.size() + 1));
}*/
}
In this class, I made sure to have an empty constructor with additional constructors and the usual get/set functions so that the database could work with it.
I appreciate any and all pointers that anyone could provide on how to fix this issue. This is for my college capstone course, and it's holding us up quite drastically for what appears to be no good reason. Thanks everyone.

Why is the array list ratingItemList showing as empty after insertion of several items?

While its in the Document Snapshot loop its adding the ratings to the ratingItemList. I know this for sure because I'm also printing the size of the list in the Log and it's increasing.
But after it comes out of that loop just to be sure I check whether it is empty or not and it prints Empty List in the log.
Can you guys help me out locating the error?
package com.example.ratingapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.ArrayList;
import java.util.List;
public class YourRating extends AppCompatActivity {
private List<ratingItem> ratingItemList;
private FirebaseFirestore db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_your_rating);
ratingItemList=new ArrayList<>();
db = FirebaseFirestore.getInstance();
db.collection("userRatings").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
if(!queryDocumentSnapshots.isEmpty()){
Log.d("Check1","Ratings Exist");
List<DocumentSnapshot> documentSnapshots = queryDocumentSnapshots.getDocuments();
for(DocumentSnapshot doc : documentSnapshots) {
String rating = doc.getString("Rating");
//Log.d("Rating",rating);
com.google.firebase.Timestamp date = doc.getTimestamp("Date");
//Log.d("Date",date.toString());
ratingItem newRatingItem = new ratingItem(rating, date);
Log.d("Rating", newRatingItem.getRating());
Log.d("Date", newRatingItem.getTimestamp().toString());
ratingItemList.add(newRatingItem);
Log.d("Size ",String.valueOf(ratingItemList.size()));
}
}
else{
Toast.makeText(YourRating.this,"No ratings available!",Toast.LENGTH_LONG).show();
}
}
});
if(ratingItemList.isEmpty()){
Log.d("Empty","Empty List");
}
for(ratingItem r: ratingItemList){
Log.d("Rating1",r.getRating());
Log.d("Date1",r.getTimestamp().toString());
}
}
}
if you call for background thread result in first line and print it on very next line, your callback method does not give guarantee to run before the very next line. It will start to execute thread of first line and without waiting for response run the next line. So you are getting it empty.
Check list size also in callback onSuccess() method, after for loop:
public class YourRating extends AppCompatActivity {
private List<ratingItem> ratingItemList;
private FirebaseFirestore db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_your_rating);
ratingItemList = new ArrayList<>();
db = FirebaseFirestore.getInstance();
db.collection("userRatings").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
if (!queryDocumentSnapshots.isEmpty()) {
Log.d("Check1", "Ratings Exist");
List<DocumentSnapshot> documentSnapshots = queryDocumentSnapshots.getDocuments();
for (DocumentSnapshot doc : documentSnapshots) {
String rating = doc.getString("Rating");
//Log.d("Rating",rating);
com.google.firebase.Timestamp date = doc.getTimestamp("Date");
//Log.d("Date",date.toString());
ratingItem newRatingItem = new ratingItem(rating, date);
Log.d("Rating", newRatingItem.getRating());
Log.d("Date", newRatingItem.getTimestamp().toString());
ratingItemList.add(newRatingItem);
Log.d("Size ", String.valueOf(ratingItemList.size()));
}
if (ratingItemList.isEmpty()) {
Log.d("Empty", "Empty List");
}
for (ratingItem r : ratingItemList) {
Log.d("Rating1", r.getRating());
Log.d("Date1", r.getTimestamp().toString());
}
} else {
Toast.makeText(YourRating.this, "No ratings available!", Toast.LENGTH_LONG).show();
}
}
});
}
}
you success listener runs on the background thread and it is a promise that will be run when the data will be obtained from the firebase.
on the other hand the piece of code where you check the array list is empty or not runs on the ui thread. It does not wait for the data to be fetched.

My app keeps crashing when I go to another activity

I am trying to make an app named 'moviesinfo', in which I have a login page, with sign up and forgot password option. When I try to log in, the app crashes. I also don't know if the data entered on the sign-up page is being stored in the database or not.
This is my mainactivity.java
package com.example.moviesinfo;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
SQLiteDatabase db;
SQLiteOpenHelper openHelper;
private EditText user;
private EditText password;
private Button btn;
private Button btn2;
private Button forgot;
Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
forgot=findViewById(R.id.forgot);
btn2=(Button) findViewById(R.id.signup);
user= (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
btn = (Button) findViewById(R.id.login);
openHelper= new DatabaseHelper(this);
db=openHelper.getReadableDatabase();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String username1= user.getText().toString();
String password1= password.getText().toString();
cursor = db.rawQuery("SELECT * FROM " +DatabaseHelper.TABLENAME + " WHERE " + DatabaseHelper.COL2 + "=? AND " + DatabaseHelper.COL3+"=?", new String[]{username1,password1});
if (cursor!=null){
if (cursor.getCount()>0){
cursor.moveToNext();
Intent intent = new Intent(MainActivity.this,listmenu.class);
startActivity(intent);
//Toast.makeText(getApplicationContext(),"Login Successful", Toast.LENGTH_SHORT).show();//
}else{
Toast.makeText(getApplicationContext(),"Error" , Toast.LENGTH_SHORT).show();
}
}
}
});
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sign_up();
}
});
forgot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
forgot();
}
});
}
private void sign_up()
{
Intent intent= new Intent(MainActivity.this, signup.class);
startActivity(intent);
}
private void forgot()
{
Intent intent= new Intent(MainActivity.this, forgot.class);
startActivity(intent);
}
}
This is the signup.java class
package com.example.moviesinfo;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.lang.String;
import java.util.ArrayList;
public class signup extends AppCompatActivity {
SQLiteOpenHelper openHelper;
DatabaseHelper db;
SQLiteDatabase db1;
public String uname = "";
public String pwd = "";
public ArrayList<String> cpwd = new ArrayList<String>();
EditText e1, e2, e3;
Button b1,b2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
openHelper= new DatabaseHelper(this);
e1 = (EditText) findViewById(R.id.username);
e2 = (EditText) findViewById(R.id.password);
e3 = (EditText) findViewById(R.id.cpwd);
b1 = (Button) findViewById(R.id.save);
b2 = (Button) findViewById(R.id.login2);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1=openHelper.getWritableDatabase();
String username =e1.getText().toString();
String password =e2.getText().toString();
String confirm_password =e3.getText().toString();
insert_data(username,password,confirm_password);
}
});
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(signup.this,MainActivity.class);
startActivity(intent);
}
});
}
public void insert_data(String username, String password, String confirm_password)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.COL2, username);
contentValues.put(DatabaseHelper.COL3, password);
contentValues.put(DatabaseHelper.COL4, confirm_password);
long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
}
}
This is the DatabseHelper.java class
package com.example.moviesinfo;
import com.example.moviesinfo.signup;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME="userdetails.db";
public static final String TABLENAME="user details";
public static final String COL1="id";
public static final String COL2="username";
public static final String COL3="password";
public static final String COL4="confirmpassword";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null,1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + "TABLENAME(ID INTEGER PRIMARY KEY AUTOINCREMENT,USERNAME TEXT,PASSWORD TEXT,CONFIRMPASSWORD TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " +TABLENAME);
onCreate(db);
}
}
I expect that when I click the login button it should jump to the next activity with checking the login details from the database.
Issue 1
The first issue you will encounter is that the table name user details has a space. user will be extracted as the identifier but then the SQL parser is not expecting details, it is not a keyword or clause and thus a syntax error as per the following which would be found in the log :-
5-19 14:09:14.335 26779-26779/s.e.so56180693anotheractivity E/AndroidRuntime: FATAL EXCEPTION: main
Process: s.e.so56180693anotheractivity, PID: 26779
java.lang.RuntimeException: Unable to start activity ComponentInfo{s.e.so56180693anotheractivity/s.e.so56180693anotheractivity.MainActivity}: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:514)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1769)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1698)
at s.e.so56180693anotheractivity.DatabaseHelper.onCreate(DatabaseHelper.java:33)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:393)
at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
at s.e.so56180693anotheractivity.MainActivity.onCreate(MainActivity.java:35)
at android.app.Activity.performCreate(Activity.java:7136)
see Debug your app
An identifier can have normally unacceptable characters, such as a space, start with a number, if it is enclosed in specific characters as per :-
If you want to use a keyword as a name, you need to quote it. There are four ways of quoting keywords in SQLite:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not
standard SQL. This quoting mechanism is used by MS Access and SQL
Server and is included in SQLite for compatibility.
keyword A keyword enclosed in grave accents (ASCII code 96) is an identifier.
This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.
e.g. you could have :-
public static final String TABLENAME="user details"; //<<<<<<<<<< cannot have spaces in a name unless enclosed
//!!!!NOTE!!!! ONLY 1 of the below would be allowed
public static final String TABLENAME="`user details`"; //<<<<<<<<<< e.g (with space)
public static final String TABLENAME= "[user details]";
public static final String TABLENAME = "\"user details\"";
public static final String TABLENAME = "'user details'";
public static final String TABLENAME="user_details"; //<<<<<<<<<< changed to this for testing.
Read the comments
Fix for Issue 1
public static final String TABLENAME="user details";
was changed to :-
public static final String TABLENAME="user_details";
The App was uninstalled and rerun.
Issue 2
The next issue is that the SQL to create the table will not create a table named according to the value that the constant TABLENAME (user_details after applying the Fix 1) has. The table is named TABLENAME as the word TABLENAME is in quotes.
It results in the exception :-
2019-05-19 13:56:15.118 26443-26443/s.e.so56180693anotheractivity E/SQLiteLog: (1) no such table: user_details
Fix for Issue 2
The following is how it would be suggested that the CREATE TABLE sql is setup:-
//Uses the identifiers (names) as per the variables
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLENAME + "(" +
COL1 + " INTEGER PRIMARY KEY," + // NO NEED FOR INEFFICIENT AUTOINCREMENT
COL2 + " TEXT UNIQUE," + //ADDED UNIQUE so that user names are not duplicated
COL3 + " TEXT, " +
COL4 + " TEXT" +
")"
);
That is constants are used for the names.
IMPORTANT as this is a change to the database schema and that the database exists you MUST delete the database so that the DatabaseHelper onCreate method will run.
The keyword UNIQUE has been added, otherwise the same user could be added multiple times
Question
I also don't know if the data entered on the sign-up page is being
stored in the database or not.
To enable you to know or not and as you should now be aware of looking in the log then amending the insert_data method as follows will enable you to see if the data is being stored.
public long insert_data(String username, String password, String confirm_password) // Signature changed to return long (id)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.COL2, username);
contentValues.put(DatabaseHelper.COL3, password);
contentValues.put(DatabaseHelper.COL4, confirm_password);
long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
//TODO REMOVE LOGGING BEFORE PUBLISHING THE APP
if (id > 0) {
Log.d("INSERTUSERDETAILSROW","The row was successfully inserted into the " + DatabaseHelper.TABLENAME + " table.");
} else {
Log.d("INSERTUSERDETAILSROW","Row not inserted!!!!!!!!!!");
}
return id; // Can be useful to have access to the id that was generated. Note method signature change
}
Example output :-
in the log :-
D/INSERTUSERDETAILSROW: The row was successfully inserted into the user_details table.
Issue 4
If the password and confirm_password values do not match, the row is still added i.e. the confirm_password values serves no purpose.
Fix for Issue 4
A check is added to only add data if the password and confirm_password values match. If they do not then a Toast is issued.
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1=openHelper.getWritableDatabase();
String username =e1.getText().toString();
String password =e2.getText().toString();
String confirm_password =e3.getText().toString();
if (password.equals(confirm_password)) {
insert_data(username, password, confirm_password);
} else {
Toast.makeText(v.getContext(),"Password and Confirm Password do not match. Data not added.",Toast.LENGTH_LONG).show();
}
}
});
Issue 5
Although it won't appear to be a problem your should not start the activity when you want to return from an activity as that will destroy the initial activity and start another. The correct way is to finish the activity and it will then return to the actual activity from which it is was started from.
Fix for Issue 5
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Intent intent = new Intent(signup.this,MainActivity.class);
//startActivity(intent);
finish(); //<<<<<<<<<< Proper way to return
}
});
Done
That's it. The App should now be relatively functional as far as logging in and signing up is concerned.

I want to save user profile in local sqlite database and the user information

I've done firebase authentication for login and sign up and now i want
to save user profile in local sqlite database. I've fetched the user
information from firebase and storing them in a string variable and
passing these variables to the Adduser function to save this data in
the local database.But data is not getting stored and showing "Error
with saving user" ,that is rowid is "-1" always. i'm new to android.
please help me to solve this issue. thanks in advance
java file
package com.example.mansi.busezon;
import android.app.Application;
import android.content.ContentValues;
mport android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.example.mansi.busezon.data.dbContract;
import com.example.mansi.busezon.data.dbHelper;
import com.google.firebase.FirebaseApp;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
i
public class SELL_BUY extends AppCompatActivity {
// private dbHelper mDbHelper;
String name;
String email ;
String address ;
String phoneno ;
String password ;
//String userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_sell__buy);
check();
TextView BUY= (TextView) findViewById(R.id.buy);
BUY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//create intent to open the activity
Intent BUYintent= new Intent(SELL_BUY.this,HomeActivity.class);
//start the new activity
startActivity(BUYintent);
}
});
TextView SELL= (TextView) findViewById(R.id.sell);
SELL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//create intent to open the activity
Intent SELLintent= new Intent(SELL_BUY.this,SellHomepage.class);
//start the new activity
startActivity(SELLintent);
}
});
}
public void sendMessage(View view)
{
Intent intent = new Intent(SELL_BUY.this, profile_page.class);
startActivity(intent);
}
private void check()
{
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
//database reference pointing to demo node
// DatabaseReference demoRef = rootRef.child("CI8hvEW0sfZ0oU1GziTpGYPJv2z2");
// String value = "User22";
// //push creates a unique id in database
// demoRef.push().setValue(value);
rootRef.addListenerForSingleValueEvent(new ValueEventListener()
{
String userId=getIntent().getStringExtra("Id");
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren())
{
if(ds.getKey().equals(userId))
{
//name1="aakritijohar";
name = ds.child("name").getValue(String.class);
email = ds.child("email").getValue(String.class);
address = ds.child("addres").getValue(String.class);
phoneno = ds.child("phoneno").getValue(String.class);
TextView textView = (TextView) findViewById(R.id.test);
textView.setText(phoneno);
password = ds.child("password").getValue(String.class);
Toast.makeText(SELL_BUY.this, email + " " + ds.getKey(), Toast.LENGTH_SHORT).show();
insertUser(name,email,address,phoneno,password);
}
}
Bundle extras=getIntent().getExtras();
if(extras!=null) {
String name = extras.getString("name");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
private void insertUser(String nameString,String EMAILString,String addressString,String numbertString,String pass) {
// Create database helper
dbHelper mDbHelper = new dbHelper(this);
// Gets the database in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(dbContract.userEntry.COLUMN_USER_NAME, nameString);
values.put(dbContract.userEntry.COLUMN_EMAIL, EMAILString);
values.put(dbContract.userEntry.COLUMN_number, numbertString);
values.put(dbContract.userEntry.COLUMN_address, addressString);
values.put(dbContract.userEntry.COLUMN_password, pass);
// Insert a new row for user in the database, returning the ID of that new row.
long newRowId = db.insert(dbContract.userEntry.TABLE_NAME, null, values);
// Show a toast message depending on whether or not the insertion was successful
if (newRowId == -1) {
// If the row ID is -1, then there was an error with insertion.
Toast.makeText(this, "Error with saving user", Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the insertion was successful and we can display a toast with the row ID.
Toast.makeText(this, "user saved " + newRowId, Toast.LENGTH_SHORT).show();
}
}
}
database helper class
package com.example.mansi.busezon.data;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Database helper for Pets app. Manages database creation and version management.
*/
public class dbHelper extends SQLiteOpenHelper {
public static final String LOG_TAG = dbHelper.class.getSimpleName();
/** Name of the database file */
private static final String DATABASE_NAME = "user.db";
/**
* Database version. If you change the database schema, you must increment the database version.
*/
private static final int DATABASE_VERSION = 1;
/**
* Constructs a new instance of {#link dbHelper}.
*
* #param context of the app
*/
public dbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is created for the first time.
*/
#Override
public void onCreate(SQLiteDatabase db) {
// Create a String that contains the SQL statement to create the pets table
String SQL_CREATE_USER_TABLE = "CREATE TABLE " + dbContract.userEntry.TABLE_NAME + " ("
+ dbContract.userEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ dbContract.userEntry.COLUMN_USER_NAME + " TEXT NOT NULL, "
+ dbContract.userEntry.COLUMN_address + " VARCHAR, "
+ dbContract.userEntry.COLUMN_number + " VARCHAR NOT NULL, "
+ dbContract.userEntry.COLUMN_EMAIL + " VARCHAR NOT NULL, "
+ dbContract.userEntry.COLUMN_password + " VARCHAR NOT NULL );";
// Execute the SQL statement
db.execSQL(SQL_CREATE_USER_TABLE);
}
/**
* This is called when the database needs to be upgraded.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// The database is still at version 1, so there's nothing to do be done here.
}
}
There doesn't appear to be anything wrong with the code as it is.
As such I suspect that your issue may be that you have changed the table structure since running the App.
e.g. by adding a new column and then changing the code accordingly
However, that you have then not taken into consideration that the onCreate method only gets automatically invoked when the database is created.
That is the 'onCreate' method does not run every time the App is started.
I'd suggest that deleting the App's data or uninstalling the App and then rerunning the App will resolve the issue.
If that doesn't resolve the issue then please check the log as that should contain a stack-trace for when the insert comes across the issue even though the App doesn't itself crash (you could use the insertOrThrow method instead of insert which would then result in an exception/crash).
If you then still have issues, please update the question to include the stack-trace.

Android - Firebase - Retrieving Data from Node X and Sending it to Node Y

Aim
Allow Users to send reports to the authorities. Reports will be stored and will not be overwritten when new Reports are entered by the same user
Picture of Current Database
The current user signed in is able to store "Incident Report" into the Database but apparently when the user submits another "Incident Report", the newly submitted "Incident Report" will overwrite the data of the previous "Incident Report"
Picture of Desired Database
The Yellow Highlighted data is supposed to be data retrieved from the "Users" child "name" which is the Red Circled data
For example, if the data within the Red Circled data is "Abe Long", the data of the Yellow Highlighted will be "Abe Long" as well.
In addition to that, when the current signed in User submits an "Incident Report", each new one created will create a new Unique Key. This means it will not overwrite the previously submitted data.
Report Fragment Class
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.util.Date;
import java.util.HashMap;
public class ReportFragment extends Fragment {
private EditText jReportDatePick;
private EditText jReportTimeEnt;
private EditText jReportLocationEnt;
private EditText jReportDescriptionEnt;
private Button jReportSendBtn;
private FirebaseUser jReportCurrentUserID;
private DatabaseReference jReportByUserDatabase;
private ProgressDialog jReportLoad;
public ReportFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View viewRoot = inflater.inflate(R.layout.fragment_report, container, false);
jReportDatePick = viewRoot.findViewById(R.id.reportDatePick);
jReportTimeEnt = viewRoot.findViewById(R.id.reportTimeEnt);
jReportLocationEnt = viewRoot.findViewById(R.id.reportLocationEnt);
jReportDescriptionEnt = viewRoot.findViewById(R.id.reportDescriptionEnt);
jReportSendBtn = viewRoot.findViewById(R.id.reportSendBtn);
jReportLoad = new ProgressDialog(getActivity());
jReportSendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String userReportDate = jReportDatePick.getText().toString();
String userReportTime = jReportTimeEnt.getText().toString();
String userReportLocation = jReportLocationEnt.getText().toString();
String userReportDescription = jReportDescriptionEnt.getText().toString();
if(!TextUtils.isEmpty(userReportDate)&&
!TextUtils.isEmpty(userReportTime)&&
!TextUtils.isEmpty(userReportLocation)&&
!TextUtils.isEmpty(userReportDescription)){
submitReport(userReportDate, userReportTime, userReportLocation, userReportDescription);
jReportLoad.setTitle("Sending Report");
jReportLoad.setMessage("Please wait while the report is being sent");
jReportLoad.setCanceledOnTouchOutside(false);
jReportLoad.show();
}else{
jReportLoad.dismiss();
Toast.makeText(getActivity(), "Report failed to be sent due to empty inputs", Toast.LENGTH_SHORT).show();
}
}
});
return viewRoot;
}
private void submitReport(final String userReportDate,final String userReportTime,
final String userReportLocation,final String userReportDescription) {
jReportCurrentUserID = FirebaseAuth.getInstance().getCurrentUser();
final String reportUserID = jReportCurrentUserID.getUid();
jReportByUserDatabase = FirebaseDatabase.getInstance().getReference().child("Incident Reports").child(reportUserID);
HashMap<String, String> incidentReportUser = new HashMap<>();
incidentReportUser.put("date", userReportDate);
incidentReportUser.put("time", userReportTime);
incidentReportUser.put("location", userReportLocation);
incidentReportUser.put("description", userReportDescription);
jReportByUserDatabase.setValue(incidentReportUser).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
jReportLoad.dismiss();
Toast.makeText(getActivity(), "Report was Sent", Toast.LENGTH_SHORT).show();
jReportDatePick.setText("");
jReportTimeEnt.setText("");
jReportLocationEnt.setText("");
jReportDescriptionEnt.setText("");
}else{
jReportLoad.dismiss();
Toast.makeText(getActivity(), "Report failed to be sent", Toast.LENGTH_SHORT).show();
}
}
});
}
}
Additional Comments
How the Report Fragment works
I do not intend for the currently signed in User to be able to submit their name, that will create a possibility of the User entering someone else's name into the "Incident Report". I intend for the "CurrentUser signed in" name to be retrieved and entered into the "Incident Report" automatically.
How the Report Fragment is coded
Instead of putting jReportByUserDatabase.setValue(incidentReportUser) I have tried putting .updateChildren while using Map<String, Object>. The problem was that each data was not entered under a "Unique ID" which will be stored under "Incident Report" within the Data Tree
Solution to the Problem
Helped by both Cadet and JavaBanana
Implementing a "For Loop DataSnapshot" to loop through the data and retrieving the desired one by also using the "Users class" which contains the name, address, status, etc.
private void submitReport(final String userReportDate,final String userReportTime,
final String userReportLocation,final String userReportDescription) {
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
HashMap<String, String> incidentReportUser = new HashMap<>();
incidentReportUser.put("name", user.name);
incidentReportUser.put("date", userReportDate);
incidentReportUser.put("time", userReportTime);
incidentReportUser.put("location", userReportLocation);
incidentReportUser.put("description", userReportDescription);
jReportCurrentUserID = FirebaseAuth.getInstance().getCurrentUser();
final String reportUserID = jReportCurrentUserID.getUid();
jReportByUserDatabase = FirebaseDatabase.getInstance().getReference().child("Incident Reports").child(reportUserID);
jReportByUserDatabase.push().setValue(incidentReportUser).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
jReportLoad.dismiss();
Toast.makeText(getActivity(), "Report was Sent", Toast.LENGTH_SHORT).show();
jReportDatePick.setText("");
jReportTimeEnt.setText("");
jReportLocationEnt.setText("");
jReportDescriptionEnt.setText("");
}else{
jReportLoad.dismiss();
Toast.makeText(getActivity(), "Report failed to be sent", Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Write it by this way
(Push adds values, instead of overriding).
jReportByUserDatabase.push()setValue(incidentReportUser)
Also, I recommend to make the Report node containing the user fields also. Like combine them to flat node.
Okay so the main problem with your designs that you are storing the reports under the user's Id which firebase will overwrite obviously.
You can generate a random key for storing your reports and set your report at the generated key in the database.
public class Report {
String reportId; // This is important
String reporterId; //This is important
String reporterName;
String userType;
String status;
String address;
String neibourhood;
String image;
}
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference("Incident Reports");
String reportId = dbRef.push().getKey(); //This generates a new key and returns it
Report report = new Report("report id", "reporter id", "other stuff"... "etc");
dbRef.child(reportId).setValue(report);
To Retrieve the names of the Users
DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Loop through the retrieved user data
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
System.out.println(user.name);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});

Categories

Resources