var storage = FirebaseStorage.getInstance().reference
storage.child(product.name).putBytes(convert.toByteArray()).addOnSuccessListener {
progress.dismiss()
startActivity(Intent(this, ProductList::class.java))
Toast.makeText(this, "Product Uploaded Successfully.", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener {
progress.dismiss()
Toast.makeText(this, "Cannot Uploaded...", Toast.LENGTH_SHORT).show()
}
I am getting this error:
I have tried changing the project but couldn't solve this problem
You're getting the following exception:
StorageException: Could not open resulting stream
A possible reason might be due to improper security rules. If you're in the development phase, then you can use the following rules:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
But remember, once your app goes into production, you have to secure your app accordingly.
Another possible reason might be due to trying to open large files. According to the official documentation of StorageReference#putBytes(byte[])
Asynchronously uploads byte data to this StorageReference. This is not recommended for large files. Instead upload a file via putFile or an InputStream via putStream.
Related
I have a minimal working example for uploading a zip file to firebase from my Unity-Android app. The sample works fine in playing the app in the Unity-Editor mode.
However, when building for Android, I'm getting the following error:
System.AggregateException: One or more errors occured. (No content provider: /storage/emulated/0/Android/data/com.MyCompany.MyApp/cache/myFile.zip)
Firesbase.Sotrage.StorageException: No content provider
When googling the issue, I get instructions on how to edit a "Custom AndroidManifest.xml" and adding a FileProvider class using native Android code (by compiling a library project using Android Studio etc.).
This looks like a complete overkill for my problem. Shouldn't there be a nice and easy way to share a file, created by my app, stored in the app's own folder with firebase?
So I found a workaround: Instead of trying to send the file directly to firebase, I can
first read the file into RAM as a byte array
then send the bytearray to firebase
Here some code:
FirebaseStorage storage;
StorageReference storageRef;
storage = FirebaseStorage.DefaultInstance;
storageRef = storage.RootReference;
byte[] fileData = File.ReadAllBytes(localFilePath);
StorageReference storageDataRef = storageRef.Child(firebaseFilename);
storageDataRef.PutBytesAsync(fileData)
.ContinueWith((Task<StorageMetadata> task) => {
if (task.IsFaulted || task.IsCanceled) {
Debug.Log(task.Exception.ToString());
// Uh-oh, an error occurred!
}
else {
// Metadata contains file metadata such as size, content-type, and md5hash.
StorageMetadata metadata = task.Result;
string md5Hash = metadata.Md5Hash;
Debug.Log("Finished uploading...");
Debug.Log("md5 hash = " + md5Hash);
}
});
Now I'm not getting any "FileContentProvider" errors anymore. Not sure why I have to do this though...
I'm trying to figure out a way to delete images from the external storage automatically.
In my app, the user takes photos for some purposes which are saved in a folder created by the app inside the Pictures folder. After some time, the photos taken are of no use anymore. Therefore, I'm trying to write some code that enables the app to delete these photos by itself.
Before you ask, I'm aware that is not normal for an app to delete files from the app without any command from the user. But my app is used inside the company, only by employees etc.
I'm using ctx.contentResolver.delete(uri, null, null) to delete the image file. I have a catch to recover the SecurityException like this:
catch (e: SecurityException) {
val intentSender = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
MediaStore.createDeleteR`your text`equest(ctx.contentResolver, listOf(uri)).intentSender
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
val recoverableSecurityException = e as? RecoverableSecurityException
recoverableSecurityException?.userAction?.actionIntent?.intentSender
}
else -> null
}
intentSender?.let { sender ->
intentSenderLauncher.launch(
IntentSenderRequest.Builder(sender).build()
)
}
}
And everything seems to work fine at a first look as the intent to accept appears -- but no image is shown and nothing gets deleted.
Am I doing something wrong? What could be a way to delete these files?
I'm working on an app built using Firebase on Android. The application is for keeping track of in-patients currently under our care. Our team can enter progress notes for each patient, and add tasks needed yo be performed for each patient, and mark them when they're done. I have all that done, however, I need to add one more option, where I can select a patient, and export the current view (with all the many-to-one data associated with the main record) to an external file (editable file), so we may use it to write his/her final report and summary. I've searched online, and found many recommending to export the view as a bitmap, then to pdf ... but that makes the document un-editable .. If someone has any ideas, or can point me to the right direction, I'd be grateful. The final format is not really an issue ... pdf, txt, doc, html .... I guess it doesn't really matter, as long as the data can be exported as it is in the current view (ordered and making sense), and can be edited.
Any help will be appreciated. Thank you.
I once made an app with the option to export data to a txt file on the device storage. Here's the method I used:
public void exportTxt(String text){
if(Environment.getExternalStorageState().equalsIgnoreCase("mounted"))//Check if Device Storage is present
{
try {
File root = new File(Environment.getExternalStorageDirectory(), "MyAppFolder");//You might want to change this to the name of your app. (This is a folder that will be created to store all of your txt files)
if (!root.exists()) {
root.mkdirs();
}
File myTxt = new File(root, "filename.txt"); //You might want to change the filename
FileWriter writer = new FileWriter(myTxt);
writer.append(text);//Writing the text
writer.flush();
writer.close();
Toast.makeText(this, "File exported", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
else
Toast.makeText(this, "Can't access device storage!", Toast.LENGTH_SHORT).show();
}
Don't forget to add this permission to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
So in order to use this method, all you need to do is group all of your currentView data on a single String and pass it as a parameter.
These are my Firebase Storage rules.
match
/{allPaths=**} {
allow read, write: if request.auth != null;
This is how users are adding pictures to the storage
StorageReference filepathOne = mStorage.child(user_data.getString("uidkey", null)).child("Photos").child("id_one");
As you can see I am using the UID as part of the filepath name. My assumption was that, whenever a user uploads the picture they want, only they would be able to access it as they have the unique UID. However, I created a new user account and for some reason, that user is able to access the photos uploaded by another user even though they have different UID.
I should also point out that I am storing the URI in a sharedpref, and then later converting it into a string to have it display the picture.
This is how I store in the SharedPref
Uri downloadUrl = taskSnapshot.getDownloadUrl();
Picasso.with(getContext())
.load(downloadUrl)
.fit().centerCrop()
.into(image);
editor.putString(user_idone, (taskSnapshot.getDownloadUrl()).toString());
editor.commit();
This is how I extract from the Pref and display.
Picasso.with(getContext())
.load(Uri.parse(user_data.getString("idonekey", null)))
.fit().centerCrop()
.into((ImageView) getView().findViewById(R.id.image));
Currently your rules say "anyone can read/write anything, so long as they are authenticated." It sounds like you want to change the rules to mirror your file structure and provide tighter security:
service firebase.storage {
match /b/<your-bucket-name>/o {
match /{userId}/Photos/{fileName} {
allow read: if request.auth.uid == userId;
}
}
}
Our rules docs talk in greater depth on user and group based security.
I'm getting an error:
The download quota for this file has been exceeded
This is a response from the drive api. I'm trying to download a file simply via following url:
String url = "https://www.googleapis.com/drive/v2/files/" + media.getId() + "?alt=media\n"
My file is a few MBs big and I just can't download it. I'm using scribe and oauth2, I create a request, sign it and send it. The response shows me that the signature works, but I don't know why I always get the above error response from google...
Other things like retrieving a list of all my files and my user work just fine and work multiple times as well...
Since you're using Android, why not try to call it using the Java API client, as discussed in the Download Files section of the documentation.
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
// uses alt=media query parameter to request content
return service.files().get(file.getId()).executeMediaAsInputStream();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
Another alternative is to use the webContentLink to retrieve the download URL.
Hope this helps!
Log in multcloud
Add Cloud (Google Drive) & Login and Allow Drive
select the file and Share get public url