I am currently using imagepicker on react native. When I use android to pick image it works fine. However when I use iOS it crashes when I choose a photo.
This is the error it shows in xcode debugger:
2020-04-03 11:54:27.802434+0800 app[7218:1993193] -[NSURLResponse allHeaderFields]: unrecognized selector sent to instance 0x28281aba0
2020-04-03 11:54:27.802766+0800 app[7218:1993193] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURLResponse allHeaderFields]: unrecognized selector sent to instance 0x28281aba0'
* First throw call stack:
(0x19d01c164 0x19cd30c1c 0x19cf1a7e0 0x19d02085c 0x19d022b60 0x102b27bc8 0x102b27a90 0x102b01ce0 0x1059f5d10 0x1059f718c 0x1059fe968 0x1059ff580 0x105a0b0f0 0x19cd23714 0x19cd299c8)
libc++abi.dylib: terminating with uncaught exception of type NSException
and this is my code:
chooseImage = async (id) => {
//await this.askPermissionsAsync();
let options = {
title: 'Select Image',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response.error);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else {
const source = { uri: response.uri };
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
// alert(JSON.stringify(response));
let file_data = [...this.state.fileData];
file_data[id] = response.data;
let file_uri = [...this.state.fileUri];
file_uri[id] = response.uri;
this.setState({filePath:response, fileData: file_data, fileUri: file_uri});
}
});
}
I have also added the permissions in info.plist:
<key>NSCameraUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string></string>
<key>NSDocumentsFolderUsageDescription</key>
<string></string>
but the problem still persist in ios.
The issue was
'data:image/jpeg;base64,' + this.state.fileData[id]
while rendering it on Image tag.
This issue is indicated here:
YellowBox Crash
Image Crash with data:image/png;base64
The solution I did was to add "noData: true" on option and access directly the URI file location in the image tag.
Hope this helps
react-native link did not link the library, so the mage picker lib did not build with the app. Thats why I as getting null pointer exception because there was no lib.
Or else manually add the library.
<key>NSCameraUsageDescription</key>
<string>Access to take a photo by camera</string>
<key>NSAppleMusicUsageDescription</key>
<string>Access to pick a photo</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access to pick a photo</string>
Related
So I am trying to lauch the image library with a package called react-native-image-picker:
function launchLibrary(fun) {
let options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.launchImageLibrary(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
alert(response.customButton);
} else {
const source = { uri: response.uri };
console.log(source);
console.log('response', JSON.stringify(response));
fun(response);
}
});
};
Then when the function gets executed, I get the following response:
response {"errorMessage":"Activity error","errorCode":"others"}
What went wrong here?
The Google Play store no longer accepts builds targeting SDK < 30 so I managed to get it working with a different work around.
I updated react-native-image-picker to version "^4.7.0" and the error went away, but note that launchImageLibrary response may now contain an array of "assets" with image data, rather than including the image data right within the response object.
After updating, replacing response.uri with response.assets[0].uri did the trick for me.
I changed compileSdkVersion and targetSdkVersion from 30 to the 29 in
build.gradle , depending on that answer:
https://github.com/react-native-image-picker/react-native-image-picker/issues/1600
compileSdkVersion = 29
targetSdkVersion = 29
and it worked normally after that.
I have uploaded a pdf file successfully to drive using a node server. However, I can not find a way to convert it to the google doc format so that it can be downloaded later as a docx document.
here is my actual code:
const fileMetadata = {
'name': 'new file.pdf',
//'mimeType': 'application/vnd.google-apps.document'
// trying to create it as a google doc directly does
// not work either
};
const media = {
mimeType: 'application/pdf',
body: fs.createReadStream(pdf)
};
drive.files.create({
resource: fileMetadata,
media,
fields: 'id'
}, (err, createdFile) => {
if (err) {
console.error(err);
} else {
// ------- COPY AS GOOGLE DOC
drive.files.copy({
fileId: createdFile.data.id,
requestBody:{
mimeType:'application/vnd.google-apps.document'
}
}, (err, googleDocFiles) => {
if (err) {
console.log(err)
// GaxiosError: Bad Request
// error: [
// { domain: 'global', reason: 'badRequest', message: 'Bad Request' } ]
} else {
console.log(googleDocFiles)
}
})
}});
What i have tried
using the files.upload method with the same requestBody returns a 200 response, however the pdf is unchanged
I know is possible, I did it before, using the copy method however now it not working and I have no clue why *sigh
EDIT
The mimeType in the request body is responsible for the 400 error, that is very weird since I am following the steps in the documentation here:
Import to Google Docs types section
this section is explicit about importing a CSV, however in the box under that section says that I can convert a pdf to doc using the corresponding mime type
I re-installed the package and it work
I am trying to create a Audio/Video Calling app using React Native. There's a screen in the app where calling happens using WebRTC. Let's call it 'Call' screen. TO show calling notification I am using the package react-native-callkeep. Once a user picks up the call, I'm taking him directly to the 'Call' screen. Everything works fine except when I'm trying to take the user to the 'Call' screen.
Here's how I'm doing it:
Inside my AppDelegate.m I have this
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
{
return [RNCallKeep application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
Inside the index.js, I'm calling initCalling before registering the app like this:
...
initCalling();
AppRegistry.registerComponent(appName, () => App);
And Here's what initCalling does
const initCalling = () => {
const options = {
ios: {
appName: 'MyApp',
includesCallsInRecents: false,
imageName: 'notification_icon',
supportsVideo: true,
},
android: {
alertTitle: 'Permissions required',
alertDescription: 'This application needs to access your Calling Service',
cancelButton: 'Cancel',
okButton: 'ok',
imageName: 'notification_icon',
}
};
RNCallKeep.setup(options);
function checkCallNotification(message) {
if (!message.data.callType) {
return;
}
const { threadId, messageKey } = message.data;
RNCallKeep.displayIncomingCall(
message.data.channelId,
message.data.title,
message.data.title,
'number',
message.data.callType === 'video',
);
RNCallKeep.addEventListener('answerCall', async () => {
RNCallKeep.removeEventListener('endCall');
RNCallKeep.endAllCalls();
Linking.openURL(message.data.deeplink);
RNCallKeep.removeEventListener('answerCall');
});
RNCallKeep.addEventListener('endCall', () => {
RNCallKeep.endAllCalls();
RNCallKeep.removeEventListener('endCall');
});
}
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
checkCallNotification(remoteMessage);
});
messaging().onMessage(async (remoteMessage) => {
checkCallNotification(remoteMessage);
});
}
When a notification arrives, the call keep starts showing the call screen. Once user picks up the call, Im trying to take him to the 'Call' screen but instead I'm getting this
index.bundle?platfor…&minify=false:41712 Possible Unhandled Promise Rejection (id: 0):
Error: Unable to open URL: myapp://call
Error: Unable to open URL: myapp://call
on debugging I can see the line Linking.openURL(message.data.deeplink); is failing even though the url is correct. And this is happening only in iOS. On Android things are working perfect. Can someone please help me know what I'm doing wrong ? Thanks !
I am building an app with React Native, for Android and iOS. I am trying to let the user download a PDF file when clicking on a button.
react-native-file-download does not support Android
react-native-fs does nothing when I trigger downloadFile (nothing shows up on the notification bar), and I am not able to find the file after that. I added android.permission.WRITE_EXTERNAL_STORAGE to the Android Manifest file. I double-checked that the file I am trying to download exists (when it does not, the library throws an error)
I do not find other solutions for this problem. I have found libraries for viewing a PDF, but I would like to let the user download the PDF.
Just implemented the download feature an hour ago :p
Follow these steps:
a) npm install rn-fetch-blob
b) follow the installation instructions.
b2) if you want to manually install the package without using rnpm, go to their wiki.
c) Finally, that's how I made it possible to download files within my app:
const { config, fs } = RNFetchBlob
let PictureDir = fs.dirs.PictureDir // this is the pictures directory. You can check the available directories in the wiki.
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : true, // setting it to true will use the device's native download manager and will be shown in the notification bar.
notification : false,
path: PictureDir + "/me_"+Math.floor(date.getTime() + date.getSeconds() / 2), // this is the path where your downloaded file will live in
description : 'Downloading image.'
}
}
config(options).fetch('GET', "http://www.example.com/example.pdf").then((res) => {
// do some magic here
})
If you're using Expo, react-native-fetch-blob won't work. Use FileSystem.
Here's a working example:
const { uri: localUri } = await FileSystem.downloadAsync(remoteUri, FileSystem.documentDirectory + 'name.ext');
Now you have localUri with the path to the downloaded file. Feel free to set your own filename instead of name.ext.
I Followed the solution from Jonathan Simonney, above on this post. But I had to change it a little:
const { config, fs } = RNFetchBlob;
const date = new Date();
const { DownloadDir } = fs.dirs; // You can check the available directories in the wiki.
const options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true, // true will use native manager and be shown on notification bar.
notification: true,
path: `${DownloadDir}/me_${Math.floor(date.getTime() + date.getSeconds() / 2)}.pdf`,
description: 'Downloading.',
},
};
config(options).fetch('GET', 'http://www.africau.edu/images/default/sample.pdf').then((res) => {
console.log('do some magic in here');
});
GetItem_downloadbtn = (item, itemname) => {
console.log("fiel url comiugn jdd " + item);
console.log("item name checkoing " + itemname);
const android = RNFetchBlob.android;
const filename = itemname;
const filepath = RNFetchBlob.fs.dirs.DownloadDir + '/foldernamae/' + filename;
const downloadAppUrl = item;
RNFetchBlob.config({
addAndroidDownloads: {
useDownloadManager: true,
title: 'great, download success',
description:'an apk that will be download',
mime: 'application/vnd.android.package-archive',
// mime: 'image/jpeg',
// mediaScannable: true,
notification: true,
path: filepath
}
})
.fetch('GET', downloadAppUrl)
.then((res) => {
// console.log('res.path ', res.path());
alert('res.path ', res.path());
android.actionViewIntent(res.path(), 'application/vnd.android.package-archive');
})
.catch((err) => {
alert('download error, err is', JSON.stringify(err));
});
}
I had the same issue, got it working using Expo WebBrowser Module
// install module
npm install react-native-webview
// import the module
import * as WebBrowser from 'expo-web-browser';
// then in your function you can call this function
await WebBrowser.openBrowserAsync(file_ur);
it will open preview of the file and then user can download using share button.
We use FileOpener2 plugin for cordova to open a downloaded .apk file from our servers. Recently, we found that Android 6.0 or higher devices are throwing an exception only on the file open process. We were able to trace this down to the cordova.js file, where the posted exception occurs. We have yet to find a cause or a fix, but have put a workaround in place. Any info would be amazing on this so we can maintain our in-app self updating process going on all Android devices.
Code (Working on Android <= 6.0):
// we need to access LocalFileSystem
window.requestFileSystem(LocalFileSystem.PERSISTENT, 5 * 1024 * 1024, function (fs) {
//Show user that download is occurring
$("#toast").dxToast({
message: "Downloading please wait..",
type: "warning",
visible: true,
displayTime: 20000
});
// we will save file in .. Download/OURAPPNAME.apk
var filePath = cordova.file.externalRootDirectory + '/Download/' + "OURAPPNAME.apk";
var fileTransfer = new FileTransfer();
var uri = encodeURI(appDownloadURL);
fileTransfer.download(uri, filePath, function (entry) {
//Show user that download is occurring/show user install is about to happen
$("#toast").dxToast({
message: "Download complete! Launching...",
type: "success",
visible: true,
displayTime: 2000
});
////Use pwlin's fileOpener2 plugin to let the system open the .apk
cordova.plugins.fileOpener2.open(
entry.toURL(),
'application/vnd.android.package-archive',
{
error: function (e) {
window.open(appDownloadURL, "_system");
},
success: function () { console.log('file opened successfully'); }
}
);
},
function (error) {
//Show user that download had an error
$("#toast").dxToast({
message: error.message,
type: "error",
displayTime: 5000
});
},
false);
})
Debugging Information:
THIS IS NOT OUR CODE, BUT APACHE/CORDOVA CODE
Problem File: cordova.js
function androidExec(success, fail, service, action, args) {
// argsJson - "["file:///storage/emulated/0/download/OURAPPNAME.apk","application/vnd.android.package-archive"]"
//callbackId - FileOpener21362683899
//action - open
//service FileOpener2
//bridgesecret - 1334209170
// msgs = "230 F09 FileOpener21362683899 sAttempt to invoke virtual method 'android.content.res.XmlResourceParser //android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference"
var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
// If argsJson was received by Java as null, try again with the PROMPT bridge mode.
// This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "#Null arguments.") {
androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
androidExec(success, fail, service, action, args);
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
} else if (msgs) {
messagesFromNative.push(msgs);
// Always process async to avoid exceptions messing up stack.
nextTick(processMessages);
}