Xamarin.Mobile Component multiple file saved getting deleted without calling delete function for iOS - ios

We are using Xamarin.Mobile component for taking and storing photos in an local app directory. Now, its works fine when I am storing a single photo but if I am storing multiple photo and trying to access those, only last image exist, all other images are getting deleted. I don’t call delete function anywhere in my code.
We are making app for both iOS and android and we have some Core Class that are linked in both projects
When it enter the function as shown is the last call stack, only last image exists, all other image are getting deleted.
The top three functions are from our Core Class which are linked in both iOS and Android.
I have enable iTunes file sharing, images are getting stored inside Documents folder and I am giving each image a different name.
here is the code for taking photos:
Random rand1 = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
picker = new MediaPicker();
if( !picker.IsCameraAvailable )
return;
MediaPickerController controller = picker.GetTakePhotoUI (new StoreCameraMediaOptions {
Name = "Ticket"+rand1.Next(1, 1000000)+".jpg",
Directory = ""
});
this.PresentViewController( controller, true, null );
controller.GetResultAsync().ContinueWith (t => {
// We need to dismiss the controller ourselves
this.PresentedViewController.DismissViewController (true, () => {
// User canceled or something went wrong
if (t.IsCanceled || t.IsFaulted)
return;
// We get back a MediaFile
MediaFile media = t.Result;
ticket.imagePaths.Add( media.Path );
});
}, uiScheduler);
Here is my Application Output:
2014-01-15 15:17:40.445 CCR_Ticket_System_iOS[2063:60b] File Exists in TicketRepo: /private/var/mobile/Applications/ABE44A50-7119-4BF9-8DF9-DC50C80E7591/Documents/Ticket235666.jpg
2014-01-15 15:17:42.384 CCR_Ticket_System_iOS[2063:60b] File Exists in TicketRepo: /private/var/mobile/Applications/ABE44A50-7119-4BF9-8DF9-DC50C80E7591/Documents/Ticket952511.jpg
2014-01-15 15:17:49.320 CCR_Ticket_System_iOS[2063:60b] File doesn't Exists in SaveTicket in DatabaseADO: /private/var/mobile/Applications/ABE44A50-7119-4BF9-8DF9-DC50C80E7591/Documents/Ticket235666.jpg
2014-01-15 15:17:49.323 CCR_Ticket_System_iOS[2063:60b] File Exists in SaveTicket in DatabaseADO: /private/var/mobile/Applications/ABE44A50-7119-4BF9-8DF9-DC50C80E7591/Documents/Ticket952511.jpg
Please let me know what I am doing wrong. Please let me know if you need more information. I am stuck on this problem for last 2 days.

I just ran into this problem myself and saw that there was no solution posted yet. Here is what I figured out:
The problem has to do with the MediaPicker. When mediaPicker.PickPhotoAsync(), mediaPicker.TakePhotoAsync(), etc is called, it returns an object of type MediaFile. This MediaFile has a property called “Path” which contains a string with the path to the file. We store this string to use later.
The problem comes up when we realize how MediaPicker is implemented. As soon as the MediaFile is disposed of, it deletes the file that the MediaFile is associated with. Since we let the MediaPicker fall out of scope, the file gets deleted immediately after it is added to the list.
There are a couple solutions to this:
1) Keep a reference to the MediaFile until the file is no longer needed.
2) Copy the image to a new location so the MediaFile can be disposed of
Personally I think option 1 is a much better solution.

Related

find and share a downloaded video on Flutter ios without going through picker?

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?

How to show data in firebase cloud storage file? Mac OS

