I think I wrote the codes correctly, but Firebase does not add data in Realtime Database. I downloaded the JSON file, connected the project, checked it via Firebase tools, but it still doesn't add data. What can I do it?
Mainactivity.java - addevent class(it will work when click the button)
private void addEvent(){
String plan = etplan.getText().toString();
String note = etnote.getText().toString();
String date = etdate.getText().toString();
String time = ettime.getText().toString();
String remb = "false";
if (remember.isChecked()==true){
remb = "true";
}
else{
remb = "false";
}
String id = dbRef.push().getKey();
Events event = new Events(id,plan,note,date,time,remb);
dbRef.child(id).setValue(event);
}
I get the following error in the Run section of the program:
glUtilsParamSize: unknow param at 0x000082
And edited this code:
dbRef.child(id).setValue(event)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
Toast.makeText(MainActivity.this,"Events Added SUCCESSFULLY!", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this,e.toString(), Toast.LENGTH_SHORT).show();
}
});
Related
I have created a function to add a new user to Firestore Database:
public void addNewUser(String email, String username, String profile_photo){
FirebaseFirestore db = FirebaseFirestore.getInstance(); // this is instantiated here, just to show you
User user = new User(userID, (long) 1, email, StringManipulation.condenseUsername(username), username, profile_photo);
db.collection("Users").add(user)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Log.d(TAG, "DocumentSnapshot added with ID: " + documentReference.getId());
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error adding document", e);
}
});
}
And a function to fetch the data from the database, waiting for all the fields to appear in-app.
public UserSettings RetrieveUserSettings(){
Log.d(TAG, "getUserAccountSettings: retrieving user account settings from firebase");
User settings = new User();
DocumentReference userRef;
FirebaseAuth firebaseAuth=FirebaseAuth.getInstance();
try {
userRef = db.collection("Users")
.document(firebaseAuth.getCurrentUser().getUid());
userRef.get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if(documentSnapshot.exists())
{
settings.setDisplay_name(documentSnapshot.getString("display_name"));
settings.setUsername(documentSnapshot.getString("username"));
settings.setProfile_photo(documentSnapshot.getString("profile_photo"));
settings.setEmail(documentSnapshot.getString("email"));
settings.setPhone_number(documentSnapshot.getLong("phone_number"));
settings.setUser_id(documentSnapshot.getString("user_id"));
}
else{
Log.d(TAG, "doc not fount in getUserSettinghs ");
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: failed to fetch data");
}
});
} catch (NullPointerException e) {
Log.d(TAG, "getUserAccountSettings: NULLPointerException: " + e.getMessage());
}
Log.e(TAG, "getUserAccountSettings: retrieved user_account_settings information: " + settings.toString());
return new UserSettings(settings);
}
When I authenticate, this is the User UID that is generated: E5bBL0D9lCSKy5a0YdUJjuMVuUT2, but when I call the addNewUser function, my Firestore Database looks like this :
, so it is obvious that the User UID generated at authentication is not the same with the document id, which is :
XWwnRBklieJXSxokQuNe.Do you have any idea why this is happening?
As #HenryTwist mentioned in his comment, when using the following line of code:
db.collection("Users").add(user).addOnSuccessListener(/* ... /*);
You are adding a new "User" object to the "Users" collection using a random ID. The above line of code does the same thing as:
db.collection("Users").document().set(user).addOnSuccessListener(/* ... /*);
When you call CollectionReference's add() method or CollectionReference's document() method without passing any parameters, the built-in generator used by Firestore will always generate a random ID each time one of the methods is called.
As I see from the following line of code:
userRef = db.collection("Users").document(firebaseAuth.getCurrentUser().getUid());
You have already implemented Firebase Authentication, which is good. That being said, when you want to add new "User" object to the database, use the UID that comes from authentication process, as shown below:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
db.collection("Users").document(uid).set(user).addOnSuccessListener(/* ... /*);
In this way, the ID of the document will match the value of the "user_id" property in the database.
In my app a first time user creates a username which I save in Firestore as a document and set it as displayName (username = name of document = displayName). In the app the user has the option to change his username by typing a new one in an EditText. The result should be that the data which is stored under his current username moves to a new document which has the new username. So first I check if the new username is already in use by someone else, if not I create a new document which name is the new username. Now I get the current displayName (which is the current username) as a string and the input of the EditText as a string (new username). I Implemented a method to move documents from here: How to move a document in Cloud Firestore?
But when I call the method like this moveFirestoreDocument(usernameInput, oldUsername ); I get:
moveFirestoreDocument cannot be applied to (String, String)
How can I resolve this problem? Can I change the moveFirestoreDocument method so it can also takes Strings?
Here is the method:
public void moveFirestoreDocument(DocumentReference fromPath, final DocumentReference toPath) {
fromPath.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
toPath.set(document.getData())
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully written!");
fromPath.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully deleted!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error deleting document", e);
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error writing document", e);
}
});
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}
You get the following error:
I get "moveFirestoreDocument cannot be applied to (String, String)
Because you are trying to pass to the moveFirestoreDocument() method two arguments of type String and not of type DocumentReference. In order to be able to move a document, both fromPath and toPath must be of type DocumentReference so you can call set() on toPath and get() and delete() on fromPath.
Can I change the moveFirestoreDocument method so it can also takes Strings?
There is no need to change the method, you can simply pass the correct arguments when you call it. According to the details that you have provided in the question, I understand that you have a schema that is similar to this:
Firestore-root
|
--- users (collection)
|
--- John (document)
|
--- //User details
To rename the document call the method using:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference usersRef = rootRef.collection("users");
DocumentReference oldUsernameRef = usersRef.document(oldUsername);
DocumentReference usernameInputRef = usersRef.document(usernameInput);
moveFirestoreDocument(oldUsernameRef, usernameInputRef);
I am trying to get the download Url based on the condition that the image path for the storage reference is null or not.
I tried to put the whole code inside the if else statement instead of just assigning the value to download_uri inside the condition which resolves the error. I am not able to understand why this approach works and another one doesn't.
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String name=mProfileName.getText().toString();
if(!TextUtils.isEmpty(name) && mainImageUri!=null){
mProgressBar.setVisibility(View.VISIBLE);
if(isChanged){
//The task of storing the data goes through uploading the image as well.
user_id = mUser.getUid();
final StorageReference image_path= mStorageReference.child("profile_photo").child(user_id+".jpg");
image_path.putFile(mainImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()){
storeFireStore(image_path,name);
}else{
String error = task.getException().getMessage();
Toast.makeText(SetUpActivity.this,"Image Error: "+error,Toast.LENGTH_SHORT).show();
}
mProgressBar.setVisibility(View.INVISIBLE);
}
});
}else{
//The task of storing the data does not go through uploading the image.
storeFireStore(null,name);
mProgressBar.setVisibility(View.INVISIBLE);
}
}
}
});
}
private void storeFireStore(StorageReference image_path, final String name) {
final Uri[] download_uri = new Uri[1];
if(image_path!=null){
image_path.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
download_uri[0] =uri;
Log.d(TAG,"Download Url obtained");
}
});
} else{
download_uri[0] =mainImageUri;
Log.d(TAG,"Download Url obtained in else");
}
Map<String,String> userMap=new HashMap<>();
userMap.put("image", download_uri[0].toString());//line 202 this is
where the error occurs.userMap.put("name",name);
I expect to get the downLoad_uri but it provides a null value
image_path.getDownloadUrl().addOnSuccessListener() is asynchronous and returns immediately, before the results of the operation are complete. Your code goes on to access the download_uri array which is initialized with null values. You can only expect the array to have a populated value after the callback completes.
I don't know why you are doing unnecessary work to get download URL of image if you can do it by just simple on line of code.
Just use below code to upload image in firebase storage.
image_path.putFile(mainImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()){
// HERE YOU CAN DIRECTLY GET DOWNLOAD URL OF UPLOADED IMAGE USING TASK RESULT.
String downloadUrl = String.valueOf(taskSnapshot.getDownloadUrl());
storeFireStore(downloadUrl,name);
} else {
String error = task.getException().getMessage();
Toast.makeText(SetUpActivity.this,"Image Error: "+error,Toast.LENGTH_SHORT).show();
}
mProgressBar.setVisibility(View.INVISIBLE);
}
});
And make change in storeFireStore method like below,
private void storeFireStore(String image_path, final String name) {
Map<String, String> userMap = new HashMap<>();
userMap.put("image", image_path != null ? image_path : "");//line 202 this is where the error occurs.
userMap.put("name", name);
}
I am trying to insert data using the Retrofit library. The data has been inserted successfully and I am also receiving the response from the API, but my error is that I am not getting the intent Activity (AdminActivity.class) after the Toast. Can anyone help me on this??
private void createUserResponse() {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
CreateUserRequest createUserRequest = new CreateUserRequest(editTextUserId.getText().toString().trim(),
editTextPassword.getText().toString().trim(),
editTextUserName.getText().toString().trim(),
editTextProfileImage.getText().toString().trim(), editTextSchoolId.getText().toString().trim(),editTextRole.getText().toString().trim());
Call<CreateUserResponse> createUserResponseCall = apiInterface. createUserCall(createUserRequest);
createUserResponseCall.enqueue(new Callback<CreateUserResponse>() {
#Override
public void onResponse(Call<CreateUserResponse> call, Response<CreateUserResponse> response) {
Log.d("CreateUser" , "onResponse: " + response.body().getMessage());
String status = response.body().getStatus();
if (status.equals("sucess")){
String message = response.body().getMessage();
Toast.makeText(getActivity(),"User Created Successfully" + message,Toast.LENGTH_SHORT).show();
Intent i = new Intent(getActivity(), AdminActivity.class);
startActivity(i);
} else{
String message = response.body().getMessage();
Toast.makeText(getActivity(),"" + message, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<CreateUserResponse> call, Throwable t) {
}
});
}
You have a typo within your if-else condition, so your code do not execute the if statement even if you get a successful response.
Fix the following typo and try again:
if (status.equals("success")) // fixed typo on "sucess" word
I have an android app that is connected to an API through retrofit, ive succesfully logged in, if i press back button to return back to the login activity again, if i try re-logging in again, the app crashes and give me a NullPointerException.
here's connection code
private void loginUser(String email, String password) {
UnifyAuthenticationApiInterface service = this.client.create(UnifyAuthenticationApiInterface.class);
Call<UnifyAuthenticationApiResponse> call = service.staffLogin(email, password);
call.enqueue(new Callback<UnifyAuthenticationApiResponse>() {
#Override
public void onResponse(Call<UnifyAuthenticationApiResponse> call,
Response<UnifyAuthenticationApiResponse> response) {
UnifyAuthenticationApiResponse result = response.body();
School school = new School();
com.peterstev.unify.login.Data data = result.getData();
mySchoolsList = new ArrayList<School>();
mySchoolsList = data.getSchools();
staff = data.getStaff();
gotoHomeActivity();
}
#Override
public void onFailure(Call<UnifyAuthenticationApiResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Login Failed # onFailure", Toast.LENGTH_SHORT).show();
}
});
}
and the goToHomeActivity() is
private void gotoHomeActivity() {
progressDialog.dismiss();
if (mySchoolsList.size() > 1) {
schoolsListView = new ListView(MainActivity.this);
schoolsArrayAdapter = new SchoolListAdapter(MainActivity.this, android.R.layout.simple_list_item_1, mySchoolsList);
schoolsListView.setAdapter(schoolsArrayAdapter);
dialog = new Dialog(MainActivity.this);
dialog.setContentView(schoolsListView);
dialog.setTitle("Welcome " + staff.getFullName());
dialog.show();
} else {
Intent intent = new Intent(MainActivity.this, NavMainActivity.class);
startActivity(intent);
}
}
the NullPointerException gets thrown at
com.peterstev.unify.login.Data data = result.getData();
at first, it gets the data n succesfully logs in, but when i use the back button n try to log in again it crashes.
Debugger is your answer - check if you aren't loosing any data when going back - maybe you're storing login params somewhere in activity class but you're not saving instance state properly and second request is triggered without necessary data. Check state of variables just before calling your request first and second time.
In situation like that always best bet to place breakpoint and trigger your work step by step. You cannot be good developer without debugger skills.
I think for some reason, the data object wasn't receiving the result when i used the back button to navigate to the parent activity. so i used and if condition to make it get the required data.
private void loginUser(String email, String password) {
UnifyAuthenticationApiInterface service = this.client.create(UnifyAuthenticationApiInterface.class);
Call<UnifyAuthenticationApiResponse> call = service.staffLogin(email, password);
call.enqueue(new Callback<UnifyAuthenticationApiResponse>() {
#Override
public void onResponse(Call<UnifyAuthenticationApiResponse> call,
Response<UnifyAuthenticationApiResponse> response) {
if(response.isSuccessful()) {
UnifyAuthenticationApiResponse result = response.body();
School school = new School();
data = result.getData();
if(data == null) {
try{
this.onResponse(call, response);
}catch(NullPointerException NPE){
Log.d("NPE", NPE.getMessage());
}
}
mySchoolsList = new ArrayList<School>();
mySchoolsList = data.getSchools();
staff = data.getStaff();
gotoHomeActivity();
}
}
#Override
public void onFailure(Call<UnifyAuthenticationApiResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "Login Failed # onFailure", Toast.LENGTH_SHORT).show();
}
});
}