React Native Share save image option not working in iOS - android

I'm trying to save a base64 encoded image in iOS using react-native-share and also Share module from React Native. But both fail when trying the Save Image option.
React Native Share
try {
const sharedResponse = await Share.open({ url: dataUri });
console.log(sharedRes);
} catch (error) {
console.log(error);
}
Share Module
try {
const sharedResponse = await Share.share({ url: dataUri });
console.log(sharedRes);
} catch (error) {
console.log(error);
}
Options other than Save image such as copy, and save to files are working fine.
I have added the following in Info.plist as well
<key>NSPhotoLibraryAddUsageDescription</key>
<string>APP wants to save to photos</string>
This is working fine on the first try in the app's lifetime (When it's asking the permissions from the user). After that this functionality doesn't work.

For some reason you need to write the file to the temp directory first before sharing. I'm not sure the reasoning behind this... but it did fix the issue for me.
const filename = `snapshot.jpeg`; // or some other way to generate filename
const filepath = `${FileSystem.cacheDirectory}/${filename}`;
await FileSystem.writeAsStringAsync(filepath, res.data, { encoding: 'base64' });
const isSharingAvailable = await isAvailableAsync();
if (!isSharingAvailable) {
showAlert('Error', 'Sharing is not available.')
return;
}
if (Platform.OS === 'ios') {
//sharing just the file allows for more applications to be shared too. Adding a message seems to remove many apps from the sharing list
await Share.share({ url: filepath });
}

This strange behaviour had happened because I'm trying to open the Share pop-up above a React Native Modal. The issue didn't occur if I try to hide the Modal before the Share pop-up comes up.

I resolved the issue when storing the image locally before opening the Share Modal.
To store the image i used the npm package 'react-native-fs' and then use it just like this:
import RNFS from "react-native-fs";
function storeFileLocally(url: string): Promise<string> {
const localFile = `${RNFS.DocumentDirectoryPath}/tempFile.jpeg`;
const options: RNFS.DownloadFileOptions = {
fromUrl: url,
toFile: localFile
};
return RNFS.copyFile(url, localFile)
.then(() => 'file://'+localFile)
.catch((error) => {
console.error(error);
return null;
});
}

Related

react-native-share instagram story doesn't work on Android [React Native]

I'm using react-native-share to share content on instagram stories.
On iOS, it works fine; however, on Android, it does not resolve the promise and does not display any error.
import { default as RNShare } from "react-native-share";
const shareOnInstagram = async (callback) => {
const imageUrl =
"https://images.unsplash.com/photo-1556035511-3168381ea4d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1674&q=80";
/* Download image using expo-file-system */
const base64 = await downloadImage({ url: imageUrl, isBase64: true });
const shareOptions = {
backgroundImage: imageUrl,
stickerImage: "data:image/png;base64," + base64,
backgroundBottomColor: "#fefefe",
backgroundTopColor: "#906df4",
social: RNShare.Social.INSTAGRAM_STORIES,
appId: META_API_KEY,
};
RNShare.shareSingle(shareOptions).catch((err) => {
console.log(err);
});
callback();
};
Here's the specs:
"react-native": "^0.70.6"
"react-native-share": "^8.0.1"
I think the problem in your Image format https://images.unsplash.com/photo-1556035511-3168381ea4d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1674&q=80 - if you check it is image/avif but from android documentation https://developers.facebook.com/docs/instagram/sharing-to-stories/ you can find that it should be MEDIA_TYPE_JPEG. Try to use JPEG as a workaround and if it works probably you need to convert avif to jpeg for Android version

PDFMake: Unable to save pdf file on android device

Unable to save pdf file on android which is created using PDFMake library.
In my ionic app, I am not able to download pdf which I created using PDFMake library even it log success. Here I am trying to writeFile using file module, when user click on generatePdf button
Since last two days I am trying to achieve this.. but no luck, so now I am looking for some help here.
component.html
<ion-button (click)="generatePdf()">generatePdf</ion-button>
component.ts
generatePdf() {
let self = this;
const pdfData = {
content: [
'First paragraph',
'Another paragraph',
],
};
let pdfDocGenerator = pdfMake.createPdf(pdfData);
pdfDocGenerator.getBuffer((buffer) => {
let utf8 = new Uint8Array(buffer);
let binaryArray = utf8.buffer;
self.saveToDevice(binaryArray, 'first.pdf');
});
}
saveToDevice(data: any, savefile: any) {
let self = this;
self.file.writeFile(self.file.externalApplicationStorageDirectory, savefile, data, { replace: false
})
.then(() => {
console.log('success...');
})
.catch((err) => {
console.log('error...');
});
}

