react native file system, fs, cannot find taken pictures - react-native

In my ReactNative application I am using "react-native-vision-camera": "^2.13.5" for taking pictures.
After the picture is taken and uploaded, I want to delete it from the device, but the RNFS (react-native-fs) cannot find the file by the given path on iOS and Android devicess:
I get the error
iOS ; [Error: ENOENT: no such file or directory, open
'/private/var/mobile/Containers/Data/Application/1BB2256A-ED83-407D-9C76-07431268779B/tmp/ReactNative/CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg']
Android ; [Error: File does not exist]
The path in Android is like: /data/user/0/packagename/cache/mrousavy2423256141715663083.jpg
const photo = await camera.current.takePhoto(); // camera: React.RefObject<Camera>
const task = storage().ref(<ref>).putFile(photo.path)
const result = await task.then(); // Firebase Storage can read and upload the photo
RNFS.stat(photo.path) // <-- Error: The file “CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg” couldn’t be opened because there is no such file.
RNFS.unlink(photo.path) // <-- [Error: ENOENT: no such file or directory, open '/private/var/mobile/Containers/Data/Application/1BB2256A-ED83-407D-9C76-07431268779B/tmp/ReactNative/CE2FA429-76C8-4BD9-925A-BED09B0B77BB.jpeg']
// Prepending file:// Does not work too
RNFS.unlink(`file://${photo.path}`)
RNFS.stat(`file://${photo.path}`)
Is it because of access permission that react-native-fs needs?
How does the firebase storage have access to the photo?
Is the path a real temp folder that gets cleared after the app is closed?
why react-native-vision-camera saves media there by default?
Do I really need to remove that media manually or does it get removed?
env:
"react-native": "0.68.2",
"react-native-fs": "^2.20.0",
"react-native-vision-camera": "^2.13.5",
physical device : iPhone 8 Plus with iOS 15.5

There is no need to delete the file as the photos are being stored in a temporary directory. It will be deleted when the app closes.
https://mrousavy.com/react-native-vision-camera/docs/api/interfaces/PhotoFile

Instead of calling RNFS.unlink(photo.path) try RNFS.unlink(photo.uri). The react-native-vision-camera API outputs a File object with a URI not a path.

Related

Expo, how to save file from app directory to local directory

Im new to React Native and im using Expo to create an iOS and Android app. All I want to do is save a file that is stored in the application to the users device.
Using downloadAsync and shareAsync I can download from a remote url and save it but I can not download or just share a local file stored in in the apps directory.
Ive tried
await shareAsync('file://./manuals/mypdf.pdf');
await shareAsync('./manuals/mypdf.pdf');
await shareAsync(require('./manuals/mypdf.pdf'));
and I get the error
[Unhandled promise rejection: Error: You don't have access to provided file.] or the app just crashes
Use loadAsync to download asset data to a local file in the device's cache directory. After that the asset file is accessible like any other file.
const [{ localUri }] = await Asset.loadAsync(require('./manuals/mypdf.pdf'));

React Native - How to upload Audio files with spaces in their names

I have successfully been able to upload file when the filename is just one word, When there are spaces in the name, the file, I get error from server.
Example: 1.] '.../musics/Love.m4a' -> upload successfully
2] '.../musics/Love Thy Neighbor.m4a' -> upload failed
Any idea on how to handle this issue in React native will be highly appreciated.
I have been trying to upload an audio file in react-native but because of space in file name not being able to upload to server, I get below error from a server;
**file:** {uri: 'file:///Users/fathom-d004/Library/Developer/CoreSi…m.brandarmy.user1-Inbox/Love%20Thy%20Neighbor.m4a',
name: 'Love Thy Neighbor.m4a', type: 'audio/x-m4a'}
error: Error: ENOENT: no such file or directory, open '/Users/fathom-d004/Library/Developer/CoreSimulator/Devices/83619055-D45F-4FA9-85CC-A2009A599EA7/data/Containers/Data/Application/FE596B31-0385-4F77-B342-EF354F86FF1B/tmp/com.brandarmy.user1-Inbox/Love%2520Thy%2520Neighbor.m4a'
Used below simple solution;
I believe I've found the error. The issue was that the file I was uploading had a space in it, so we need to decode the URL first before uploading file to server, like:
var decodedURL = decodeURIComponent(file.uri);
const base64 = await fs.readFile(decodedURL, "base64");
Thanks...!

