iOS screenshot with cordova is not in the photos library - ios

I'm using the cordova screenshot plugin : https://github.com/gitawego/cordova-screenshot to take a screenshot in my iPhone using this code :
navigator.screenshot.save(function (error, res) {
if (error) {
console.log('Screenshot error');
console.error(error);
} else {
console.log('screenshot ok', res.filePath);
}
}, 'jpg', 50, 'project-X-result');
It seems to work (i have no error) but I can't find the screenshot in the Photos Library. Is it possible to save it in this library?
How should I do? Using another plugin to move the file? (where should it be moved exactly?) Editing the plugin to save it directly in the library? (where should it be saved exactly?)

I just ran through the same problem. It took several days but I figured out how to do it.
It does involve another plugin Canvas2Image plugin. I didn't think it would work, but I was desperate and it did work in the end. Here's how I did it.
If you are getting the console.log for screenshot ok, then you are in good shape. The next thing you will need to do is install Canvas2Image with your CLI like so:
cordova plugin add https://github.com/devgeeks/Canvas2ImagePlugin.git
(or replace 'cordova' with 'phonegap' if you use that instead.)
Next, you will need to add a function (in this case saveImageToPhone()) that calls the plugin you just added to your project. This function will be called from your navigator.screenshot.save() function you already have. We will add that function call to your screenshot.save success block, right after the console.log line.
The key here is using that filePath property that we get back in the success block; That's our absolute path to the image we just saved to the temp folder in iOS. We will simply pass that path to the second function and let it do its work.
Here's those two functions from my code:
function saveScreen(){
navigator.screenshot.save(function(error,res){
if(error){
console.error(error);
}else{
console.log('ok',res.filePath);
var MEsuccess = function(msg){
console.info(msg);
} ;
var MEerror = function(err){
console.error(err);
};
saveImageToPhone(res.filePath, MEsuccess, MEerror);
}
},'jpg',90);
}
function saveImageToPhone(url, success, error) {
var canvas, context, imageDataUrl, imageData;
var img = new Image();
img.onload = function() {
canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
try {
imageDataUrl = canvas.toDataURL('image/jpeg', 1.0);
imageData = imageDataUrl.replace(/data:image\/jpeg;base64,/, '');
cordova.exec(
success,
error,
'Canvas2ImagePlugin',
'saveImageDataToLibrary',
[imageData]
);
}
catch(e) {
error(e.message);
}
};
try {
img.src = url;
}
catch(e) {
error(e.message);
}
}
Now just call the first function from wherever you wish.
If it works, you'll get a console.log right after your filePath readout that says
IMAGE SAVED!
Be careful, you might overwrite the same screenshot if you use a name as a screenshot.save parameter (after your jpg and quality parameters). My app needs to save different screenshots and have them all available later; by removing the name parameter and allowing the OS to name the file I was able to achieve just that.
I hope that helps you out, I know it caused me a lot of trouble...

Related

Trouble reading user accessible files

