I was trying to store data to Firebase Cloud Firestore but after running my app it showed this error in the log.
[Firestore]: Write failed at Backpaper Registration/WSjZoirLf8WRBuGCVbUZ: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
This is the part of my code.
fb=FirebaseFirestore.getInstance();
map=new HashMap<String>();
map.put("Name of Department",txtDepartment);
map.put("Name of Student",txtStudentName);
map.put("Registration No",txtRegNo);
map.put("CGPA in Previous Semester",txtCgpa);
map.put("Phone",txtPhoneNo);
map.put("Email",txtEMail);
map.put("Subject 1",txtSubject1);
map.put("Subject 2",txtSubject2);
map.put("Subject 3",txtSubject3);
map.put("Subject 4",txtSubject4);
map.put("Subject 5",txtSubject5);
map.put("Payment Details(Rs.)",txtPaymentDetails);
map.put("Payment Date",txtPaymentDate);
fb.collection("Backpaper Registration").add(map).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
#Override
public void onComplete(#NonNull Task<DocumentReference> task) {
if(task.isSuccessful()){
Toast.makeText(Backpaper.this, "Registration Successful", Toast.LENGTH_SHORT).show();
startActivity(new Intent(Backpaper.this,Academic.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP));
finish();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Backpaper.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Can somebody help me?
You should check out the Rules on Firebase
Change allow read, write: if false; to true;
Nots:
It is not advised to choose this solution because it makes the
database unsafe.
Only use this for testing purposes.
You need the Firebase rules setting at Firebase console.
If you had signed into project, the rules setting may like :
// Allow read/write access on all documents to any user signed in to the application
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
If you just demo the function, you call setting the rules:
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
The more officially document you can found here.
https://firebase.google.com/docs/firestore/security/get-started
It could be because, you have not given the read & write permission to firebase.
Change your Firebase Database to test mode.
1. Go to your firebase database console
2. Go to Rules
3. Start in test mode
This will change allow read, write: true
This turn off the database security but for testing purpose it is advised
Related
I've seen many people ask the question already. But unfortunately, my knowledge of programming is limited only to writing PowerShell scripts :) and I cannot figure out the code.
Perhaps someone will throw java and xml code, applications. Which can turn off or turn on mobile hotspot programmatically, without going into the settings.
I was able to achieve that the settings would open where the user can toggle the state of the hotspot. But I need what the user could not do, tk. the application works in kiosk mode and it only needs to access the API and switch the state of the hotspot.
You can use AndroidWifiManager library to enable hotspot programmatically.
Here is how it can be used in your code (This is already available in the Git ReadMe, I am just rewriting it.)
Step 1 : Add the jcenter repository to your build file
allprojects {
repositories {
...
jcenter()
}
}
Step 2 : Add the dependency
dependencies {
implementation 'com.vkpapps.wifimanager:APManager:1.0.0'
}
Step 3 : Use in your app
Handle error manually
APManager apManager = APManager.getApManager(this);
apManager.turnOnHotspot(this, new APManager.OnSuccessListener() {
#Override
public void onSuccess(String ssid, String password) {
//write your logic
}
}, new APManager.OnFailureListener() {
#Override
public void onFailure(int failureCode, #Nullable Exception e) {
//handle error like give access to location permission,write system setting permission,
//disconnect wifi,turn off already created hotspot,enable GPS provider
//or use DefaultFailureListener class to handle automatically
}
});
//use this line to turn off Hotspot
//apManager.disableWifiAp();
Handle error automatically with inbuilt class
APManager apManager = APManager.getApManager(this);
apManager.turnOnHotspot(this,
new APManager.OnSuccessListener() {
#Override
public void onSuccess(#NonNull String ssid, #NonNull String password) {
//write your logic
}
},
new DefaultFailureListener(this)
);
//use this line to turn off Hotspot
//apManager.disableWifiAp();
I'm using Firestore in my app and I can't figure out how to handle at user level the exceptions thrown by that. (I mean what to display to the user when such exceptions occur).
For example, to perform any CRUD operation on Firestore (DocumentReference#get, DocumentReference#set, DocumentReference#update) a Task is returned, which might contain an exception, but in the documentation I can't find why this exception might be thrown by Firestore.
Is there something better that we can do, rather than simply log the exception and show a generic message like "an error occurred, please try again later"?
As in the official documentation regarding getting data, you can get the exception from the task object like this:
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d(TAG, "DocumentSnapshot data: " + document.getData());
} else {
Log.d(TAG, "No such document");
}
} else {
//Log the error if the task is not successful
Log.d(TAG, "get failed with ", task.getException());
}
}
});
And remember, a Task is complete when the work represented by the Task is finished, regardless of its success or failure. There may or may not have been an error, and you have to check for that. On the orter side, a Task is "successful" when the work represented by the task is finished, as expected, with no errors.
As #Raj mentioned in his answer, you can also use addOnFailureListener but note, if there is a loss of network connectivity (there is no network connection on user device), neither onSuccess() nor onFailure() are triggered. This behavior makes sense, since the task is only considered completed when the data has been committed (or rejected) on the Firebase server. onComplete(Task<T> task) method is called also only when the Task completes. So in case of no internet connection, neither onComplete is triggered.
You can use onFailureListener() method of Firestore and get the errors while getting, setting or updating the data. In this example I have used it in setting data:-
firestore.collection("User").document(uid).set(user).addOnSuccessListener(this, new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid)
{
//Data Saved Successfully
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(Exception e)
{
//Toast error using method -> e.getMessage()
}
});
If you want to catch exceptions in firebase authentication module then refer:- How to catch a Firebase Auth specific exceptions
In the below example, I call a method signinUser(username, password) This then runs through Firebase to determine if the user has successfully or unsuccessfully been able to sign in. However, it takes Firebase a short amount of time to do this, which by that time the method has already returned with the original value, before being updated by the successful-ness / unsuccessful-ness of the sign in process.
How would I go about returning the method once the Firebase authentication has done it's thing. I am aware I could put a timer on when the return statement is called, however, I'm not sure how that'd work as slow internet connects could cause it to take longer than the given amount set by a timer.
My code is as follows:
public AuthSuccess signinUser(String username, String password) {
mAuth.signInWithEmailAndPassword(username + "#debugrestaurant.com", password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(context, "Successful!", Toast.LENGTH_SHORT).show();
authSuccess = new AuthSuccess(true, null);
} else {
Toast.makeText(context, "Unsuccessful!", Toast.LENGTH_SHORT).show();
authSuccess = new AuthSuccess(false, task.getException());
Toast.makeText(context, "Exception: " + authSuccess.getException().getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}
});
return authSuccess;
}
Please note that the class AuthSuccess is simply an object I've created to collect whether or not the sign in was successful, and if not, to collect the exception.
You cannot return something now that hasn't been loaded yet. With other words, you cannot simply use the authSuccess object outside the onComplete() method because it will always be null due the asynchronous behaviour of this method. This means that by the time you are trying to return that result outside that method, the data hasn't finished loading yet from the database and that's why is not accessible. A quick solve for this problem would be to use the value of authSuccess only inside the onComplete() method, otherwise I recommend you see the last part of my anwser from this post in which I have exaplined how it can be done using a custom callback. You can also take a look at this video for a better understanding.
Your old code is probably something like this
public void onSignInClick(){
AuthSuccess result = signinUser(username, password);
if(result.success){
startMainActivity();
}else{
showErrorPopUp();
}
}
Change this to:
public void onSignInClick(){
signinUser(username, password);
}
protected void handleLoginResult(AuthSuccess result){
if(result.success){
startMainActivity();
}else{
showErrorPopUp();
}
}
And at the very end of your onComplete method do:
handleLoginResult(authSuccess);
The issue I am ultimately trying to solve, before I pose my question, is the synchronicity of querying my Firebase database and writing code based on the result. A simple example to illustrate:
Boolean userFound = false;
DatabaseReference userName = FirebaseDatabase.getInstance().getReference().child("Profiles").child("Name");
userName.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.getValue().toString();
userFound = true;
Toast.makeText(getBaseContext(), "Welcome back, " + name + ".", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Never used this section
}
});
If (!userFound) {
Toast.makeText(getBaseContext(), "User not found.", Toast.LENGTH_SHORT).show();
}
In the example above, the listener looks for a name in the database. If the name is found it gives a welcome message and sets "userFound" to true. If a name is not found, "userFound" will remain as false and you can generate a user not found message.
The problem with this is that everything runs at the same instant and so you will always get the "User not found" message instantly, and then a few seconds later the listener might actually find the user and say "Welcome back".
I have been looking into how I can possible resolve this, and I have found Java Promises. Am I looking in the right direction? Here are two promise examples:
CompletableFuture.supplyAsync(this::failingMsg)
.exceptionally(ex -> new Result(Status.FAILED))
.thenAccept(this::notify);
This code looks great, and the article here is very detailed in its usage: http://www.deadcoderising.com/java8-writing-asynchronous-code-with-completablefuture/
Except for the fact that is will ONLY work in API 24 and above. Which means your app will not work on 90% of devices. So this is essentially worthless.
The other way of doing this is as follows:
try {
Promise { client.newCall(request).execute() }
.then { ... }
.thenAsync { ... }
.then { ... }
} catch (e: Exception) {
...
}
As explained here: https://medium.com/#sampsonjoliver/promises-in-android-and-java-d6b1c418ea6c
Except that when I try to use this code there is no such thing as Promise. It just says it cannot resolve the symbol. So this guy has written an article on something that doesn't even exist.
Am I looking at the right stuff here? The end game is to make my app wait for the result of any database lookup before continuing to process code. If I cannot do this, then the database becomes completely useless.
Thanks guys. Please help!
The solution with a problem using asynchronous APIs is pretty much always the same: move the code that needs access to the data into the method that is called when the data is available.
So in your case that means moving the check and toast into onDataChange:
DatabaseReference userName = FirebaseDatabase.getInstance().getReference().child("Profiles").child("Name");
userName.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Boolean userFound = false;
String name = dataSnapshot.getValue().toString();
userFound = true;
Toast.makeText(getBaseContext(), "Welcome back, " + name + ".", Toast.LENGTH_SHORT).show();
if (!userFound) {
Toast.makeText(getBaseContext(), "User not found.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
For more on this, see:
Setting Singleton property value in Firebase Listener
Doug's excellent blog post
Querying data from firebase
Wait Firebase async retrive data in android
Handle data returned by an Async task (Firebase)
Hi I tried to open some files from Google Drive in andoid app using Google Drive Api with:
ResourceClient.openFile(selectedFile.asDriveFile() , DriveFile.MODE_READ_WRITE)
My code worked just fine for Word format (docx), but for all ohters format i tried it threw
com.google.android.gms.common.api.ApiException: 10: This file is not openable.
exception. This exception is nowhere to be found and i really couldn't get rid of it. If anybody can help I would be really grateful.
EDIT: Btw. I claimed metadata for all files successfully.
EDIT 2: Even while using Google samples i could open just Word documents.
Code that I used just in case you would need it:
Signing in to google:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.build();
signInClient = GoogleSignIn.getClient(getApplicationContext(), gso);
startActivityForResult(signInClient.getSignInIntent(), SING_IN_REQEST_CODE);
Geting metadata and files:
contentsTask = resourceClient.getMetadata(selectedFile.asDriveResource())
.continueWithTask(new Continuation<Metadata, Task<DriveContents>>(){
#Override
public Task<DriveContents> then(#NonNull Task<Metadata> task) throws Exception {
if(task.isComplete() && task.isSuccessful()) {
Log.d(TAG, "Metadata claimed sucessfully");
if(task.getResult().isEditable())
Log.d(TAG, "File is edittable");
return resourceClient.openFile(selectedFile.asDriveFile() , DriveFile.MODE_READ_WRITE);
}
else {
Log.i(TAG, "Metadata wasn't claimed sucessfully" + task.isComplete());
return null;
}
}
} ).addOnSuccessListener(new OnSuccessListener<DriveContents>() {
#Override
public void onSuccess(DriveContents driveContents) {
Log.i(TAG, "successfully get driveContents");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i(TAG, "didn't successfully get driveContents", e);
}
});
EDIT: Issue has been replicated by: https://github.com/googledrive/android-demos/issues/70
So, I left and come back this topic 2 times, but for others: Despide the fact that i didn't find ANY DOCUMENTATION that would say that, Android Drive API (and my friend told me exactly same expirience with Java API) can only download files:
PDF
Pictures
and can not download:
office formats
If anybody would have anything to add (like I overlooked huge documentaion on topic wich formats can you acces with Drive APIs please let me know.-