-
Notifications
You must be signed in to change notification settings - Fork 2.2k
🔥[Android][Storage] Upload to firebase storage from android internal folder fails #2558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Smells like a FileProvider issue since you're failing on a content URI. This is a separate project but examine this: https://github.com/mikehardy/react-native-update-apk#manual-steps-for-android |
This is not related to firebase storage, I also use firebase storage and image-picker together To process the uri on my Android, I use another library (ex: rn-fetch-blob, react-native-fs) so that the uri obtained from the original image picker (content: //) will be made into a file: // |
@agungkes I don't believe that is recommended in android anymore - attempting to convert a content URI to a file URI. The ContentResolver system is specifically in place to abstract content from the file system so that other more ephemeral content providers can also provide images etc, such as Google Drive etc. Or so that permissions can be adequately checked, for instance in Android 10 you can have "external read access" as a permission but because of scoped storage might still be denied access to a file if you reach for it directly, whereas from a Content URI you might have permission. |
@agungkes Some background reading - if you look at the comments on all the proposed solutions it's clear things work sometimes and not others, and that's because there are lots of cases where there is no "file", so you can't get a file path - in other words, you need to handle content paths somehow https://stackoverflow.com/questions/5657411/android-getting-a-file-uri-from-a-content-uri?noredirect=1&lq=1 |
@mikehardy I'm sorry to bring back this thread, but app crashing on android when using putFile seems so random. I was never able to reproduce the issue on my android devices, but I have hundreds of users who face this problem. (very small ratio, but still) I have tried all kind of "handling content paths" without success (playing with the "file://" extension, adding or removing it etc) It still crashes on their device and I am unable to find a permanent fix for all devices. Has anyone found a good fix that work for all cases on android? That would be amazing. |
If you're still using file:// URIs at all, I would suspect they've chosen a data source that cannot be converted to file:// and you must use content resolver and the more virtual content:// URIs. That's all I can think of. @pierroo you don't give any information on your versions, the code in use, the error or anything though, so 🤷♂ just guessing here |
Okay guys. I've spent 3 days to resolving this problem. Actually react-native-firebase storage doesn't understand uri as "content://com.android.externalstorage". The real path should be given to file as "/data/emulated/0". Fetch this can eg use rn-feth-blob fs.state(fileUri) |
I'm not sure to understand, so using rn-feth-blob fs.state(fileUri) would ALWAYS return the correct path for filePut to handle on android? Nothing to worry about anymore using this method? |
I've tested this on google drive, sd-card, internal storage, cyrillic name, and not have problems |
@ffqs awesome, that sounds promising. Would it be possible for you to share your piece of code where you use this method before calling putFile? Do you use it for both iOS and android, or only android? |
Don't need for ios, just fileUri |
@ffqs got it. So, could you please share the code you used exactly with putFile? all examples I found on internet used the "put" method that does not exist with react native firebase. |
...
|
Thank you @ffqs , I will give it a try right now and let you know. So you don't need the usual blob polyfill: const Blob = RNFetchBlob.polyfill.Blob ? I didn't know about this "RNFetchBlob.fs.stat" method, I have to look into it. Thank you for your time! |
putFile already uploading file |
I come with bad news, unfortunately I sent a modified apk with this new RNFetchBlob method, but still no success, their app crashes when calling the putFile... Back to point zero. |
Please more info. I use "react-native-firebase": "5.5.6". Also rn-fetch-blob was forked for support sd-card and google drive https://github.com/ffqs/rn-fetch-blob#46c672507c497154f2daeded433abb86ee7e3980 |
I also use react-native-firebase 5.5.6, with latest rn-fetch-blob, and yes it does work for me and 99% of users. But for some devices, it just crashes and I am still unable to know why: the imagePicker does show the image in the state taken from path or uri properly, but as soon as it comes to sending it to "putFile": it crashes. It crashes on a Lenovo A7000-a, os version 5.0, and on a Primo R4 Plus, os version 5.1, for example. |
The fork @ffqs is using is vital, it's doing the ContentResolver local cache file I was talking about, whereas the regular rn-fetch-blob does not do that in the base of the fork at least (maybe it's fixed in more current master) ffqs/rn-fetch-blob@9380242#diff-a46d0c3ac70a38fb8df8d56e9d80e121R211 |
I'm not sure the check it is doing is comprehensive though, I would expand it to any 'content://' URI, really ffqs/rn-fetch-blob@9380242#diff-a46d0c3ac70a38fb8df8d56e9d80e121R269 |
But this contentResolver does not seem to be enough yet; is there no 100% bulletproof method to handle any kind of file path/uri users might be picking from imagePicker? |
I think the bulletproof method would be to always do the local cache from a content:// uRI, like it is doing but only for google docs. Of course what level of bullet-proof? How do you handle failure if the device does not have enough space for the local copy? Might be easier to do a PR for react-native-firebase v5 that implements the v6 put command! esp since there is already an implementation to grab from v6. |
Regardless of very special cases like "not enough space for local copy", if such a method did exist I would be happy to implement it. how to "always" do the local cache from a content uri? isn't it what the method of ffqs is supposed to do? And even if they implemented the put method in v5; does it mean that as a safety measure android users should always rely on put method and forget the putFile method to make sure it will work for most? |
Then check the second code link I posted where they check 'is it a google photos URL?' and instead say 'is it a content:// URL?' then if it is do the same thing I think
A good point, yeah - I can see why doing putFile might be interesting in some cases? If you really know you have a file:// URL somehow? But I would never trust that a file on disk actually exists any more. Android has tried to move to all virtual streams of data provided on demand |
uhh :( |
So, there is no way to 100% fix this photo issue on v5, is that what it means? Migrating to v6 will be painful, but that is not the worst part, having to forget entirely about putFile and use put instead to handle all cases sounds bad. Should we wait for firebase summit to be done before we bother the invertase team with this? |
For unrelated reasons I was looking at rn-fetch-blob yesterday and there is a pull request that I personally reviewed that seems like it would fix things at that layer: joltup/rn-fetch-blob#165 So I would try: yarn add joltup/react-native-modal-datetime-picker#165/head as an rn-fetch-blob dependency, and then re-test something that gives you a virtual file (a content:// URI with no backing file, like from picasa or a contact photo or whatever) while using the code in that PR and see how you go. As for the invertase team and timing, I'd say that's about right. But putFile exists in v6 https://invertase.io/oss/react-native-firebase/v6/storage/reference/reference#putFile - so you don't have to forget about it, and on a scan of that code it winds up here which says that it is content-uri safe: https://firebase.google.com/docs/reference/android/com/google/firebase/storage/StorageReference.html#putFile(android.net.Uri,%20com.google.firebase.storage.StorageMetadata) But then again I just checked the v5.x.x code thoroughly for comparison and it looks like it's doing roughly the same thing https://github.com/invertase/react-native-firebase/blob/v5.x.x/android/src/main/java/io/invertase/firebase/storage/RNFirebaseStorage.java#L376 - calling into the API I linked above which is supposed to be content-uri safe So this seems pretty strange to me now, based on code inspection, this should be working, and moving to rnfbv6 probably won't affect it. You could try the rn-fetch-blob PR I linked above, or investigate more deeply into why the access via content URIs is failing, but something's not right here and I'm leaning towards a permissions issue somehow - content resolver permissions are separate from external storage I believe, they are inter-app relationships, not file system, so maybe there is something there |
@mikehardy, just checking in on this issue. I'm in the process of upgrading to RN 0.61.1 paired with rnfb v5.5.6. Currently we're always having the user select a profile pic from the Android DocumentPicker, so we're getting the In Gradle I'm referencing I'm not sure that I completely follow the conversation above, but do you recommend attempting to upgrade to rnfb v6.0.0, or trying to make the |
I can't decide for you @cdunkel as you may need notifications and that's not done for v6 yet. I have not personally tried what I mentioned above with the rn-fetch-blob PR but it seemed fine on review if you need RNFBv5 I'd use that PR |
@mikehardy, thanks! We're not using notifications through Firebase, so that shouldn't be an issue. I'll try the rn-fetch-blob PR first, though, and see if that solves my problem. I did find something interesting yesterday while working on different ways to resolve this. I'm using the |
you might be interested in the logcat output then, perhaps you are having a permission issue between the apps that the content resolver system is blocking you on |
@mikehardy I've reviewed my logcat output, as well as my RN console output and compared my success and fail cases. It appears that the primary difference is that when the upload succeeds it's coming from My current guess is that there's some issue with resolving the documents and photo providers into a real URI that can be uploaded to FirebaseStorage? |
my log from logcat, when i try upload file "latest-search" from SD-card (correctly for inner storage also) using only putFile
|
Yep - this verifies my hunch though I'm not sure exactly what to do about it, but it's inter-app permissions. For some reason the ContentResolver that has the content you want is not allowed to export it to you. Maybe you need Camera permissions on Android (I believe that allows access to camera roll) or external storage read (for the sd-card file) - although external storage is about to get a seismic shift as it goes to "scoped storage", a whole different thing... |
@mikehardy I was able to eventually get my code working. I had to use a combination of tactics to get file and image uploading working on both iOS and Android. For uploading a document selected from storage on Android I'm using react-native-document-picker. Before showing the Document Picker I had to request For image upload I'm effectively doing the same thing except that I'm using react-native-image-picker, and I have to use react-native-fs to parse out the real path using Regarding accessing the camera roll, I believe that I still needed external storage permissions to read that. |
That all sounds about like what I'd expect. Not an awesome developer experience but matches my personal experience with Android file access - it's messy and yes - very permission based. At least react-native-permissions is really easy to work with. Glad you got it working! |
Thanks! Hopefully my experience can help @ffqs or anyone else find a solution that works for them. |
Hello 👋, to help manage issues we automatically close stale issues.
|
Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information. |
I've encountered this issue and have been stuck on this for 2 days in a row. Then I used RNFetchBlob like your approach. It works well. Thank you very much. |
This works. |
The cleanest solution is to use react-native-fs:
|
assuming that doesn't fill up available memory |
True. With content links you can only stream them. We need a streaming API to put to storage. |
I am using this as a work around but still, as @mikehardy affirmed, you need memory available :/
|
Thanks everyone. After a lot of try and error I was able to "fix" my issue. However most other libraries support the import RNFS from 'react-native-fs';
export const getFixedUri = async (uri: string): Promise<string> => {
if (uri.startsWith('content://')) {
const destPath = `${RNFS.TemporaryDirectoryPath}/tempVideo`;
await RNFS.copyFile(uri, destPath);
return destPath;
}
return uri;
}; Usage: ref.putFile(await getFixedUri(path)) I have to use |
Interesting - thanks for posting that @levino - it looks like it has an implied dependency on module |
I apply all the solution above for Android 11 level 30. but i am still facing the same issue but still facing the same issue kindly help me if you solved this for android 11. I already add the permission and manually allow that
and i also add android:requestLegacyExternalStorage="true" but not working on android 11 |
Thank you so much @levino |
If the problematic uri is coming from react-native-document-picker, I think the following solution is neater than the other solutions suggested so far (above.) However, it still has the limitation of the need for storage to copy the file - like most of the other solutions! The following solution does NOT need additional libraries, like react-native-fs or react-native-blob-util. |
@Bilal-Abdeen Thanks for the suggestion. It worked for me |
Issue
Description
🔥 So my issue is really similar (if not the same) to this one. So i'm using this library so the user can select or take a picture to display in the app and then upload it to the firebase storage.
The issue occurs in Android when the user selects a picture from a place different than the default photo gallery, then when it tries to upload the uri to the firebase storage it outputs an error. This error doesn't happen when the user takes a picture or select the gallery of the device.
In iOS this problem doesn't happen as well because the user can only select a picture from the default gallery (or take a picture) when using the image picker component in this system.
This is my code to uploading the uri to the firebase storage:
When the given uri is from the camera or the users' gallery (such as this one:
file:///Users/Library/Developer/CoreSimulator/Devices/B27D6137-7BF5…F-397B-4439-BD5A-73350751C834/tmp/6B4587BC-7103-4577-BC2B-C16ABF5A9F6E.jpg
) theputFile
works fine and uploads it to firebase storage.However if the uri is from a different place in the android file system (such as this one
content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F78/ORIGINAL/NONE/1779395513
) theputFile
stops working and returns an error.This is the error it outputs:
I thought the problem might be related to permissions in the device when accessing the image in that particular location, but i already asked (and checked) permission for writing and reading from the external storage. Also, the image picker component can display that image in the app, so it must have permission to access it.
This is my code for the image picker component:
Project Files
iOS
Click To Expand
ios/Podfile
:AppDelegate.m
:// N/A
Android
Click To Expand
Have you converted to AndroidX?
android/gradle.settings
jetifier=true
for Android compatibility?jetifier
for react-native compatibility?android/build.gradle
:android/app/build.gradle
:android/settings.gradle
:MainApplication.java
:AndroidManifest.xml
:Environment
Click To Expand
react-native info
output:react-native-firebase
version you're using that has this issue:5.5.3
Firebase
module(s) you're using that has the issue:implementation "com.google.firebase:firebase-storage:17.0.0
TypeScript
?Y
The text was updated successfully, but these errors were encountered: