Is it possible to programmatically take a screenshot of the current phone view while the react-native app is in the background? The expo api for takeSnapshotAsync requires a view ref to work. I do not want to capture the actual app itself. I want to capture whatever the user is doing on their phone.
I believe this one should be able to do what you want: https://github.com/gre/react-native-view-shot
import RNViewShot from "react-native-view-shot";
RNViewShot.takeSnapshot(viewRef, {
format: "jpeg",
quality: 0.8
})
.then(
uri => console.log("Image saved to", uri),
error => console.error("Oops, snapshot failed", error)
);
Try to call RNViewShot in setInterval maybe it will work even when the app is minimalized. If RNViewShot will not work then you will have to create your own native ios module.
Related
I have a Flutter app that can view mp4 files from a URL. (Using a video controller playing directly from the URL.) I want the user to be able to share them if they wish. As best I can tell the file has to actually exist on the device so I have broken down the steps for now into download file, invoke share.
I'm using this guide: https://retroportalstudio.medium.com/saving-files-to-application-folder-and-gallery-in-flutter-e9be2ebee92a
I need to work on ios and android. The problem is that on ios neither the filename I get from the dio downloader nor the ImageGallerySaver seem to "work" when passed to the system ShareSheet.
I'm using the flutter extensions dio, share_plus, cross_file, image_gallery_saver as I've seen recommended in various places.
File saveFile = File(directory.path + "/$fileName");
developer.log("starting download...");
await dio.download(url, saveFile.path,
onReceiveProgress: (value1, value2) {
developer.log("got progress " + value1.toString());
setState(() {
downloadProgress = value1 / value2;
});
});
_permaFile = saveFile.path;
if (Platform.isIOS) {
var galleryResult = await ImageGallerySaver.saveFile(saveFile.path,
isReturnPathOfIOS: true);
developer.log("gallery save result = " + galleryResult.toString());
_permaFile = galleryResult['filePath'];
}
After getting a directory we use dio to download the file, do some log chirping, and then save the name to an object member called _permaFile.
Then the share button triggers:
void _shareAction() async {
final box = context.findRenderObject() as RenderBox?;
final files = <XFile>[];
if (_permaFile == null) {
return;
}
developer.log("sharing file: " + _permaFile.toString());
files.add(XFile(_permaFile!));
await Share.shareXFiles(files,
text: "Event",
// subject: "Subject for Event",
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
}
This works on android device... after I download I hit share, and I can share the video to a third-party app like WhatsApp.
On ios the ShareSheet is invoked but when I share I only get the text "Event", not the video file that goes along with it.
Note that I have tried both results... setting the _permaFile to be what comes back from ImageGallerySaver but also just using what the dio downloader gives back.
Note also that the ImageGallerySaver seems to work: the video really does land and is there in the ios video lib. If I go into the Photos app I can share from there to WhatsApp and have the video get sent.
In each case I get errors like this:
[ShareSheet] error fetching item for URL:file:/var/mobile/Media/DCIM/100APPLE/IMG_0021.MP4 -- file:/// : (null)
[ShareSheet] error fetching file provider domain for URL:file:/var/mobile/Media/DCIM/100APPLE/IMG_0021.MP4 -- file:/// : (null)
[ShareSheet] error loading metadata for
documentURL:file:/var/mobile/Media/DCIM/100APPLE/IMG_0021.MP4 --
file:/// error:Error Domain=NSFileProviderInternalErrorDomain Code=0
"No valid file provider found from URL
file:/var/mobile/Media/DCIM/100APPLE/IMG_0021.MP4 -- file:///."
UserInfo={NSLocalizedDescription=No valid file provider found from URL
file:/var/mobile/Media/DCIM/100APPLE/IMG_0021.MP4 -- file:///.}
In order to test this further I built the share_plus demo app:
https://github.com/fluttercommunity/plus_plugins/tree/main/packages/share_plus/share_plus
I modified it to share videos to see what was different. The share plus example (sp_example) works for sharing videos that have been selected by the picker.
For this reason I think the problem is something I'm missing about ios video filenames/formats and possibly a built-in conversion step that happens.
Here are what the filenames look like that I see in my app:
dio download result:
file:///var/mobile/Containers/Data/Application/223BF2B9-DDF0-490E-932F-09D5F03B98B3/Library/Caches/test.mp4
ImageGallerySaver result:
file:///var/mobile/Media/DCIM/100APPLE/IMG_0019.MP4
This is what video filenames look like when they are picked and shared in sp_example:
/private/var/mobile/Containers/Data/Application/E5CB4D7C-6CDF-4AA2-8134-C4322ED7C886/tmp/trim.E6633D68-44E3-4853-A29E-A71AC95A0913.MOV
Note that it has been converted to MOV extension and the user gets trim step right in the picker that results in trim in the name.
For my purposes I don't want to go through the picker, the user is on the screen showing the video and they shouldnt have to repick, so where do I get the post-conversion ios filename that references what I just saved?
I am currently working on an ionic app for iOS and I am facing a problem.
I want to make a call via a SIP client. The thing is iOS doesn't let me choose which app to use for the call, it just uses the native dialer.
My question is: is there any way to make iOS ask me which app to choose?
The code I currently use is:
window.open('tel:' + nr);
I also tried:
window.open('tel:' + nr, '_system');
You can use Call Number native plugin.
Installation :
ionic cordova plugin add call-number
npm install #ionic-native/call-number
Usage :
import { CallNumber } from '#ionic-native/call-number/ngx';
constructor(private callNumber: CallNumber) { }
...
this.callNumber.callNumber("18001010101", false) // Set to false to allow user to choose app
.then(res => console.log('Launched dialer!', res))
.catch(err => console.log('Error launching dialer', err));
callNumber() takes two parameters :
number: String; phone number to call (e.g. "1234567890")
bypassAppChooser: boolean; true if you always wish to bypass the app chooser if user has multiple applications installed that can handle calls
I'm building a cross platform app using Ionic 3.19.1,
On Android everything runs fine, but when i build the app for IOS and then run it on a device using Xcode i get some unexpected behaviour:
Expected:
1) Clicking on a button, the dialer should open and make a call
2) Clicking on a button, the camera should open
Actual:
None of those actions happen until the app gets into background, for example when opening the notifications bar or the tools bar on the bottom.
CODE:
This is the code used for making a phone call, using #ionic-native/call-number
this.callNumber.callNumber("+123456789", true)
.then(() => this.navCtrl.setRoot(CompletedPage))
.catch((error) => console.log(error));
This is the code used to open the camera, using #ionic-native/camera
const options: CameraOptions = {
quality: 60,
targetHeight: 600,
targetWidth: 600,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
}
The code and cordova plugins are correctly set up and working fine, the only problem is that they don't get executed until some event occurs on the page (i guess focus event or something related),
i'm not getting errors for the call-number, but i'm getting a warning for the camera:
Attempt to present <CDVCameraPicker: 0x17a84e00> on <MainViewController: 0x176345a0> whose view is not in the window hierarchy!
I looked around for that message but i couldn't fine nothing related to ionic.
Any kind of help or just link to resources will be appreciated!
I'm developing a App with Ionic 2 and I'm have problems with #ionic-native/Camera. I've this code on Upload.ts
let loader = this.loading.create({
content: 'Carregando video....'
});
loader.present().then(() => {
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
mediaType: this.camera.MediaType.VIDEO,
}
this.camera.getPicture(options).then((videoData) => {
this.uploadForm.controls['file'].setValue(videoData)
loader.dismiss();
}, (err) => {
console.log(err);
});
});
This code works fine in Android, but when I run ionic cordova run ios -lc, the promise this.camera.getPicture(options) is never resolved, so the loader keep running forever.
Thanks in advance!
So, I found the problem. First thing is that native components bugs with -l (--livereload). I don't know how to explain why but I got this information from the Ionic Worldwide slack. A member from Ionic Team said:
"live-reload on a device can cause issues with plugins and file system".
So I used this video to understand how to debbug the APP using the iOS emulator and Safari.
https://www.youtube.com/watch?v=Aob749bkoLY
A little brief of the video: when using iOS emulator, you can access the menu Developer > Emulator > <App Name>. A new window with inspector tools will open and logs from the emulator will appear on this window.
I found out that's the video url was incorrect. Before, to be compatible with Android, I've this code responsible to find the video pointer in system and send to the server:
filePath = 'file:///' + this.uploadForm.controls['file'].value;
But, iOS File Picker already has a "file:///" prefix. So prefixing it again made it wrong. So I updated the code to be like this:
if (this.platform.is('android')) {
filePath = 'file:///' + this.uploadForm.controls['file'].value;
} else {
filePath = this.uploadForm.controls['file'].value;
}
This resolved the problem.
I need to catch sound volume button press inside my react-native application. Couldn't find anything in docs.
You can use react-native-system-setting package with addVolumeListener listener. Something like this
componentDidMount() {
// listen the volume changing
this.volumeListener = SystemSetting.addVolumeListener(data => {
// your action here
});
}
You could create a native module as per FuzzyTree's comment however if you want something that's ready out of the box you could use https://github.com/IFours/react-native-volume-slider and make it hidden. The onValueChange callback is called upon the iOS device volume controls being changed.
Another idea could be to look into the aforementioned module and just take out what you need to form a new module and publish it for the benefit of everyone.