I would like to create a function that gets the data in my firebase cloud storage. For example, I have 3 separate folders as follows: Movies, Songs and previews. I would like to create a function that will be able to download the url file of the specified folder to get the data of it so I can display it on the selection screen. I have the folders pretty organized. They're in this order, Movies/MovieName/{Movie.jpg (image for the movie), Movie.mp4(video)}. I need my function to open up "Movies" and run through the MovieName file and post each of the contents inside those files. So kinda like a streaming service, I do NOT want to download the url file permanently on the localfile. So kinda think of netflix where they have the image of the movie, with a little description, reviews, etc and it'll stream. You can never download the movie permanently.
"What have I tried?":
I've tried using the firebase link here to guide me but it seems like I'm not understanding it. I've also tried the "list all" list all link but I don't believe it shows the data of each file. Nor was it working for me. Finally I've tried using the URLSession.streamtask()
but I've never used that before and so I'll try to successfully use it now by researching more.
"Some code":
func getAlbums() {
storageref.downloadURL { (url, error) in
if let error = error {
print(error.localizedDescription)
}
else {
//get download url
}
}
According to the firebase link attached this is what I need to do but I don't know how to get the download URL after the else statement.

How to set path to picture in folder in device in android appcelerator app

So I have app where I want to let users to share screenshot of score to facebook etc... I'm using SocialShare widget. In documentation it says to set path to image like this: "image:fileToShare.nativePath", but I'm not really sure how to set it. Another problem is that I need to share picture that has always different name, it saves screenshots with names like tia7828157.png,tia107997596.png... in folder in device internal memory in pictures/enigmania/ I'm new to appcelerator, so I dont know if there is something like wildcard I could use for this? Thanks for any help.
This is my code so far which I know is wrong, I know the widget works because it shares text without problem:
function shareTextWidget(e){
// share text status
var socialWidget=Alloy.createWidget('com.alcoapps.socialshare');
socialWidget.share({status:"Enigmania kvíz",androidDialogTitle:"hoho",image:test.png/pictures/enigmania});
}
You should use Ti.Filesystem class methods/properties to get the path of any file located on internal or external storage.
Also aware of the permissions of reading storage on Android 6+. Use Storage Permissions before accessing any file on Android 6+.
Simple code snippet to create a directory on internal storage at this location: pictures/enigmania and then write an image file of captured view in this directory.
function shareTextWidget(e){
var directory = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'pictures/enigmania');
!directory.exists() && directory.createDirectory();
var fileToShare = Ti.Filesystem.getFile(directory.resolve(), 'screen.jpg');
fileToShare.write($.SCREENSHOT_VIEW.toImage()); // write the blob image to created file
var socialWidget=Alloy.createWidget('com.alcoapps.socialshare');
socialWidget.share({status:"Enigmania kvíz",androidDialogTitle:"hoho",image:fileToShare.nativePath});
}
This code should work without any issues.
Note that $.SCREENSHOT_VIEW is the View ID for which you will take screenshot, so it depends on you how you maintain your View positions in order to capture correct screenshot, but point is to use Ti.UI.View toImage() method to capture the screenshot of particular view.
Let me know if this works for you or not, else we can look into other methods by getting your exact requirements. Good Luck!!!!

Dropbox SDK bug