I am using nativescript-mediafilepicker as means of choosing a file, and this can read external storage successfully (I have downloaded a PDF to the 'downloads' folder on iOS and I am able to pick it.) I then try to load the file using the file system module from nativescript library, and this fails because it is listed as NativeScript encountered a fatal error: Uncaught Error: You can’t save the file “com.xxxxxx” because the volume is read only. This doesn't make sense as I am trying to read anyway - I don't understand where the saving part is from. The error comes from fileSystemModule.File.fromPath() line.
Something to note that file['file'] is file:///Users/adair/Library/Developer/CoreSimulator/Devices/82F397CE-B0B3-4ADD-AD52-805265C7AC49/data/Containers/Data/Application/7B47A8BD-6DBA-42CF-8792-38A8C5E61174/tmp/com.xxxxxx/test.pdf
Is the file automatically being pulled to an application specific directory after this media picker?
getFiles() {
let extensions = [];
if (app.ios) {
extensions = [kUTTypePDF]; // you can get more types from here: https://developer.apple.com/documentation/mobilecoreservices/uttype
} else {
extensions = ["pdf"];
}
const mediaFilePicker = new Mediafilepicker();
const filePickerOptions = {
android: {
extensions,
maxNumberFiles: 1,
},
ios: {
extensions,
maxNumberFiles: 1,
},
};
masterPermissions
.requestPermissions([masterPermissions.PERMISSIONS.READ_EXTERNAL_STORAGE,masterPermissions.PERMISSIONS.WRITE_EXTERNAL_STORAGE])
.then((fulfilled) => {
console.log(fulfilled);
mediaFilePicker.openFilePicker(filePickerOptions);
mediaFilePicker.on("getFiles", function (res) {
let results = res.object.get("results");
let file = results[0];
console.dir(file);
let fileObject = fileSystemModule.File.fromPath(file["file"]);
console.log(fileObject);
});
mediaFilePicker.on("error", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
mediaFilePicker.on("cancel", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
})
.catch((e) => {
console.log(e);
});
},
The issue I have experienced is resultant of the expectation of File.fromPath and what is returned by the file picker. File picker is returning a "file://path" URI, and File.fromPath is expecting a string of just "path".
Simply using the following instead is enough.
let fileObject = fileSystemModule.File.fromPath(file["file"].replace("file://","");

Random image from folder

How can I make possible that the app will load all of the images from the specific folder and then put in array and choose one image randomly? When chose one then pass to the fronted to show the image. How to do that too?
I am C# developer but not long time ago I found ElectronJS and this framework does everything easier so therefore I am moving to this framework.
I did in C# programming this way:
// basic settings.
var ext = new List<string> { ".jpg", ".gif", ".png" };
// we use same directory where program is.
string targetDirectory = Directory.GetCurrentDirectory() + "\\assets\\" + "images\\" + "animals\\";
// Here we create our list of files
// New list
// Use GetFiles to getfilenames
// Filter unwanted stuff away (like our program)
if (Directory.Exists(targetDirectory))
{
Files = new List<string>
(Directory.GetFiles(targetDirectory, "*.*", SearchOption.TopDirectoryOnly)
.Where(s => ext.Any(es => s.EndsWith(es))));
// Show first picture so we dont need wait 3 secs.
ChangePicture();
}
else
{
panel5.BackgroundImage = new Bitmap(Resources.doggy);
}
I don't know how to do in ElectronJS.
Thank you in advance the answers.
Alright. I found the solution.
However I don't understand the people who are giving negative reputation for the opened question. If they are giving negative reputation then they could explain why.
Well anyway, I did fix this issue with this way:
I created images.js file and added this:
var fs = require('fs');
function getRandImage() {
var files = fs.readdirSync('./assets/images/animals/')
/* now files is an Array of the name of the files in the folder and you can pick a random name inside of that array */
let chosenFile = files[Math.floor(Math.random() * files.length)]
console.log('../assets/images/animals/' + chosenFile);
return '../assets/images/animals/' + chosenFile;
}
module.exports = { getRandImage }
I used console to see if the value is correct, otherwise others can delete that part.
Sending the data to the renderer process:
const { getRandImage } = require('./images');
child.webContents.send('random-image', getRandImage());
I did put in the preload.js file the following (I used the starter pack electronjs github to start with something):
var { ipcRenderer } = require('electron');
ipcRenderer.on('random-image', function (event, store) {
document.getElementById("randompic").src = store;
console.log(store);
});
Same here, I did use console.log just for test the value is correct and I used to change the randompic ID related image src html to the randomly chosen image.
Hopefully I did helping those people who are newbie as me.

React-native, how to get file-asset image absolute path?

I'm doing some image manipulation on ios on react-native.
The problem is one of the libraries I'm using only supports absolute paths, but I only have the file-asset uri.
Example
I have:
assets-library://asset/asset.HEIC?id=CE542E92-B1FF-42DC-BD89-D61BB70EB4BF&ext=HEIC
I need:
file:///Users/USERNAME/Library/Developer/CoreSimulator/Devices/########-####-####-####-############/data/Containers/Data/Application/########-####-####-####-############/Documents/########-####-####-####-############.jpg
Is there any way to easily get the image absolute path?
This is what I ended up doing, based on #ospfranco's answer.
I saved a copy of the asset on the temp folder. Also included a little snippet to generate a random string for the file name.
import RNFS from 'react-native-fs';
getAssetFileAbsolutePath = async (assetPath) => {
const dest = `${RNFS.TemporaryDirectoryPath}${Math.random().toString(36).substring(7)}.jpg`;
try {
let absolutePath = await RNFS.copyAssetsFileIOS(assetPath, dest, 0, 0);
console.log(absolutePath)
} catch(err) {
console.log(err)
}
}
So, the reason why you only get an url is because it image might not be stored on the device (it could be on iCloud). iOS silently downloads the asset for you once you do any operation on it.
That will not help you if you are really trying to manipulate the image from your react-native code though, so here is one workaround:
import RNFS from 'react-native-fs';
getAssetFileAbsolutePath = async (assetPath) => {
const dest = `${RNFS.TemporaryDirectoryPath}${Math.random().toString(36).substring(7)}.jpg`;
try {
let absolutePath = await RNFS.copyAssetsFileIOS(assetPath, dest, 0, 0);
} catch(err) {
// ...
}
}
Bare in mind this copies the file to a temporary directory which means it is not permanent, you can also copy it to your application's document directory.
I got it to work using RNFS, but I had to add a little 'extra' to the uri path to get it to work.
<TouchableHighlight
onPress={async () => {
const destPath = RNFS.CachesDirectoryPath + '/MyPic.jpg';
try {
await RNFS.copyAssetsFileIOS(imageUri, destPath, 0, 0);
console.log('destPath', destPath);
} catch (error) {
console.log(error);
}
navigation.navigate('SelectedPicture', {
uri: 'file://' + destPath,
});
}}>
<Image source={{uri: imageUri}} style={styles.image} />
</TouchableHighlight>
The question is old but i answer it to help people like me, new in react-native, having the same issue.
i were struggling with it trying to get the images from the cameraroll and process them with an OCR library. I was using react-native-photo-framework to get the images and i found that you can get fileurl using the method getImageMetadata with the assets. I need this fileurl because the original URI that has the format 'photo://...' wasn't being recognized as a valid URL for the OCR Library. I haven´t tested it with real devices and with iCloud assets yet. Example:
const statusObj = await RNPhotosFramework.requestAuthorization()
if (statusObj.isAuthorized) {
const assetList = await RNPhotosFramework.getAssets({
includeMetadata: true,
includeResourcesMetadata: true,
fetchOptions: {
mediaTypes: ['image'],
sourceTypes: ['userLibrary', 'cloudShared', 'itunesSynced'],
}
})
const asset = photos.assets[0]
const metadata = await asset.getImageMetadata()
const uri = metadata.imageMetadata.fileUrl
}

How to take screen shot from a layout in ionic/cordova/phonegap?

I'm trying to build a cordova based application using ionic.
In my application , there is a section which users can select images from our server and move them or do some actions on it(like zoom & rotate ...). At the end I want them to be able to share the result on our website and social medias. My problem is that how can I take a screen shot from the layout which they build it? I've already seen html2canvas library , but it has a problem with out source images that are saved on our server and does not take screen shot of them.
Install the following plugin to your project
cordova plugin add https://github.com/gitawego/cordova-screenshot.git
Add this service to your angular module
.service('$cordovaScreenshot', ['$q', function($q) {
return {
capture: function(filename, extension, quality) {
extension = extension || 'jpg';
quality = quality || '100';
var defer = $q.defer();
navigator.screenshot.save(function(error, res) {
if (error) {
console.error(error);
defer.reject(error);
} else {
console.log('screenshot saved in: ', res.filePath);
defer.resolve(res.filePath);
}
}, extension, quality, filename);
return defer.promise;
}
};
}]);
Than, you can simply add a button to take a screen shot with this service.
I have a nice example here for taking a screenshot and share it on Facebook:
//Take a picture
$cordovaScreenshot.capture()
.then(function(result) {
//on success you get the image url
//post on facebook (image & link can be null)
$cordovaSocialSharing
.shareViaFacebook("Text to post here...", result, "Link to share")
.then(function(result) {
//do something on post success or ignore it...
}, function(err) {
console.log("there was an error sharing!");
});
}, function(err) {
console.log("there was an error taking a a screenshot!");
});
Please note that this example uses the social sharing plugin by ngCordova:
http://ngcordova.com/docs/plugins/socialSharing/
file Screenshot.js to:
var formats = ['png','jpg'];
function Screenshot() {
}
Screenshot.prototype.save = function (callback,format,quality, filename) {
format = (format || 'png').toLowerCase();
filename = filename || 'screenshot_'+Math.round((+(new Date()) + Math.random()));
if(formats.indexOf(format) === -1){
return callback && callback(new Error('invalid format '+format));
}
quality = typeof(quality) !== 'number'?100:quality;
cordova.exec(function(res){
callback && callback(null,res);
}, function(error){
callback && callback(error);
}, "Screenshot", "saveScreenshot", [format, quality, filename]);
};
Screenshot.install = function () {
if (!window.plugins) {
window.plugins = {};
}
window.plugins.screenshot = new Screenshot();
return window.plugins.screenshot;
};
cordova.addConstructor(Screenshot.install);
This way I can make the call with the following code:
window.plugins.screenshot.save(function(error,res){
if(error){
alert(error);
}else{
alert('ok',res.filePath); //should be path/to/myScreenshot.jpg
}
},'jpg',50,'myScreenShot');
This worked perfectly on my Android smartphone.
I also added in res / xml / config.xml file:
<feature name="Screenshot">
<param name="android-package" value="org.apache.cordova.screenshot.Screenshot"/>
</feature>
In the AndroidManifest.xml file:
And added the java class in the following package: org.apache.cordova.screenshot.Screenshot
All these configurations have the information in the plugin.xml file of the plugin
The easiest way is to use this plugin:
com.darktalker.cordova.screenshot

How to download picture with Phonegap Filetransfer to image gallery in iOS

This has been asked several times, but most of these questions are unanswered
I'm downloading a file like below, and it seems to work fine. However .. it does not show up in the iOS, ehm, gallery. That is, in the 'photos' application.
var fileTransfer = new FileTransfer();
var encurl = encodeURI(url);
var filename = url.split('/').slice(-1)[0];
var filepath = "foo/"+filename;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
var syspath = fileSystem.root.toURL() + '/' + filepath;
var fileTransfer = new FileTransfer();
fileTransfer.download(
encurl,
syspath,
function (entry) {
foo.debug("Download success "+syspath);
},
function (error) {
foo.error("Download failed with error "+error.code+' '+syspath);
}
);
}, function (evt) {
foo.error("Filesystem failed with error "+evt.target.error.code);
});
and the result is
[Log] Download success file:///var/mobile/Applications/68DE0AD9-FBD2-4D82-92C0-2B7634B218D5/Documents//foo/20141030-153810-editor.jpg (console-via-logger.js, line 173)
hurray. now, how do you open the download, using just your fingers, on ios ?
I would mark this as a duplicate of Phonegap - Save image from url into device photo gallery
I was happy with the answer by M165437 and my comments. That answered my question.
Try to download by using https://www.npmjs.com/package/com-cordova-image-save-to-gallery plugin. It will download a picture from a given URL and save it to IOS Photo Gallery.
Cordova plugin add https://github.com/valwinjose007/cordova-image-save-to-gallery.git
How to use:
declare var CordovaImageSaveToGallery: any;
CordovaImageSaveToGallery.downloadFromUrl('https://picsum.photos/200/300',(res)=>{
//download success
},(err)=>{
//error on download
});

Resources