Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Video returned by gallery doesn't exist #3181

Open
jsfan3 opened this issue Jul 23, 2020 · 6 comments
Open

[BUG] Video returned by gallery doesn't exist #3181

jsfan3 opened this issue Jul 23, 2020 · 6 comments
Assignees
Milestone

Comments

@jsfan3
Copy link
Contributor

jsfan3 commented Jul 23, 2020

Randomly and unpredictably, sometimes the videos returned by the Gallery are not accessible. This only happens on iOS. Specifically, in my iPhoneX I have iOS 13.6.

Please note that I have uninstalled and reinstalled the same app many times for development purposes, I don't know if this detail is relevant.

Relevant code:

CN.openGallery(evt -> {
                if (evt != null && evt.getSource() != null) {
                    try {
                        // copy the file from the temporary location to the FileSystemStorage
                        String tempFile = (String) evt.getSource();
                        if (!FileSystemStorage.getInstance().exists(tempFile)) {
                            form.add(new SpanLabel("The file returned from gallery doesn't exist, it cannot be uploaded:"));
                            form.add(new SpanLabel(tempFile));
                            form.revalidate();
                            throw new IllegalStateException("The file returned from gallery doesn't exist: " + tempFile);
                        }
                        long tempFileSize = FileSystemStorage.getInstance().getLength(tempFile);
                        if (tempFileSize == 0) {
                            form.add(new SpanLabel("Empty file returned from gallery, it cannot be uploaded:"));
                            form.add(new SpanLabel(tempFile));
                            form.revalidate();
                            throw new IllegalStateException("Empty file returned from gallery: " + tempFile);
                        }
                [...]

                }, CN.GALLERY_ALL);
        });

Screenshot:

error

@jsfan3 jsfan3 changed the title [BUG] Video returned from gallery doesn't exist [BUG] Video returned by gallery doesn't exist Jul 23, 2020
@shai-almog shai-almog added this to the Version 8.0 milestone Jul 24, 2020
@jsfan3
Copy link
Contributor Author

jsfan3 commented Jul 24, 2020

@shai-almog Please consider that it's a blocking bug, since I cannot use the gallery to load videos, that it's a crucial feature. I tried to workaround the issue using the https://github.com/shannah/cn1-filechooser, but the issue is exactly the same. One of my friend tried the same code on a different iPhone model and he got the same issue.

So, in the meanwhile, if you have an idea about any workaround, I'll appreciate it.

@jsfan3
Copy link
Contributor Author

jsfan3 commented Jul 24, 2020

First the bug happened sporadically, then more frequently, now always... at least on my phone.

@jsfan3
Copy link
Contributor Author

jsfan3 commented Jul 24, 2020

This Stack Overflow discussion seem related to this issue, however I didn't get what I have to do:
https://stackoverflow.com/questions/57798968/didfinishpickingmediawithinfo-returns-different-url-in-ios-13

I add other infos:

  • on iOS 11, the video returned by Gallery are accessible;
  • on iOS 12, the video returned by Gallery is "null";
  • on iOS 13, the video returned by Gallery is a file path like the one in the screenshot, but it's not accessible.

@jsfan3
Copy link
Contributor Author

jsfan3 commented Jul 24, 2020

The same issue, I report the link in the case it can be useful to solve the issue:
apache/cordova-plugin-camera#506

@jsfan3
Copy link
Contributor Author

jsfan3 commented Jul 26, 2020

My temporary workaround using a native interface, that has pros and cons. It allows me to get a video using the iOS Gallery:

Gallery.java

import com.codename1.io.Log;
import com.codename1.io.Util;
import com.codename1.system.NativeLookup;
import com.codename1.ui.CN;

/**
 * Gallery
 */
public class Gallery {
    private static GalleryNative nativeInterface = NativeLookup.create(GalleryNative.class);
    private static volatile String filePath = null;
    private static volatile boolean lock = false;
    