Launch local pdf file with external pdf viewer using react-native and expo

I'm new to react-native. I have a sample pdf file on my mobile storage and tried to launch in an external pdf viewer using IntentLauncher.startActivityAsync. It launches the external app but doesn't open the file. Here is my code,
IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
data: FileUri,
flags: 1,
type: "application/pdf",
});
This is my file-url: '/storage/emulated/0/MyFolder/sample-file.pdf'.
I think the data (key) may be wrong. How can I fix it?
Without any other way, now I am using React Native CLI to overcome the issue.
react-native-file-viewer fulfilled my need. And here is my code,
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
FileViewer.open(path, {showOpenWithDialog: true})
.then(() => {
// something useful here
})
.catch((err) => {
console.log('err: ', err);
});
} else {
console.log('Permission denied');
}
And this is my path: 'file:///storage/emulated/0/Download/test.pdf'

how to use print attribute react-native-share

I am using the react-native-share extension for the share and print Pdf document. I am trying to add The 'Print' attribute but it is not working or I couldn't get it right
I follow this document https://react-native-community.github.io/react-native-share/docs/share-open#activitytype
and i used the example here https://react-native-community.github.io/react-native-share/docs/share-open#activityitemsources-ios-only
According to this document, I created an object like
const url = this.props.navigation.state.params.document.url
{
item:{
print : url
}
},
https://react-native-community.github.io/react-native-share/docs/share-remote-file
The code below solves my problem for IOS. I think there was a problem because the document came from the url.Its still not working for android
static sharePDFWithAndroid(fileUrl, type) {
let filePath = null;
let file_url_length = fileUrl.length;
const configOptions = { fileCache: true };
RNFetchBlob.config(configOptions)
.fetch('GET', fileUrl)
.then(resp => {
filePath = resp.path();
return resp.readFile('base64');
})
.then(async base64Data => {
base64Data = `data:${type};base64,` + base64Data;
await Share.open({ url: base64Data });
// remove the image or pdf from device's storage
await RNFS.unlink(filePath);
});
}

Share images and files on react-native using Expo

I've saved the file i want to share locally using FileSystem.downloadAsync
Share.share works fine for iOS. How can I share an image I have saved locally on Android?
I've tried
https://github.com/lucasferreira/react-native-send-intent
https://github.com/react-native-community/react-native-share
Both these solutions do not seem to work with Expo.
I'm using react-native version : https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz
FileSystem.downloadAsync(url, FileSystem.documentDirectory+filename).then(({uri})=>{
if(Platform.OS == "android"){
// ???
}
else{
Share.share({url:uri});
}
})
Is there something i'm missing?
Since SDK33, you can use Expo Sharing to share any type of file to other apps that can handle its file type even if you're on Android.
See : https://docs.expo.io/versions/latest/sdk/sharing/
Usage is pretty simple :
import * as Sharing from 'expo-sharing'; // Import the library
Sharing.shareAsync(url) // And share your file !
In order for users to share content saved within our (Expo) app, we structured it like this. (This is working across iOS & Android).
IMPORT SHARING:
import * as FileSystem from 'expo-file-system';
import * as Sharing from 'expo-sharing';
ADD ONPRESS TO BUTTON (OR WHEREVER):
<Button
name="share"
onPress={() =>
openShareDialogAsync(media, {
video: media.meta.fileType === 'video',
})
}
/>
SHARE VIDEO OR IMAGE TO ANY APP IN USERS HANDSET
const openShareDialogAsync = async (mediaProp, options) => {
const fileDetails = {
extension: options.video ? '.mp4' : '.jpg',
shareOptions: {
mimeType: options.video ? 'video/mp4' : 'image/jpeg',
dialosTitle: options.video
? 'Check out this video!'
: 'Check out this image!',
UTI: options.video ? 'video/mp4' : 'image/jpeg',
},
};
const downloadPath = `${FileSystem.cacheDirectory}${mediaProp.media_id}${fileDetails.extension}`;
const { uri: localUrl } = await FileSystem.downloadAsync(
mediaProp.url,
downloadPath
);
if (!(await Sharing.isAvailableAsync())) {
showMessage({
message: 'Sharing is not available',
description: 'Your device does not allow sharing',
type: 'danger',
});
return;
}
await Sharing.shareAsync(localUrl, fileDetails.shareOptions);
};
Hope this helps :]

Categories

Resources