I'm new in Xamarin development.
I build my app, where user can clicks on DOWNLOAD button.
This button download video from the server and save to Photo library.
Here is how I implement this (maybe its incorrect way??)
public bool SaveVideo(byte[] videoData, int id)
{
try
{
CreateCustomAlbum();
// Save file to applicaiton folder
string local_path = SaveFileToApplicationFolder(videoData);
_lib.WriteVideoToSavedPhotosAlbum(new Foundation.NSUrl(local_path), (t, u) =>
{
DeleteLocalFile(local_path); // HERE I DELETE FILE FOR NOT INCREASE SIZE OF APPLICATION
_local_file_path = t.AbsoluteUrl.ToString(); // global variable
_lib.Enumerate(ALAssetsGroupType.Album, HandleALAssetsLibraryGroupsEnumerationResultsDelegate, (obj) => { });
});
return true;
}
catch (Exception ex)
{
return false;
}
}
void DeleteLocalFile(string local_path)
{
try
{
if (File.Exists(local_path))
{
File.Delete(local_path);
if (!File.Exists(local_path))
{
Console.WriteLine("Deleted");
}
}
}
catch (Exception ex)
{
}
}
string SaveFileToApplicationFolder(byte[] videoData)
{
try
{
string file_path = String.Empty;
var doc = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filename = "MY-APP-" + id + ".mp4"; // id global variable
file_path = Path.Combine(doc, filename); // global variable
File.WriteAllBytes(file_path, videoData);
return file_path;
}
catch (Exception ex)
{
return String.Empty;
}
}
void HandleALAssetsLibraryGroupsEnumerationResultsDelegate(ALAssetsGroup group, ref bool stop)
{
try
{
if (group == null)
{
stop = true;
return;
}
if (group.Name == "MY-APP-ALBUM-NAME")
{
stop = true;
_current_album = group;
SaveFileToCustomAlbum();
}
}
catch (Exception ex)
{
}
}
void SaveFileToCustomAlbum()
{
try
{
if (_current_album != null && !String.IsNullOrEmpty(_local_file_path))
{
_lib.AssetForUrl(new Foundation.NSUrl(_local_file_path), delegate (ALAsset asset)
{
if (asset != null)
{
_current_album.AddAsset(asset);
}
else
{
Console.WriteLine("ASSET == NULL.");
}
}, delegate (NSError assetError)
{
Console.WriteLine(assetError.ToString());
});
}
}
catch (Exception ex)
{
}
}
So this code do:
1) Save video to local folder my video - Method SaveFileToApplicationFolder
2) Then Save video file to Photo library - Method SaveVideo
3) Then Delete file from app folder (in purpose not increase application folder size (app size) --- IF ITS CORRECT logic??
4) Then put assets to Custom Album for my App
SO everything here works well for me......BUT!
I need overtime when user open item - check if he already has video for this item in photos library or not?
And here I'm stack....i just don't understand how i can to check if user has specific video?? I don't find hot to set NAME for ASSETS and hot looking for assets by name...so don't know hot to find this assets....METADATA?? Key_VALUE of object??
Refer to Obj-C Check if image already exists in Photos gallery
In short:
Store assetUrl when saving video with NSUserDefaults
Check if the video exists in Photo library with assetUrl when next time to open it .
You may just want to use xam.plugin.media nuget package. It makes it very easy to take and store videos as well as access the default video picker for selecting existing videos
Related
So, I am trying to save an image file from the camera then upload it to firebase. Unfortunately, the firebase storage plugin has some errors and doesn't return errors in the catch so I need to check wifi connection before i do so, just in case i need to cache the image and upload it later. Once the image file has uploaded i then create some JSON and send that to firebase database where the app pulls down relevant information.
Note: sometimes this code works and the image is not empty, othertimes the image comesback empty so im guessing its a timing issue?
Future saveImageFile(UploadImage image) async {
await storage.init();
var imageFile = storage.saveImageFile(image.file, image.getName());
instance.setInt("ImageCount", imageCount + 1);
checkConnectionThenUploadImage(imageFile);
}
//From storage class
File saveImageFile(File toBeSaved, String fileName) {
final filePath = '$imageDirectory$fileName';
var file = new File(filePath)
..createSync(recursive: true)
..writeAsBytes(toBeSaved.readAsBytesSync());
return file;
}
checkConnectionThenUploadImage(File image) {
checkConnectivity().then((isConnected) async {
if (!isConnected) {
instance.setBool("hasImagesToUpload", true);
} else {
await saveImageToStorage(image);
}
}).catchError((error) {
print("Error getting connectivity status, was error: $error");
});
}
saveImageToStorage(File imageFile) async {
final fileName = getNameFromFile(imageFile);
final StorageReference ref = FirebaseStorage.instance.ref().child("AllUsers").child(uuid).child(fileName);
final StorageUploadTask uploadTask = ref.putFile(imageFile, const StorageMetadata(contentLanguage: "en"));
final url = (await uploadTask.future).downloadUrl;
if (url != null) { //Normally you could catch an error here but the plugin has a bug so it needs to be checked in other ways
final fireImage = new FireImage(getNameFromFile(imageFile), storage.getDateFromFileName(fileName), imageCount, "", url.toString());
saveImageJsonToDatabase(fireImage);
storage.deleteImageFile(fileName);
} else {
checkConnectionThenUploadImage(imageFile);
}
}
saveImageJsonToDatabase(FireImage image) async {
await storage.init();
storage.saveJsonFile(image);
checkConnectivity().then((isConnected) {
if (!isConnected) {
instance.setBool("hasJsonToUpload", true);
} else {
final DatabaseReference dataBaseReference = FirebaseDatabase.instance.reference().child("AllUsers").child(uuid);
dataBaseReference.child("images").push().set(image.toJson()).whenComplete (() {
storage.deleteJsonFile(basename(image.name));
}).catchError((error) { //catching errors works with firebase database
saveImageJsonToDatabase(image);
});
}
});
}
//From storage class
deleteImageFile(String fileName) async {
final filePath = '$imageDirectory$fileName';
File(filePath).delete();
}
The image gets uploaded and the json is created but when i try to view the image using the download url from firebase storage it says the image is empty. The only clue i have is that this is a timing issue because it only happens occasionally.
Can anyone see where im going wrong?
I've been following various answers to various questions on the subject and I've come to a result and some code which looks like it works. I'm getting stuck with the NSURL part of it. I've got 2 mp3 tracks in the assets folder of my iOS gluon project. I've made the IOSAudioService Class to handle the playback. and I'm passing an argument from the play button in the view to the Play() method. Everything other than the actual file is registering as working. I'm getting an NSError, which from looking at the code is a nil value, so either the argument isn't passing correctly or it can't find the file. Code below.
public AVAudioPlayer backgroundMusic;
private double currentPosition;
NSURL songURL = null;
#Override
public void Play(String filename){
songURL = new NSURL(filename);
try {
if (backgroundMusic != null) {
Resume();
}
else {
//Start the audio at the beginning.
currentPosition = 0;
backgroundMusic = new AVAudioPlayer(songURL);
//create the mendia player and assign it to the audio
backgroundMusic.prepareToPlay();
backgroundMusic.play();}
//catch the audio error
} catch(NSErrorException e) {
System.out.println("error: " + e);
}
}
#Override
public void Stop() {
backgroundMusic.stop();
backgroundMusic = null;
}
#Override
public void Pause() {
currentPosition = backgroundMusic.getCurrentTime();
backgroundMusic.pause();
}
#Override
public void Resume() {
backgroundMusic.setCurrentTime(currentPosition);
backgroundMusic.play();
}
try {
services = (AudioService) Class.forName("com.gluonhq.charm.down.plugins.ios.IOSAudioService").newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
System.out.println("Error " + ex);
}
I'm getting the error at the catch block for NSExceptionError e.
if (services != null) {
final HBox hBox = new HBox(10,
MaterialDesignIcon.PLAY_ARROW.button(e -> services.Play("/audio.mp3")),
MaterialDesignIcon.PAUSE.button(e -> {
if (!pause) {
services.Pause();
pause = true;
} else {
services.Resume();
pause = false;
}
}),
MaterialDesignIcon.STOP.button(e -> services.Stop()));
//set the HBox alignment
hBox.setAlignment(Pos.CENTER);
hBox.getStyleClass().add("hbox");
//create and set up a vbox to include the image, audio controls and the text then set the alignment
final VBox vBox = new VBox(5, Image(), hBox, text1);
vBox.setAlignment(Pos.CENTER);
setCenter(new StackPane(vBox));
} else {
//start an error if service is null
setCenter(new StackPane(new Label("Only for Android")));
}
Services.get(LifecycleService.class).ifPresent(s -> s.addListener(LifecycleEvent.PAUSE, () -> services.Stop()));
}
I've also follow the advice on creating the service factory class and the interface from Audio performance with Javafx for Android (MediaPlayer and NativeAudioService) taking out the add audio element and I'm intending to do this on a view by view basis if possible.
Problem solved after must fiddling and looking in the Javadocs.Solved by adding/replacing some code with the below.
songURL = new NSURL("file:///" + NSBundle.getMainBundle().findResourcePath(filename, "mp3"));
try {
songURL.checkResourceIsReachable();}
catch(NSErrorException d) {
System.out.println("Song not found!" + d);
}
I am using using DropZone JS with MVC. The ActionMethod that saves the images is using a try catch. Now what would I need to return from the ActionMethod in case of an error so the front end will pick that up and show the error mark to the user instead of showing everything went successful.
Is it built in with DropZone or do I need to bind it to event such as complete? If so, how?
An example of the DropZone JS complete event
this.on("complete", function (file, response) {
// If an error has occurred, mark the item as failed
if (response.code != 200){
}
// If it went through successful, show that to the user
if (response.code == 200){
}
});
If this would work, in MVC I could just return HttStatusCodeResult such as
return new HttpStatusCodeResult(HttpStatusCode.BadRequest) and return new HttpStatusCodeResult(HttpStatusCode.Ok)
UPDATED - ActionMethod
[HttpPost]
public ActionResult SaveImages()
{
bool isSavedSuccessfully = true;
string fName = "";
try
{
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
if (HttpPostedFileBaseExtensions.IsImage(file))
{
//Save file content goes here
fName = file.FileName;
if (file != null && file.ContentLength > 0)
{
var originalDirectory = new DirectoryInfo(string.Format("{0}Images\\", Server.MapPath(#"\")));
string pathString = Path.Combine(originalDirectory.ToString(), "Temp");
var fileName1 = Path.GetFileName(file.FileName);
bool isExists = Directory.Exists(pathString);
if (!isExists)
Directory.CreateDirectory(pathString);
var path = string.Format("{0}\\{1}", pathString, file.FileName);
file.SaveAs(path);
_testRepository.EditMainPicture("test", pathString, "imageText", 1);
}
}
}
}
catch (Exception ex)
{
// TODO Add error logging!!
isSavedSuccessfully = false;
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
return new HttpStatusCodeResult(HttpStatusCode.Ok);
}
For some reason if anything else fails within this method, DropZone will not pick it up and it will mark as the file has been successfully uploaded. I want it to show an error if anything fails within the ActionMethod
You'll need to listen for the error event
An error occured. Receives the errorMessage as second parameter and if the error was due to the XMLHttpRequest the xhr object as third.
Example
dropzone.on("error", function(file, errorMesage, xhr) { ... });
I tried to listen file change event in BlackBerry base on FileExplorer example, but whenever I added or deleted file, it always showed "Deferring persistence as device is being used" and I can't catch anything .Here is my code:
public class FileChangeListenner implements FileSystemJournalListener{
private long _lastUSN; // = 0;
public void fileJournalChanged() {
long nextUSN = FileSystemJournal.getNextUSN();
String msg = null;
for (long lookUSN = nextUSN - 1; lookUSN >= _lastUSN && msg == null; --lookUSN)
{
FileSystemJournalEntry entry = FileSystemJournal.getEntry(lookUSN);
// We didn't find an entry
if (entry == null)
{
break;
}
// Check if this entry was added or deleted
String path = entry.getPath();
if (path != null)
{
switch (entry.getEvent())
{
case FileSystemJournalEntry.FILE_ADDED:
msg = "File was added.";
break;
case FileSystemJournalEntry.FILE_DELETED:
msg = "File was deleted.";
break;
}
}
}
_lastUSN = nextUSN;
if ( msg != null )
{
System.out.println(msg);
}
}
}
Here is the caller:
Thread t = new Thread(new Runnable() {
public void run() {
new FileChangeListenner();
try {
Thread.sleep(5000);
createFile();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
Create file method worked fine:
private void createFile() {
try {
FileConnection fc = (FileConnection) Connector
.open("file:///SDCard/newfile.txt");
// If no exception is thrown, then the URI is valid, but the file
// may or may not exist.
if (!fc.exists()) {
fc.create(); // create the file if it doesn't exist
}
OutputStream outStream = fc.openOutputStream();
outStream.write("test content".getBytes());
outStream.close();
fc.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
and output:
0:00:44.475: Deferring persistence as device is being used.
0:00:46.475: AG,+CPT
0:00:46.477: AG,-CPT
0:00:54.476: VM:+GC(f)w=11
0:00:54.551: VM:-GCt=9,b=1,r=0,g=f,w=11,m=0
0:00:54.553: VM:QUOT t=1
0:00:54.554: VM:+CR
0:00:54.596: VM:-CR t=5
0:00:55.476: AM: Exit net_rim_bb_datatags(291)
0:00:55.478: Process net_rim_bb_datatags(291) cleanup started
0:00:55.479: VM:EVTOv=7680,w=20
0:00:55.480: Process net_rim_bb_datatags(291) cleanup done
0:00:55.481: 06/25 03:40:41.165 BBM FutureTask Execute: net.rim.device.apps.internal.qm.bbm.platform.BBMPlatformManagerImpl$3#d1e1ec79
0:00:55.487: 06/25 03:40:41.171 BBM FutureTask Finish : net.rim.device.apps.internal.qm.bbm.platform.BBMPlatformManagerImpl$3#d1e1ec79
I also tried to remove the thread or create or delete file in simulator 's sdcard directly but it doesn't help. Please tell me where is my problem. Thanks
You instantiate the FileChangeListenner, but you never register it, and also don't keep it as a variable anywhere. You probably need to add this call
FileChangeListenner listener = new FileChangeListenner();
UiApplication.getUiApplication().addFileSystemJournalListener(listener);
You also might need to keep a reference (listener) around for as long as you want to receive events. But maybe not (the addFileSystemJournalListener() call might do that). But, you at least need that call to addFileSystemJournalListener(), or you'll never get fileJournalChanged() called back.
I am creating a multimedia app that allows the user to save wallpapers and ringtones. I know the path I need to save them to is "SDCard/BlackBerry/ringtones/file.mp3" (or "/pictures" for wallpapers). I have searched forums and post for a couple days and the only thing I found was how to write text files. For now, assume that the ringtones and pictures are saved in the projects resource folder. If you could provide any input, I would greatly appreciate it.
Saving anything should be about the same. Try something like this:
FileConnection fc;
try {
String fullFile = usedir + filename;
fc = (FileConnection) Connector.open(fullFile, Connector.READ_WRITE);
if (fc.exists()) {
Dialog.alert("file exists");
} else {
fc.create();
fileOS = fc.openOutputStream();
fileOS.write(raw_media_bytes, raw_offset, raw_length);
}
} catch (Exception x) {
Dialog.alert("file save error);
} finally {
try {
if (fileOS != null) {
fileOS.close();
}
if (fc != null) {
fc.close();
}
} catch (Exception y) {
}
}
usedir and filename are your path components, raw_media_bytes is your data, etc etc.
Thanks for your help cjp. Here is the code to saving a resource mp3 file to a sd card:
byte[] audioFile = null;
try {
Class cl = Class.forName("com.mycompany.myproject.myclass");
InputStream is = cl.getResourceAsStream("/" + audioClip);
audioFile = IOUtilities.streamToBytes(is);
try {
// Create folder if not already created
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/ringtones/");
if (!fc.exists())
fc.mkdir();
fc.close();
// Create file
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/ringtones/" + audioClip, Connector.READ_WRITE);
if (!fc.exists())
fc.create();
OutputStream outStream = fc.openOutputStream();
outStream.write(audioFile);
outStream.close();
fc.close();
Dialog.alert("Ringtone saved to BlackBerry SDcard.");
} catch (IOException ioe) {
Dialog.alert(ioe.toString());
}
} catch (Exception e) {
Dialog.alert(e.toString());
}
As cjp pointed out, here is how to save an image resource to a SD card:
EncodedImage encImage = EncodedImage.getEncodedImageResource(file.jpg");
byte[] image = encImage.getData();
try {
// create folder as above (just change directory)
// create file as above (just change directory)
} catch(Exception e){}