DocumentPicker in React-Native not working properly for Android devices - react-native

I have implemented a document picker in my react native application and it is working fine for iOS. However in Android, I am having a weird issue
When I open the document picker and the navigation takes to the file explorer (Downloads section) in Android phone, though I am able to select the pdf file but, when it comes to the application back, it stuck to the page and the file is not there. I have attached the screenshot Same behaviour when the file explorer takes to the recent files. Only when from the recent files, I select the google drive and try to select the pdf from there, it works as expected and I can see the file in my application and the app do not stuck.
Here is what I have written for the pdf document picker
selectPDF = async ()=>{
var imageList = [...this.state.files];
try {
const results = await DocumentPicker.pickMultiple({
type: [DocumentPicker.types.pdf],
});
for (const res of results) {
console.log(
res.uri,
res.type, // mime type
res.name,
res.size
);
const fileName = res.uri.replace("file://","");
let data1 = ''
RnFetchBlob.fs.readStream(
fileName,
'base64',
4095
)
.then((ifstream)=>{
//let data1 = ''
ifstream.open()
ifstream.onData((data)=>{
data1 += data;
})
ifstream.onEnd(() => {
let base64 = data1
imageList.push({
imageName:res.name,
image:base64,
mime:res.type,
size:res.size
})
this.setState({
...this.state,
openCamera:false,
lastFileName:imageList[imageList.length - 1].imageName,
files:imageList
})
})
})
}
} catch (err) {
if (DocumentPicker.isCancel(err)) {
this.closeModal();
} else {
throw err;
}
}
}
Can anyone throw some light as to what I may be missing. Is some configuration needs to be set on device level or any other thing.

you can use something like this,
const [file, setFile] = useState(null);
const selectFile = async () => {
try {
const results = await DocumentPicker.pickMultiple({
type: [DocumentPicker.types.allFiles],
});
setFile(results);
} catch (err) {
if (DocumentPicker.isCancel(err)) {
alert('Canceled');
} else {
alert('Unknown Error: ' + JSON.stringify(err));
throw err;
}
}
};
now you can call file in your function
and to use it you can do like this
<TouchableOpacity
activeOpacity={0.5}
onPress={selectFile}>
<Text>Select File</Text>
</TouchableOpacity>

Related

React Native: How to read and display xml file

How can I display the .xml file to the screen. I can display the pdf file using react-native-pdf but how can I display the text in .XML file or read it.
solution to display the text in .XML file or read it
I'm showing you how can you read any file. If you can read any file, storing that to some state, then rendering is not an issue, I hope so.
Here is how to read a local file in react-native :
var RNFS = require('react-native-fs');
import DocumentPicker from 'react-native-document-picker';
selectFiles = () => {
let that = this;
try {
DocumentPicker.pickMultiple({
type: [DocumentPicker.types.allFiles],
}).then((results) => {
console.log(results[0]);
//that.setState({language: results[0].type});
RNFS.readFile(results[0].uri)
.then((file) => {
that.setState({
code: file
});
})
.catch((error) => console.log('err: ' + error));
//the `code` state holds your xml file, just display it however you want... use 3rd party library for syntax highlight or whatever you want
});
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err;
}
}
};

React Native Linking Promise resolved reject not getting called

I am using react native linking component for opening call application.call suggestion dialog get opened but when I click on cancel it does not return me any promise
static makePhoneCall = (mobileNumber) =>
{
let phoneNumber = '';
if (Platform.OS === 'android') {
let userMobile = `tel:${mobileNumber}`
phoneNumber = userMobile;
}
else {
let userMobile = `tel://${mobileNumber}`
phoneNumber = userMobile;
}
Linking.openURL(phoneNumber).then(() => {
alert('success')
}).catch(() => {
alert('failure')
});
return 'default`
}
classname.makePhoneCall(this.state.item.mobileNumber)
I want to know how to handle openUrl Promise with some example, I have share code of what I have done. I am using react native version 0.59.9
You should check to see if theres an app available to handle the url first.
Linking.canOpenURL(phoneNumber)
.then((supported) => {
if (!supported) {
console.log("Can't handle url: " + url);
} else {
return Linking.openURL(url);
}
})
.catch((err) => console.error('An error occurred', err));

Trouble with saving file onto expo filesystem. I get the uri for the recording but can't seem to get the file after leaving the screen