    /**
     * Public API to pick a single video from the Gallery
     * @return 
     */
    public static String pickVideo() {
        if (nativeInterface != null && nativeInterface.isSupported()) {
            lock = true;
            Gallery.filePath = null;
            nativeInterface.pickVideo();
            while (lock) {
                CN.invokeAndBlock(() -> Util.sleep(500));
            }
            return filePath;
        } else {
            return null;
        }
    }
    
    /**
     * @deprecated Callback invoked by the native interface
     */
    public static void setFilePath(String filePath) {
        Log.p("Gallery.setFilePath invoked with argument: " + filePath);
        Gallery.filePath = filePath;
        lock = false;
    }
}

GalleryNative.java

import com.codename1.system.NativeInterface;

/**
 * @deprecated
 */
public interface GalleryNative extends NativeInterface {
        
    public void pickVideo();
}

myapp_utilities_GalleryNativeImpl.h:

#import <Foundation/Foundation.h>

@interface myapp_utilities_GalleryNativeImpl : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
}

-(void)pickVideo;
-(BOOL)isSupported;
@end

myapp_utilities_GalleryNativeImpl.m:

#import "myapp_utilities_GalleryNativeImpl.h"
#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h> // needed for video types
#import "CodenameOne_GLViewController.h"
#include "myapp_utilities_Gallery.h"

@implementation myapp_utilities_GalleryNativeImpl : UIViewController

-(void)pickVideo{
    dispatch_async(dispatch_get_main_queue(), ^{
        // Present videos from which to choose
        UIImagePickerController *videoPicker = [[UIImagePickerController alloc] init];
        videoPicker.delegate = self; // ensure you set the delegate so when a video is chosen the right method can be called

        videoPicker.modalPresentationStyle = UIModalPresentationCurrentContext;
        // This code ensures only videos are shown to the end user
        videoPicker.mediaTypes = @[(NSString*)kUTTypeMovie, (NSString*)kUTTypeAVIMovie, (NSString*)kUTTypeVideo, (NSString*)kUTTypeMPEG4];

        videoPicker.videoQuality = UIImagePickerControllerQualityTypeHigh;
        // [self presentViewController:videoPicker animated:YES completion:nil];
        [[CodenameOne_GLViewController instance] presentViewController:videoPicker animated:YES completion:^{}];
    });
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    dispatch_async(dispatch_get_main_queue(), ^{
        // This is the NSURL of the video object, note the "createTemporaryPathforVideoFile"
        // suggested here as solution for the iOS13 video gallery bug:
        // https://stackoverflow.com/a/61777073
        NSURL *videoURL = [self createTemporaryPathforVideoFile : [info objectForKey:UIImagePickerControllerMediaURL] ];

        NSLog(@"VideoURL = %@", videoURL);
        [picker dismissViewControllerAnimated:YES completion:NULL];
        myapp_utilities_Gallery_setFilePath___java_lang_String(CN1_THREAD_GET_STATE_PASS_ARG fromNSString(CN1_THREAD_GET_STATE_PASS_ARG videoURL.absoluteString));
    });
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    dispatch_async(dispatch_get_main_queue(), ^{
        [picker dismissViewControllerAnimated:YES completion:NULL];
    });
}

-(NSURL *)createTemporaryPathforVideoFile:(NSURL *)url{
    NSURL *tempURL =  [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:true];
    NSURL *tempFileURL = [tempURL URLByAppendingPathComponent:url.lastPathComponent];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager copyItemAtURL:url.absoluteURL toURL:tempFileURL error:nil];
    return tempFileURL;
}


-(BOOL)isSupported{
    return YES;
}

@end

@shai-almog shai-almog assigned shai-almog and unassigned shannah Jul 27, 2020
@shai-almog shai-almog modified the milestones: Version 8.0, Version 7.0 Jul 27, 2020
@shai-almog
Copy link
Collaborator

Thanks. I Think this is clearer now with your code and the Cordova fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants