I'm currently using the nativescript-mediafilepicker to upload files. I want the user to pick files regardless of the file extension but the only file shwon by the application is a jpg file. What seems to be the problem here?
public openCustomFilesPicker() {
let extensions = [];
if (Application.ios) {
extensions = [kUTTypePDF, kUTTypeText];
} else {
extensions = ["txt", "pdf", "jpg"];
}
let options: FilePickerOptions = {
android: {
extensions: extensions,
maxNumberFiles: 2,
},
ios: {
extensions: extensions,
multipleSelection: true,
hostView: this._hostView,
},
};
let mediafilepicker = new Mediafilepicker();
mediafilepicker.openFilePicker(options);
mediafilepicker.on("getFiles", function (res) {
let results = res.object.get("results");
console.dir(results);
if (results) {
for (let i = 0; i < results.length; i++) {
let result = results[i];
console.log(result.file);
}
}
});
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);
});
}
Related
I am using Flutter in VSCode with Android Emulator. I've encountered a problem where FilePicker won't show any pictures where it should. I am new in this area and I am following a tutorial - for him everything works normally but for me no. Can someone please help me?
utils.dart
Future<List<File>>pickImages() async {
List<File> images = [];
try{
var files = await FilePicker.platform.pickFiles(
type: FileType.any,
allowMultiple: true,
);
if (files != null && files.files.isNotEmpty) {
for(int i = 0; i < files.files.length; i++){
images.add(File(files.files[i].path!));
}
}
} catch(e) {
debugPrint(e.toString());
}
return images;
}
add_product_screen.dart
void selectImages() async {
var res = await pickImages();
setState(() {
images = res;
});
}
Further in Scaffold I am just calling selectImages with onTap.
I am using UIImagePickerController to record short (<30s) videos which are then saved and uploaded via our API. The app is cross-platform and so I need recorded videos to be encoded into mp4 format so that Android devices can play them.
I used instructions from the following questions to create my solution:
Swift - How to record video in MP4 format with UIImagePickerController?
AVFoundation record video in MP4 format
https://forums.developer.apple.com/thread/94762
I record my video through the UIImagePickerController like so:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// Local variable inserted by Swift 4.2 migrator.
let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)
let videoNSURL = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.mediaURL)] as? NSURL
videoURL = videoNSURL!.absoluteURL
if let videoURL = videoURL {
let avAsset = AVURLAsset(url: videoURL, options: nil)
avAsset.exportVideo { (exportedURL) in
if let uploadVC = self.uploadVC {
uploadVC.incomingFileURL = exportedURL
uploadVC.myJewelleryID = self.myJewelleryID
uploadVC.topicID = self.topicID
}
DispatchQueue.main.async { [weak self] in
//Update UI with results from previous closure
self?.dismiss(animated: true, completion: nil)
self?.showUploadContainer()
self?.updateVideoContainerWithURL(url: exportedURL)
}
}
}
}
This then passes the exported MP4 url to the upload container view, where it saves the file to the device:
private func saveVideoFileToDevice() {
//Filename Struct = [AssetID]_[TopicID]_[CustomerID]_[Datestamp]
let date = Date()
let formater = DateFormatter()
formater.locale = Locale(identifier: "en_US_POSIX")
formater.dateFormat = "YYYY-MM-dd-HH-mm-ss"
uploadFileName = ""
if let mjID = myJewelleryID {
uploadFileName = "ASID_\(mjID)_\(User.instance.customerID)_\(formater.string(from: date)).mp4"
} else if let tID = topicID {
uploadFileName = "ASID_\(tID)_\(User.instance.customerID)_\(formater.string(from: date)).mp4"
}
let fileManager = FileManager.default
if let destURL = URL(string: "file://\(NSHomeDirectory())/Documents/\(uploadFileName!)") {
var fileData: Data!
print("destURL = \(destURL)")
do {
try fileManager.copyItem(at: incomingFileURL! as URL, to: destURL)
fileData = try Data(contentsOf: incomingFileURL! as URL)
try fileData.write(to: destURL)
}
catch {
print("DEBUG: Failed to save video data")
}
}
}
and then uploads the file to our API. Although the file is MP4, it does not play on Android. On inspection, the file looks very similar to a file that will actually play on an Android device when we compare the codec data:
Does anyone have any ideas on how I can fix this?
Thanks!
var exportSession: AVAssetExportSession!
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let videoURL = (info[UIImagePickerController.InfoKey.mediaURL] as? URL) else { return }
encodeVideo(videoURL)
}
func encodeVideo(_ videoURL: URL) {
let avAsset = AVURLAsset(url: videoURL, options: nil)
//Create Export session
exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("rendered-Video.mp4")
deleteFile(filePath)
exportSession!.outputURL = filePath
exportSession!.outputFileType = AVFileType.mp4
exportSession!.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: avAsset.duration)
exportSession.timeRange = range
exportSession!.exportAsynchronously(completionHandler: {() -> Void in
DispatchQueue.main.async {
Utility.stopActivityIndicator()
switch self.exportSession!.status {
case .failed:
self.view.makeToast(self.exportSession?.error?.localizedDescription ?? "")
case .cancelled:
self.view.makeToast("Export canceled")
case .completed:
if let url = self.exportSession.outputURL {
//Rendered Video URL
}
default:
break
}
}
})
}
Delete File function:
func deleteFile(_ filePath: URL) {
guard FileManager.default.fileExists(atPath: filePath.path) else {
return
}
do {
try FileManager.default.removeItem(atPath: filePath.path)
} catch {
fatalError("Unable to delete file: \(error) : \(#function).")
}
}
Don't forget to import AVFoundation
Hope that will help!
//MARK:- Convert iPhoneVideo(.mov) to mp4
extension AVURLAsset
{
func exportVideo(presetName: String = AVAssetExportPresetHighestQuality, outputFileType: AVFileType = .mp4, fileExtension: String = "mp4", then completion: #escaping (URL?) -> Void)
{
let filename = url.deletingPathExtension().appendingPathExtension(fileExtension).lastPathComponent
let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)
if let session = AVAssetExportSession(asset: self, presetName: presetName) {
session.outputURL = outputURL
session.outputFileType = outputFileType
let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 0)
let range = CMTimeRangeMake(start: start, duration: duration)
session.timeRange = range
session.shouldOptimizeForNetworkUse = true
session.exportAsynchronously {
switch session.status {
case .completed:
completion(outputURL)
case .cancelled:
debugPrint("Video export cancelled.")
completion(nil)
case .failed:
let errorMessage = session.error?.localizedDescription ?? "n/a"
debugPrint("Video export failed with error: \(errorMessage)")
completion(nil)
default:
break
}
}
} else {
completion(nil)
}
}
}
//MARK:- ImagePicker delegate methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
{
if let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
let avAsset = AVURLAsset(url: url, options: nil)
avAsset.exportVideo(presetName: AVAssetExportPresetHighestQuality, outputFileType: AVFileType.mp4, fileExtension: "mp4") { (mp4Url) in
print("Mp4 converted url : \(String(describing: mp4Url))")
self.videoPath = mp4Url//videoURL//
}
}
}
My issue is very similar to this question Cordova - Reading Large Image corrupts image
but I haven't had any success with the solution. I'm also attempting to use the image picker plugin for Cordova
Cordova 7.0.1
Android 6.2.3
SapUI5 1.44.17
fileToBase64: function(fileUrl, callback) {
window.resolveLocalFileSystemURL(fileUrl, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onload = function(evt) {
callback(evt.target.result);
};
reader.readAsDataURL(file);
}, function(error) {
console.log("File entry error " + error);
});
}, function(error) {
console.log("Resolve system file error " + error);
});
},
The result returned is an incomplete base64 string. Here's the loop through my images
handleImagePicker: function(oEvent) {
var _this = this;
window.imagePicker.getPictures(
function(results) {
var numOfImagesLeftToProcess = results.length;
if(numOfImagesLeftToProcess)
_this.appBusy(true);
for (var i = 0; i < results.length; i++) {
_this.fileToBase64(results[i], function(base64Str) {
console.log(base64Str);
numOfImagesLeftToProcess--;
if(numOfImagesLeftToProcess == 0) {
_this.appBusy(false);
}
});
}
}, function (error) {
console.log('Error: ' + error);
},
{
//outputType: imagePicker.OutputType.BASE64_STRING // default .FILE_URI
}
);
},
Not sure if the callback is being called prematurely. I'm able to view the images fine on the device and I've tested this code on two different devices with two different version of Android.
Any help would be appreciated.
I have implemented the following CardIO plugin in my Ionic App:
https://github.com/card-io/card.io-Cordova-Plugin
This works fine on iOS. However, on Android, when I use the keyboard option in the Camera Screen to manually type in the card details, it first loads the correct screen momentarily, and then jumps back to the first screen (Sign Up screen in this case) of the app. While debugging the app flow, I saw that the callback for Card IO is working fine, but there seems to be an issue when Ionic handles the event.
Any help greatly appreciated!
Following is the code in my controller:
$scope.$on('$ionicView.beforeEnter', function()
{
$scope.creditCardScanning();
}
$scope.creditCardScanning = function(){
var cardIOResponseFields = [
"cardType",
"redactedCardNumber",
"cardNumber",
"expiryMonth",
"expiryYear",
"cvv",
"postalCode"
];
var onCardIOComplete = function(response) {
for (var i = 0; i < cardIOResponseFields.length; i++) {
var field = cardIOResponseFields[i];
}
var cardName = response[cardIOResponseFields[0]].toUpperCase();
for (i = 0; i < $scope.cardtype.length; i++) {
var cardTypeDict = $scope.cardtype[i];
if(cardTypeDict.card_type_name === cardName){
document.getElementById('cardtype').selectedIndex = i;
$scope.params.card_type = cardName;
break;
}
}
document.getElementById('cardNumber').value = response[cardIOResponseFields[2]];
$scope.params.card_number = response[cardIOResponseFields[2]];
var expMonthVal = response[cardIOResponseFields[3]];
for(i=0;i < $scope.expmonth.length; i++) {
var expMonthDict = $scope.expmonth[i];
if(expMonthDict.value === expMonthVal){
document.getElementById('expmonth').selectedIndex = i;
$scope.params.expiration_month = expMonthDict.value;
break;
}
}
for (i = 0; i < $scope.expyear.length; i++) {
var expYearDict = $scope.expyear[i];
if(expYearDict.value === response[cardIOResponseFields[4]]){
document.getElementById('expyear').selectedIndex = i;
$scope.params.expiration_year = response[cardIOResponseFields[4]];
break;
}
}
document.getElementById('cvv').value = response[cardIOResponseFields[5]];
$scope.params.security_code = response[cardIOResponseFields[5]];
};
var onCardIOCancel = function() {
console.log("card.io scan cancelled");
};
var onCardIOCheck = function (canScan) {
console.log("card.io canScan? " + canScan);
var scanBtn = document.getElementById("scanBtn");
if (!canScan) {
console.log("Cannot scan card");
}
scanBtn.onclick = function (e) {
CardIO.scan({
"requireExpiry": true,
"requireCVV": true,
"requirePostalCode": false,
"shows_first_use_alert": true,
"disable_manual_entry_buttons": false
},
onCardIOComplete,
onCardIOCancel
);
}
};
CardIO.canScan(onCardIOCheck);
}
And in my view, I am calling the function to load the next page, once the card details are successfully entered and the "Next" Button is tapped.
I want to traverse through each file in the SD card inside all the directories and sub directories using the FILE API of phonegap (which is the w3c file api actually). I have to perform a certain set of operations on these files by looking at their nature. I donot want to search for specific types of files, but traverse through each file in a sequential manner.
Can someone please help me with this? Just a basic loop framework with the necessary requirements for the traversal would be a great help.
Thank You in advance.
I think the following code should work:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onRequestFileSystem, fail);
function onRequestFileSystem(fileSystem) {
var directoryReader = fileSystem.root.createReader();
directoryReader.readEntries(onReadEntries, fail);
}
function onReadEntries(entries) {
var i;
for (i = 0; i < entries.length; i++) {
if (entries[i].isFile == true) {
// ...
}
if (entries[i].isDirectory == true) {
var directoryReader = entries[i].fullPath.createReader();
directoryReader.readEntries(onReadEntries, fail);
}
}
}
http://www.c-sharpcorner.com/UploadFile/e83792/filesystem-directoryentry-objects-in-phonegap/
scan : function(url,fileType,callback)
{
var fileTypeCollection = [];
var defer = $q.defer();
url.forEach(function(element, index)
{
//requestLocalFileSystemURL
log(element);
window.resolveLocalFileSystemURL(element,onRequestFileSystem, fail);
log("Ends resolve");
});
function onRequestFileSystem(fileSystem)
{
var directoryReader = fileSystem.createReader();
directoryReader.readEntries(onReadEntries,fail);
} /*onRequestFile Ends*/
function onReadEntries(entries)
{
if(entries.length==0)
{
log("Entries Length....Resolving");
defer.resolve(fileTypeCollection);
}
else
{
entries.forEach( function(element, index)
{
if (element.isDirectory === true)
{
// Recursive -- call back into this subdirectory
onRequestFileSystem(element);
}
if(element.isFile == true)
{
fileType.forEach(function(type)
{
if(element.name.indexOf(type) != -1)
{
fileTypeCollection.push(element);
}
});
} /*is File ENds*/
}); /*Entries For Each Ends*/
}
} /*OnRead Ends*/
function fail(resp)
{
log(resp);
defer.reject();
} /*Fail Ends*/
return defer.promise;
} //Scan Function Ends
try this. remove the promises if u wish and use a callback.promises is kind of broken. if you can fix then its ok else use a callback after push for FileType