Closed YaakovDavid closed 5 years ago
You haven't provided code that you are using. It doesn't seem to related with this plugin.
My viewModel looks like this
import { AudioPickerOptions,
FilePickerOptions,
ImagePickerOptions,
Mediafilepicker,
VideoPickerOptions
} from "nativescript-mediafilepicker";
import * as app from "tns-core-modules/application";
import { Observable } from "tns-core-modules/data/observable";
import { SelectedPageService } from "../shared/selected-page-service";
declare const AVCaptureSessionPreset1920x1080;
declare const AVCaptureSessionPresetHigh;
declare const AVCaptureSessionPresetLow;
declare const kUTTypePDF;
declare const kUTTypeText;
export class MediaPickerViewModel extends Observable {
constructor() {
super();
SelectedPageService.getInstance().updateSelectedPage("MediaPicker");
}
/**
* openImagePicker
*/
openImagePicker() {
const options: ImagePickerOptions = {
android: {
isCaptureMood: false,
isNeedCamera: true,
maxNumberFiles: 10,
isNeedFolderList: true
},
ios: {
isCaptureMood: false,
maxNumberFiles: 10
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openImagePicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.dir(results);
if (results) {
results.forEach((result) => {
const file = result.file;
console.log("image file: " + file);
if (result.file && app.ios && !options.ios.isCaptureMood) {
// We can copy the image to app directory for futher proccess.
// This will create a new directory name "filepicker".
// So, after your work you can delete it for reducing memory use.
const fileName = file.replace(/^.*[\/]/, "");
mediafilepicker.copyPHImageToAppDirectory(result.rawData, fileName).then((dirRes: any) => {
console.dir(dirRes);
}).catch((e) => {
console.dir(e);
});
// or can get UIImage to display
mediafilepicker.convertPHImageToUIImage(result.rawData).then((uiRes) => {
console.log(uiRes);
});
} else if (result.file && app.ios) {
// So we have taken image & will get UIImage
// We can copy it to app directory, if need
const fileName = "myTmpImage.jpg";
mediafilepicker.copyUIImageToAppDirectory(result.rawData, fileName).then((dirRes: any) => {
console.dir(dirRes);
}).catch((e) => {
console.dir(e);
});
}
});
}
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* openVideoPicker
*/
openVideoPicker() {
let allowedVideoQualities = [];
if (app.ios) {
allowedVideoQualities = [AVCaptureSessionPreset1920x1080, AVCaptureSessionPresetHigh];
// get more from here:
// https://developer.apple.com/documentation/avfoundation/avcapturesessionpreset?language=objc
}
const options: VideoPickerOptions = {
android: {
isCaptureMood: false,
isNeedCamera: true,
maxNumberFiles: 2,
isNeedFolderList: true,
maxDuration: 20
},
ios: {
isCaptureMood: false
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openVideoPicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.dir(results);
if (results) {
results.forEach((result) => {
console.dir(result);
const file = result.file;
console.log("video file: " + file);
if (result.file && app.ios && !options.ios.isCaptureMood) {
const fileName = file.replace(/^.*[\/]/, "");
setTimeout(() => {
mediafilepicker.copyPHVideoToAppDirectory(result.urlAsset, fileName).then((appRes) => {
console.dir(appRes);
}).catch((e) => {
console.dir(e);
});
}, 1000);
} else if (result.file && app.ios) {
// or we will get our own recorded video :)
console.log(file);
}
});
}
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* audio
*/
openAudioPicker() {
const options: AudioPickerOptions = {
android: {
isCaptureMood: false,
isNeedRecorder: true,
maxNumberFiles: 2,
isNeedFolderList: true,
maxSize: 102400 // Maximum size in bytes
},
ios: {
isCaptureMood: false,
maxNumberFiles: 5,
audioMaximumDuration: 10
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openAudioPicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.dir(results);
if (results) {
results.forEach((result) => {
console.log("audio file: " + result);
if (result.file && app.ios && !options.ios.isCaptureMood) {
// We can copy the audio to app directory for futher proccess.
// This will create a new directory name "filepicker".
// So, after your work you can delete it for reducing memory use.
const fileName = "tmpFile.m4a"; // use .m4a
// copying file will require some time
mediafilepicker.copyMPMediaFileToAPPDirectory(result.rawData, fileName).then((appRes) => {
console.dir(appRes);
}).catch((err) => {
console.dir(err);
});
} else if (result.file && app.ios && options.ios.isCaptureMood) {
// So we have recorded file in APP directory
console.log(result.file);
}
});
}
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* openCustomFiles
*/
openCustomFilesPicker() {
let extensionTypes = [];
extensionTypes = (app.ios)
? [kUTTypePDF, kUTTypeText]
// you can get more types from here:
// https://developer.apple.com/documentation/mobilecoreservices/uttype
: ["txt", "pdf"];
const options: FilePickerOptions = {
android: {
extensions: extensionTypes,
maxNumberFiles: 2
},
ios: {
extensions: extensionTypes,
multipleSelection: true
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openFilePicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.dir(results);
if (results) {
results.forEach((result) => {
console.log("custom file: " + result.file);
});
}
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* imageCapture
*/
imageCapture() {
const options: ImagePickerOptions = {
android: {
isCaptureMood: true
},
ios: {
isCaptureMood: true
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openImagePicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.log("image file:");
console.dir(results);
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* videoCapture
*/
videoCapture() {
let allowedQualities = [];
if (app.ios) {
allowedQualities = [AVCaptureSessionPreset1920x1080, AVCaptureSessionPresetHigh];
// get more from here:
// https://developer.apple.com/documentation/avfoundation/avcapturesessionpreset?language=objc
}
const options: VideoPickerOptions = {
android: {
isCaptureMood: true,
maxDuration: 20,
videoQuality: 1
},
ios: {
isCaptureMood: true,
videoMaximumDuration: 10,
allowedVideoQualities: allowedQualities
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openVideoPicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.log("video capture:");
console.dir(results);
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
/**
* audioCapture
*/
audioCapture() {
const options: AudioPickerOptions = {
android: {
isCaptureMood: true,
maxSize: 102400 // Maximum size of recorded file in bytes. 5900 = ~ 1 second
},
ios: {
isCaptureMood: true,
maxNumberFiles: 5,
audioMaximumDuration: 10
}
};
const mediafilepicker = new Mediafilepicker();
mediafilepicker.openAudioPicker(options);
mediafilepicker.on("getFiles", (res) => {
const results = res.object.get("results");
console.log("audio capture:");
console.dir(results);
});
mediafilepicker.on("error", (res) => {
const msg = res.object.get("msg");
console.log("error: " + msg);
});
mediafilepicker.on("cancel", (res) => {
const msg = res.object.get("msg");
console.log("cancel: " + msg);
});
}
}
My xml
<Page class="page"
navigatingTo="onNavigatingTo"
xmlns:ui="nativescript-mediafilepicker"
xmlns="http://schemas.nativescript.org/tns.xsd">
<ActionBar class="action-bar">
<NavigationButton
android:icon="res://menu"
android:tap="onDrawerButtonTap"
ios:tap="onBackButtonTap">
</NavigationButton>
<ActionItem
ios:icon="res://navigation/menu"
tap="onDrawerButtonTap">
</ActionItem>
<Label class="action-bar-title header-text" text="Media Picker"></Label>
</ActionBar>
<GridLayout id="account-top-gridlayout" rows="auto, *">
<ScrollView row="1" id="message-center-scrollview">
<StackLayout class="message-center-menu-options body-text">
<Label style="text-align:center; margin-bottom: 10; font-size: 24;" text="Picker"></Label>
<Button height="44" tap="{{openImagePicker}}" text="Open ImagePicker"></Button>
<Button height="44" tap="{{openVideoPicker}}" text="Open VideoPicker"></Button>
<Button height="44" tap="{{openAudioPicker}}" text="Open AudioPicker"></Button>
<Button height="44" tap="{{openCustomFilesPicker}}" text="Open CustomFilePicker"></Button>
<Label style="text-align:center; margin-top: 10; font-size: 24;" text="Capture"></Label>
<Button height="44" tap="{{imageCapture}}" text="Take Picture"></Button>
<Button height="44" tap="{{videoCapture}}" text="Record Video"></Button>
<Button height="44" tap="{{audioCapture}}" text="Record Audio"></Button>
</StackLayout>
</ScrollView>
</GridLayout>
</Page>
And my ts
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import * as app from "tns-core-modules/application";
import { EventData, NavigatedData, Page, topmost } from "tns-core-modules/ui/frame";
import { MediaPickerViewModel } from "./media-picker-view-model";
// Event handler for Page 'loaded' event attached in main-page.xml
export function onNavigatingTo(args: NavigatedData) {
if (args.isBackNavigation === false) {
const page = <Page>args.object;
page.bindingContext = new MediaPickerViewModel();
}
}
export function onDrawerButtonTap(args: EventData) {
const sideDrawer = <RadSideDrawer>app.getRootView();
sideDrawer.showDrawer();
}
export function onBackButtonTap() {
topmost().goBack();
}
I can't see any error regarding this plugin. May be someone who have more experience can find the reason. You can try to get support from NativeScript core developer.
Thanks, you are right it wasn't an issue with the plugin or my code!
It just started working for me, for the first time in about three weeks. The only thing I did differently was instead of doing tns run ios
and then bring the code into Xcode and make the build, instead I rantns build ios --release
and then did the build in Xcode and it works now
Thank you for the plugin, it's really good!
Glad to hear that it's working..
Love the plugin! It works great on Android as well as on the ios simulator or on a ios device when I run it directly from Xcode but when I run it from TestFlight on devices the app closes as soon as I go to the page with this plugin.
when I run it on the ios simulator I noticed I get the below printed to the terminal
which makes me believe that the issue is that it's not running on the main thread. I found this StackOverflow post which I think is related to this https://stackoverflow.com/questions/52448204/uiimageview-setimage-crashes-on-background-thread-since-xcode-10
Would someone be able to take a look at the Swift code in this plugin and see if this works? I would do it but I'm not familiar with Swift at all