So my problem is what the title says, and I have been stuck on this problem for over a week now and am at a loss for what I can do. Here's the code
I've tried many different methods but none seem to work, at least with the saving of the file. Please let me know if you need to see more code.
async _stopRecordingAndEnablePlayback() {
this.setState({
isLoadingz: true
});
try {
await this.recording.stopAndUnloadAsync();
} catch (error) {
}
const info = await FileSystem.getInfoAsync(this.recording.getURI());
console.log(
`FILE INFO: ${JSON.stringify(info)}`,
info.uri
);
const arr = [];
const xFileInfo = JSON.stringify(info);
arr.push(xFileInfo);
this.setState({ fileInfo: arr, fileUri: info.uri });
console.log(arr);

play audio file without needing import/require

I'm trying to play and audio file but I'd like to load the file dynamically without having to hardcode the import for each file on my project folder assets/audio.
The code below is working when I use the import, but not when I use the "file".
const Sound = require('react-native-sound');
import t1 from './assets/audio/t1.mp3';
import t2 from './assets/audio/t2.mp3';
Sound.setCategory('Playback', true); // true = mixWithOthers
export const playSound = () => {
const file = './assets/audio/t1.mp3';
// const s = new Sound(file, (error) => { // does not work
const s = new Sound(t1, (error) => { // works
if (error) {
console.log('error', error);
return;
}
s.play(() => {
s.release()
});
});
};
How can I provide the filename during runtime so that I don't need to import every audio file?
You should try to do this:
// Load the sound file 'whoosh.mp3' from the app bundle
// See notes below about preloading sounds within initialization code below.
var whoosh = new Sound('whoosh.mp3', Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// loaded successfully
console.log('duration in seconds: ' + whoosh.getDuration() + 'number of channels: ' + whoosh.getNumberOfChannels());
});
Pass Sound.MAIN_BUNDLE as the second param.

React Native - How to see what's stored in AsyncStorage?

I save some items to AsyncStorage in React Native and I am using chrome debugger and iOS simulator.
Without react native, using regular web development localStorage, I was able to see the stored localStorage items under Chrome Debugger > Resources > Local Storage
Any idea how can I view the React Native AsyncStorage stored items?
React Native Debugger has this built in.
Just call showAsyncStorageContentInDev() in the RND console and you'll be able to see a dump of your app's storage.
You can use reactotron i think it has Async Storage explorer ;)
https://github.com/infinitered/reactotron
Following should work,
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (error, stores) => {
stores.map((result, i, store) => {
console.log({ [store[i][0]]: store[i][1] });
return true;
});
});
});
I have created a helper method to log all Storage in a single object (more clean to log for example in Reactotron):
import AsyncStorage from '#react-native-community/async-storage';
export function logCurrentStorage() {
AsyncStorage.getAllKeys().then((keyArray) => {
AsyncStorage.multiGet(keyArray).then((keyValArray) => {
let myStorage: any = {};
for (let keyVal of keyValArray) {
myStorage[keyVal[0]] = keyVal[1]
}
console.log('CURRENT STORAGE: ', myStorage);
})
});
}
react native debugger
right click on free space
With bluebird you can do this:
const dumpRaw = () => {
return AsyncStorage.getAllKeys().then(keys => {
return Promise.reduce(keys, (result, key) => {
return AsyncStorage.getItem(key).then(value => {
result[key] = value;
return result;
});
}, {});
});
};
dumpRaw().then(data => console.log(data));
Maybe late, but none of these solutions fit for me.
On android, with Android Studio open file explorer then go to data/data/your_package_name
Inside you should have a folder called database and inside a file RKStorage.
This file is a SQLite3 file so get your favorite SQLite explorer and explore. If you want one this one does the job : DB Browser for SQLite
I did not find Reactotron to have any type of pretty printing enabled and it's also brutally latent so I just wrote a simple function using lodash. You could use underscore too.
Assuming you have a static mapping of all your keys...
const keys = {
key1: 'key1',
key2: 'key2'
}
export function printLocalStorage() {
_.forEach(keys, (k, v) => {
localStore.getAllDataForKey(v).then(tree => {
console.log(k) // Logs key above the object
console.log(tree) // Logs a pretty printed JSON object
})
})
}
It's not performant but it solves the problem.
You can Define function to get all keys by using async and await
getAllkeys = () => {
return new Promise( async (resolve, reject) => {
try {
let keys = await AsyncStorage.getAllKeys();
let items = await AsyncStorage.multiGet(keys)
resolve(items)
} catch (error) {
reject(new Error('Error getting items from AsyncStorage: ' + error.message))
}
});
}
somefunc = async () => {
try {
var items = await getAllkeys();
var someItems = items.filter(function (result, i, item) {
// do filtering stuff
return item;
});
// do something with filtered items
} catch (error) {
// do something with your error
}
}
I have a expo snack that shows this and also performs a "load". So it is useful for doing a dump of the contents and storing it to a file and loading it up later.
Here are they parts.
const keys = await AsyncStorage.getAllKeys();
const stores = await AsyncStorage.multiGet(keys);
const data = stores.reduce(
(acc, row) => ({ ...acc, [row[0]]: row[1] }),
{}
);
// data now contains a JSONable Javascript object that contains all the data
This ammends the data in the AsyncStorage from a JSON string.
// sample is a JSON string
const data = JSON.parse(sample);
const keyValuePairs = Object.entries(data)
.map(([key, value]) => [key, value])
.reduce((acc, row) => [...acc, row], []);
await AsyncStorage.multiSet(keyValuePairs);
import AsyncStorage from "#react-native-async-storage/async-storage";
export const printAsyncStorage = () => {
AsyncStorage.getAllKeys((err, keys) => {
AsyncStorage.multiGet(keys, (error, stores) => {
let asyncStorage = {}
stores.map((result, i, store) => {
asyncStorage[store[i][0]] = store[i][1]
});
console.table(asyncStorage)
});
});
};
enter image description here