Open file downloaded within React-Native app with another app

I am trying to open files (images, pdfs, videos, etc) downloaded with my React-Native app from my server.
So I'm using RNFetchBlob to download the file then I'm doing the following depending if it's an iOS or Android device:
openFile = (item, path) => {
if (Platform.OS === 'ios') {
RNFetchBlob.ios.previewDocument(path)
} else {
// I've tried setting a real mimetype instead of / but it still doesn't work
RNFetchBlob.android.actionViewIntent(path, '/')
}
}
On iOS it works as expected but nothing happens on Android even though I have apps that can read images, pdfs or videos on the device I'm testing on.
Any ideas why this doesn't work or how I could make the same thing with another library ?
Found out the reason for this, it's a know bug of the library and has a PR waiting to be merged (no timeframe from the repo owner).
Here is the link to the PR: https://github.com/joltup/rn-fetch-blob/pull/317
So basically this needs to be added to line 122-123 of file android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
If above is not working do to the below step:
overwrite the 121 line in android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 121 line
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 122 line

Enable react native android to load downloaded images

I have a legacy Android java application into which I am integrating react native. Per Facebook's instructions, I have a generic Activity into which I have added the following code:
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);
setContentView(mReactRootView);
However, in my case, I have downloaded my react native bundle and placed it in my Android device's cache, so I have amended that example by adding the following call:
.setJSBundleFile(mReactNativeLocalFile.getAbsolutePath())
This has enabled me to load my downloaded bundle successfully, however none of the images load. Thus, components that load images like:
<Image source={require('./img/background.jpg')} style={styles.backgroundImage} />
Do not render an actual image.
I have confirmed that all images were successfully extracted and placed in a folder named assets adjacent to my bundle. Thus, my folder structure looks like:
com.myapp/cache/templates/MyApp/
index.android.bundle
assets/
img/
background.jpg
Thus, can anyone tell me if it is possible for a react native template bundle that has been downloaded locally to the android file system to refer to images that have also been downloaded locally to the android file system?
Based on this change, the correct answer is a folder structure on your local disk that looks like this:
com.myapp/cache/templates/MyApp/
index.android.bundle
drawable-mdpi/
img_background.jpg

How to trace JavascriptException index.android.bundle:424:4194 to line number in JS source?

Google Play stack trace points the cause of crash at:
com.facebook.react.modules.core.JavascriptException: addWaypointDone
index.android.bundle:424:4194
I extracted index.android.bundle from the apk.
How do I get a JS source code line number from 424:4194 ?
Thanks Daniel. Your approach worked for me from the command-line!
I tried adding this to android/app/react.gradle but I could not find and source.map file under the ./android directory.
commandLine "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}”,
"--sourcemap-output", "source.map",
"--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets dest", resourcesDir
Is there a way to auto-build source.map file very time?
Thanks in advance,
To get an exact position you need a source map. If you don't keep those for your deploys you can regenerate it.
Check out the exact version you deployed from your VCS
Bundle it with source map output: react-native bundle --entry-file index.android.js --platform android --dev false --sourcemap-output source.map --bundle-output main.jsbundle (make sure you use the exact same dependency versions you used in your release)
Create a file findpos.js containing the following code:
findpos.js
var sourceMap = require('source-map');
var fs = require('fs');
var sourcemap = JSON.parse(fs.readFileSync('source.map', 'utf8'));
var smc = new sourceMap.SourceMapConsumer(sourcemap);
console.log(smc.originalPositionFor({
line: 424,
column: 4194
}));
Execute the script node findpos.js
You should get the exact location of the error (file, line and column).
How to use Atom to find the exception source code in the index.android.bundle
Get stack trace from Google Play
Rename the apk file with a zip extension and extract apk
Using Atom or other editor, open up the extracted '''assets/index.android.bundle''
Edit > Go to Line , from stack trace, 424:4194
All white-space is removed from the index.android.bundle and lines are concatenated to a single line. But it identifies the culprit.