I was found something strange when I using Dropbox SDK 1.3.14
And here is how the bug happen , I put a dictionary tree like
/Comic/Author - Comic name (ex.浦澤直樹 - Monster)/Volume1/0.jpg , 1.jpg , ...)
And I want download the jpg to iOS app,And also create the same dictionary tree as Dropbox
So I create a dictionary tree in Document , It looks like
/var/mobile/Containers/Data/Application/12711FE6...290C7EAF50/Documents/Dropbox/Comic/浦澤直樹 - Monster/Volume1
Than I try to download the first page of comic
But it shows an error tell me the dictionary is not exist .
I use NSFileManager to check , It did exist .
Finally I find the problem
At this callback
- (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata {
for (DBMetadata *file in metadata.contents) {
NSLog(#"File Path : %#",file.path);
}
}
Path will print like this
1./Comic
2./Comic/浦澤直樹 - Monster
3./Comic/浦澤直樹 - Monster/Volume1
4./Comic/浦澤直樹 - monster/Volume1/0.jpg
Now at the last file path , it gives me a different path name
I don't know why , but if I use this path to check is the parent dictionary is ready , It will return false.
So I never can download the file to specified path success
I was wonder does anyone got same issue like me ?
Dropbox itself is case-insensitive, with attempts to be case-preserving. However, due to various specifics, the API can't always return the expected case for every path component. So, for any file or folder metadata, the filename/last path component should have the preserved case, but other path components are not guaranteed to.
We realize this is non-ideal of course and are looking into ways to improve it, but I don't have a solution to offer right now.
If you need the preserved casing, you'll need to build it up from the last component in each parent entry.

(IOS) Cordova Camera Plugin Referring to deleted images

I'm building a cordova app (primarily for IOS & Android) in which the user can take an image, retake (, etc.) it and save it locally.
I'm currently struggling with the cordova cameraPlugin. So, here a short description of the problem.
When the user takes an image, it's saved locally in the apps temp folder and the user is able to view in in the UIWebView. On retaking, the image will be deleted from the temp folder and should not be available any longer (in RAM and local FS).
It works as long as the user doesn't retakes the image 2 or more times, if he does instead of the last image the first image will be referenced/rendered in WebView. After reopening the app, the image is displayed correctly.
An Example:
The user takes the first image. ==> cdv_photo_001.png
The second. ==> cdv_photo_002.png and the first one will be deleted (which seems to work correctly)
And the third. ==> cdv_photo_001.png and the second image will be deleted.
The third image will look the same as the deleted first one. This happens with every image after the third one.
It works fine after restarting the app
I've already tried to disable the App-Cache, delete the app cache before updating the image, refreshing the page and looking for answers online.
I'm getting an error when opening the camera UI, but I could not find a solution for it either.
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before
snapshotting or snapshot after screen updates.
The code for the camera Call:
function getPhoto() {
navigator.camera.getPicture(getPhotoOnSuccess, getPhotoOnFail, {
quality: 25,
destinationType: Camera.DestinationType.FILE_URL,
correctOrientation: true,
encodingType: Camera.EncodingType.PNG
});
}
In getPhotoOnSuccess I'm basically saving the image path to a db and appending it with jQuery to the view.
And the code to delete the image: (sidenote I`m new to Objective C)
- (void) deleteImageByPath:(NSString *)imagePath withSelector:(SEL)selector{
NSError *error = nil;
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *tempFolder = NSTemporaryDirectory();
if([mgr removeItemAtPath: imagePath error:&error] == NO) {
NSLog(#"File deleted");
}
//The files can be edited as well, so there can be two files in different directories
if(error != nil){
NSString *imgEl = tempFolder;
imgEl = [imgEl stringByAppendingPathComponent:imagePath.lastPathComponent];
if(![mgr removeItemAtPath:imgEl error:&error]){
NSLog(#"Old element couln't be deleted.");
}
}
[self performSelector:selector withObject:error];
}
The file is not in the directory anymore after deleting it, so I guess it works.
An important detail could be, that I wrote my own IOS cordova plugin, because the method for the file system access provided by cordova sucks.
So thats it.
The specific question is: Why and how is this happening and is there a chance to change this behavior? If yes, how should I proceed?
By the way, I`m using cordova 3.1.0 and the build target is IOS 7.
Thanks in advance.
Ok folks, I finally got it.
The whole problem was not related to my code or any of the cordova code.
So why did it happen? ==> I don't exactly know that, for it seems that this bug or whatever you might call it, has occurred to many people.
And they all tried to delete or deactivate the cache as I did, some of their problems are very close to my own but most aren't, so it took a while til I found a solution.
I read this thread and tried to append a timestamp to the image path and it worked!
My conclusion to this it, that there might be a problem with the UIWebView and the cache management.
Or it might proof as a general WebView problem, I will be able to check that in a few days on an Adroid device.

Resources