In my android app i am using Firebase Storage to save images i have set security rules to null then too i am not able to upload images and getting error.
Below are my error ,security rules and android code.Please let me know what i did wrong in code.
Logcat error : StorageException has occurred.
User does not have permission to access this object.
Code: -13021 HttpResult: 403
Security rules:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth == null;
}
}
}
Java code:
galleryFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(SetAvatar.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
}
else{
Intent i = new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i,GALLERY_INTENT);
}
}
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
if(requestCode == GALLERY_INTENT && resultCode == RESULT_OK){
uri = data.getData();
cv.setImageURI(uri);
final StorageReference filepath = sRef.child("Profile
Images").child(uri.getLastPathSegment());
UploadTask uploadTask = filepath.putFile(uri);
uploadTask.addOnSuccessListener(new
OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(SetAvatar.this, "Upload
successful",Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(SetAvatar.this, "Upload Failed -> " + e,
Toast.LENGTH_SHORT).show();
}
});
}
}
Thanks
change your security rules to:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
But this will make your Bucket to be modified by anyone and I don't recommend it. However, you may use it for testing purposes.
Related
So I have added some security rules to my firebase storage when I use the simulation it works as expected but when I actually perform from my app it shows me this error
2021-04-09 16:43:00.322 17375-17375/com.margsapp.messenger E/StorageException: StorageException has occurred.
User does not have permission to access this object.
Code: -13021 HttpResult: 403
2021-04-09 16:43:00.323 17375-17375/com.margsapp.messenger E/StorageException: The server has terminated the upload session
java.io.IOException: The server has terminated the upload session
Caused by: java.io.IOException: { "error": { "code": 403, "message": "Permission denied. Could not perform this operation" }}
So I simplified the log cat
And this is my security rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read: if request.auth != null;
}
match/ProfileImages/{userId}{ //Am trying to upload an image to this directory.
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId;
}
match/GroupImages{
allow read,write: if request.auth != null;
}
If the code which uploads image is necessary I will upload
If I done any mistake in rules please let me know the right way to do it.
EDIT: This is the code which uploads the image
storageReference = FirebaseStorage.getInstance().getReference("/ProfileImages/"+firebaseUser.getUid());
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GALLERY_PICK && resultCode == RESULT_OK && data != null) {
imageUri = data.getData();
CropImage.activity(imageUri)
.setGuidelines(CropImageView.Guidelines.ON)
.setAspectRatio(1, 1)
.start(this);
}
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
loadingBar.setTitle("Profile Image");
loadingBar.setMessage("Please wait, while we update your profile picture...");
loadingBar.show();
loadingBar.setCanceledOnTouchOutside(false);
assert result != null;
Uri resultUri = result.getUri();
StorageReference filepath = storageReference.child(System.currentTimeMillis()
+ "." + getFileExtension(resultUri));
uploadTask = filepath.putFile(resultUri);
uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
#Override
public Task<Uri> then(#NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return filepath.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Toast.makeText(edit_profile.this, "Image has been stored in our servers", Toast.LENGTH_SHORT).show();
Uri downloadUri = task.getResult();
assert downloadUri != null;
String mUri = downloadUri.toString();
reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser.getUid());
HashMap<String, Object> map = new HashMap<>();
map.put("imageURL", mUri);
reference.updateChildren(map);
loadingBar.dismiss();
}
}
});
} else {
Toast.makeText(this, "Profile Picture updation is cancelled", Toast.LENGTH_SHORT).show();
loadingBar.dismiss();
}
}
}
private String getFileExtension(Uri uri){
ContentResolver contentResolver = edit_profile.this.getContentResolver();
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri));
}
To solve your problem you need to match all paths within:
ProfileImages -> userId
In your Storage bucket. So your rules should look like this:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read: if request.auth != null;
}
match /ProfileImages/{userId} {
match /{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
}
I am using the following method to save information.
private void saveUserData() {
progressDialog.setTitle("Account Settings");
progressDialog.setMessage("Please wait while settings are being changed...");
progressDialog.show();
final StorageReference imageRef = storageReference
.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
imageRef.putFile(imageUri);
}
I have removed some lines of code for accessing the database.
This the log cat description.
E/StorageException: StorageException has occurred.
An unknown error occurred, please check the HTTP result code and inner exception for server response.
Code: -13000 HttpResult: 0
E/AndroidRuntime: FATAL EXCEPTION: FirebaseStorage-Upload-1
I seached this error code and found
case unknown = -13000
The app doesn't crash when I comment this line.
imageRef.putFile(imageUri);
On a side note, I am able to save text info successfully and even retrieve it from the database.
EDIT
Here is the code.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
storageReference = FirebaseStorage.getInstance()
.getReference().child("Profile Pictures");
profileImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, galleryPick);
}
});
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveUserData();
}
});
retrieveUserInformation();
}
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == galleryPick && resultCode == RESULT_OK && data != null) {
imageUri = data.getData();
profileImageView.setImageURI(imageUri);
}
}
Given the variable name imageUri, you're trying to upload to Storage from a URL, which is not supported. You'll first have to download the data from the URL, and then upload it to Storage.
I am trying to add an image to the user information in the real time database(firebase) for android. I have uploaded the image on the firebase storage but how will I be able to add the image in the database for that user?
Code Below:
//inside onCreate() method
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i,request_code);
}
});
Here I am clicking on the imageview, so I will be able to change it and get an image from the gallery.
Here I authenticate the user and send data to the database:
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(StudentSignUpActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Toast.makeText(getApplicationContext(), "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(getApplicationContext(), "Authentication failed." + task.getException(),
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(StudentSignUpActivity.this, HomeActivity.class));
finish();
}
}
});
mCurrentUser=FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference newStudent=mDatabase.push();
newStudent.child("email").setValue(email);
newStudent.child("password").setValue(password);
newStudent.child("name").setValue(name);
newStudent.child("date").setValue(dates);
newStudent.child("phone").setValue(number);
newStudent.child("uid").setValue(mCurrentUser.getUid());
//outside of onCreate()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==request_code&&resultCode==RESULT_OK){
Uri uri=data.getData();
StorageReference filepath=mStorage.child("Images").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
}
});
}
}
In the above code I have uploaded the image to the firebase storage. Now how will i be able to add that image as a child for a specific user.
I think I need to do something like this:
newStudent.child("image").setValue(uri_here);
But I am unable to figure how to get the uri of the image and how to add that uri in the setValue() since its in another method.
You can use the method getDownloadUrl() in the success listener to access the download URL:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==request_code&&resultCode==RESULT_OK){
Uri uri=data.getData();
StorageReference filepath=mStorage.child("Images").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUrl = taskSnapshot.getDownloadUrl();
newStudent.child("image").setValue(downloadUrl);
}
});
}
}
As an aside, instead of using push(), I recommend storing the user's data with the uid as the key. This will make your data easier to find.
private DatabaseReference newStudent;
mCurrentUser=FirebaseAuth.getInstance().getCurrentUser();
newStudent=mDatabase.child(mCurrentUser.getUid());
newStudent.child("email").setValue(email);
// etc
Just to update because I spent sometime to find this answer, getDownloadUrl() is NOT a function of taskSnapshot anymore. So in order to get the image URL from Firebase Storage you need to add a listener to
taskSnapshot.getMetadata().getReference().getDownloadUrl()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==request_code&&resultCode==RESULT_OK){
Uri uri=data.getData();
StorageReference filepath=mStorage.child("Images").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
taskSnapshot.getMetadata().getReference().getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
newStudent.child("image").setValue(uri);
}
});
}
});
}
}
Now it's safe to use uri to whatever you want
I have not use authentication yet, in the screen i can see the progress dialog working but its not getting stop. I think there is a problem.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==GALLERY_INTENT&&resultCode==RESULT_OK){
progressDialog.setMessage("Uploading Image...");
progressDialog.show();
Uri uri = data.getData();
StorageReference filepath = mStorageRef;
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
progressDialog.dismiss();
Toast.makeText(Profile.this, "Uploading Finished",Toast.LENGTH_LONG).show();
}
});
}
}
//firebase storage rule
service firebase.storage {
match /b/csapplication-b6e5e.appspot.com/o {
match /{allPaths=**} {
allow read, write: if request.auth == null;
}
}
}
Its because of if your file upload to firebase was successful means your ProgressDialog will be dismissed ,if not in the case of failure you have to dismiss (ProgressDialog) in the OnFailure method in the code below .
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
progressDialog.dismiss();
Toast.makeText(Profile.this, "Uploading Finished",Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads - Dismiss the ProgressDialog here
progressDialog.dismiss();
Toast.makeText(Profile.this, "Unable to Uploaded Error in Firebase",Toast.LENGTH_LONG).show();
}});
Does Google's Firebase support video storage ? Am planning to upload video and want to download on-demand. I started with Firebase. Are there any other APIs or services that give a similar functionality ?
Of course you can upload video or any files on firebase.
btnupload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent myIntent = new Intent(Intent.ACTION_GET_CONTENT);
myIntent.setType("*/*");
startActivityForResult(Intent.createChooser(myIntent,"Select File:-"),101);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode==RESULT_CANCELED)
{
// action cancelled
}
if(resultCode==RESULT_OK)
{
// Create a storage reference from our app
StorageReference storageRef = storage.getReferenceFromUrl("gs://<<Your App Bucket Address>>");
Uri uri = data.getData();
StorageReference riversRef = storageRef.child("files/"+uri.getLastPathSegment());
UploadTask uploadTask = riversRef.putFile(uri);
// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
Toast.makeText(MainActivity.this, "Upload Failed", Toast.LENGTH_SHORT).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
Toast.makeText(MainActivity.this, "Upload Success", Toast.LENGTH_SHORT).show();
}
});
}
}
Firebase has a Firebase Storage offering that allows you to store any arbitrary files.
It doesn't offer any video-specific features or functionality, but it will work if you simply want to have a place to store and retrieve your video files.