Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Native Gallery for Android & iOS [Open Source]

Discussion in 'Assets and Asset Store' started by yasirkula, Feb 28, 2018.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Hi there,

    I'd like to share a native plugin that helps you interact with Gallery/Photos on Android & iOS. With this plugin, you can:

    - save your images/videos to Gallery/Photos (gif files also supported)
    - prompt the user to pick an image or video from Gallery/Photos (picking gif files not supported on iOS)

    Simple as that. Runtime permissions for Android M+ are also supported.

    Asset Store: https://www.assetstore.unity3d.com/en/#!/content/112630
    Also available at: https://github.com/yasirkula/UnityNativeGallery

    Enjoy!
     
    Last edited: Mar 14, 2018
    psy4lyf, elpuerco63, efge and 4 others like this.
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Now live on Asset Store!
     
  3. ivo_petrov

    ivo_petrov

    Joined:
    Feb 28, 2018
    Posts:
    1
    Hi, I am trying to use your asset but I have difficulties. I can't connect the script "NativeGallery" to any Gameobject. I have the error "the script class can't be abstract". Could you please help me with this?
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    NativeGallery is a static class, so it can't be attached to any GameObject. Instead, you should simply call its static functions from your scripts, like this:
    Code (CSharp):
    1. NativeGallery.SaveImageToGallery( myTexture, "GalleryTest", "My img {0}.png" )
    See the online documentation for a more comprehensive example code.
     
  5. SrXoo

    SrXoo

    Joined:
    Nov 8, 2016
    Posts:
    4
    Hi, I am having troubles making the plugin work on iOS using the Unity Cloud service.

    Is there any support for it? I have not found any clue in the documentation.

    Thanks.
     
  6. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Honestly, I haven't thought about Unity Cloud Build support. Let me see how Cloud Build integration for plugins work.
     
  7. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    I've added a post-processor script to automate the XCode setup. It works fine while building from Editor but I didn't get a chance to test it on Unity Cloud Build. It is currently available at the GitHub repo: https://github.com/yasirkula/UnityNativeGallery

    If you test it on UCB, please let me know the result.
     
  8. jovemcaio

    jovemcaio

    Joined:
    Mar 19, 2018
    Posts:
    8
    Hi there!
    First of all, great job on the Plugin!
    I am using it to make a memory game where the user can create its own theme by using its photos from the phone gallery. I am having a little bit of trouble trying to understand some things.
    - I want to check if the device supports multiple image picker to know if I should call the "GetImage" method or the "GetImages"
    - I want to get the images from the gallery and create a path to store all of them, so I can call a method like "Resources.LoadAll<Sprite>("Sprites/Themes/" + path);"

    The problem is that I don't know how to treat the path returned by GetImagesFromGallery. I tried to Debug but it didn't show me the path (I used Android Monitor Log, from Android Studio). If you could give me some advice I would be really thankful. Here is my code:

    NativeGallery.Permission permission;

    if (NativeGallery.CanSelectMultipleFilesFromGallery())
    {
    permission = NativeGallery.GetImagesFromGallery((paths) =>
    {
    if (paths != null)
    {
    Debug.Log("Path multiple Images: " + paths);
    }

    }, title: "Select multiple images", mime: "image/*");
    }
    else
    {
    permission = NativeGallery.GetImageFromGallery((path) =>
    {

    if (path != null)
    {
    Debug.Log("Path Single Image: " + path);
    Texture2D texture = new Texture2D(2, 2);
    texture.LoadImage(File.ReadAllBytes(path));
    imageTest.texture = texture; //Raw Image. It worked for a single image
    }
    }, title: "Select single image", mime: "image/*");
    }
     
  9. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    You are using NativeGallery.CanSelectMultipleFilesFromGallery() correctly. It returns true only if the device supports multiple image picker.

    The only problem with your code is that, as the callback of GetImagesFromGallery returns a string array (rather than a string), you should iterate over the paths variable:

    Code (CSharp):
    1. if (paths != null)
    2. {
    3.     foreach( string path in paths )
    4.     {
    5.         Debug.Log("Path multiple Images: " + path);
    6.     }
    7. }
    Unfortunately, Resources.LoadAll only works for files that are located inside the Resources folder of your project. So, you will have to create textures from the selected images using a code similar to the one you wrote inside GetImageFromGallery. You don't really have to copy the selected images to a single directory for this. Simply iterate over paths variable and create a texture for each path.
     
    jovemcaio likes this.
  10. jovemcaio

    jovemcaio

    Joined:
    Mar 19, 2018
    Posts:
    8
    Thank you so much for the feedback!
     
  11. calebbbarton

    calebbbarton

    Joined:
    Mar 20, 2018
    Posts:
    5
    Hi there, I'm using your software to save/load images on mobile devices, and I'm very happy so far, however I'm running into a problem.

    The software I'm developing requires me to save the full filepath of the images I'm saving, and have run into a problem doing this on IOS builds using the NativeGallery.


    //save image taken from camera
    NativeGallery.SaveImageToGallery(toSave, "PassionMaps", m_currentMap + m_imageCount);
    //then grab full path so we can save it elsewhere
    m_fullImagePath = NativeGallery.GetSavePath("PassionMaps", m_currentMap + m_imageCount + ".png");


    As you can see, I've made the GetSavePath a public function from within the NativeGallery.cs script, but due to the way you're handling IOS image loading, using this method doesn't work on my IOS builds. (It adds a "_1" to my images, causing an incorrect filepath, and removing this string still results in an incorrect directory.)

    Is there a recommended way that I can get the full filepath of the image on IOS?

    Thanks,

    Caleb
     
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Plugin saves the image to a temporary location on iOS and deletes this temporary copy after the image is successfully saved to Photos. That's because Photos app internally keeps a separate copy of its images/videos. AFAIK, the full path of images in Photos app is not accessible to developers.

    Therefore, on iOS, you may have to write your image to Application.persistentDataPath or another accessible directory and save its full path instead. Then, you can call the SaveImageToGallery function that takes existingMediaPath as parameter to save the image to Photos.

    So, on iOS, your code should look similar to this (assuming that toSave is a Texture2D):

    Code (CSharp):
    1. string fullPath = Path.Combine( Application.persistentDataPath, m_currentMap + m_imageCount + ".png" );
    2. File.WriteAllBytes( fullPath, toSave.EncodeToPNG() );
    3.  
    4. NativeGallery.SaveImageToGallery( fullPath, "PassionMaps", Path.GetFileName( fullPath ) );
     
    litingqjt likes this.
  13. calebbbarton

    calebbbarton

    Joined:
    Mar 20, 2018
    Posts:
    5
    Hi there

    Thanks for such a swift response! I had to wait a few days for my IOS tester to get back to me, but your solution worked perfectly.

    Thanks very much.
     
    yasirkula likes this.
  14. jovemcaio

    jovemcaio

    Joined:
    Mar 19, 2018
    Posts:
    8
    Hi there!
    Does anybody know if it is possible to hide the path where the images are saved so that the user can't access the photos through the android gallery? And how to delete photos from the path only through the application?

    I am working on a game in which the images are saved on a path and it is a requisite that the user may only be able to get or delete the photos on this path through the game.

    I would really appreciate if somebody could point me the right direction. Thanks!
     
    Last edited: Apr 3, 2018
  15. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    You can save your photos to Application.persistentDataPath or, preferably, a subfolder of it. These images will not be visible to Gallery/Photos. However, you will not be able to use NativeGallery to save/load these images, which means you will have to create your own UI to save/load these images.

    You can use the following functions save/load/delete images:

    string imagesFolderPath = Path.Combine( Application.persistentDataPath, "imagesFolderName" );
    string imagePath = Path.Combine( imagesFolderPath, "image name.jpeg" );


    Save:
    Directory.CreateDirectory( imagesFolderPath );
    File.WriteAllBytes( imagePath, imageBytes );


    Load:
    if( File.Exists( imagePath ) )
    byte[] imageBytes = File.ReadAllBytes( imagePath );


    Delete:
    if( File.Exists( imagePath ) )
    File.Delete( imagePath );


    List Files:
    if( Directory.Exists( imagesFolderPath ) )
    string[] files = Directory.GetFiles( imagesFolderPath );
     
    Kjurek and jovemcaio like this.
  16. garethlamyh

    garethlamyh

    Joined:
    Jul 25, 2017
    Posts:
    5
    I am finding a plugin which can pick .bmp images from Android Gallery so that I can get the pixel data from it for further usage. Does this plugin support .bmp format? Or only for jpg & png? Thanks!:):)
     
  17. jovemcaio

    jovemcaio

    Joined:
    Mar 19, 2018
    Posts:
    8
    Thank you so much, yasirkula!
     
  18. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Although haven't tested it myself, the NativeGallery.LoadImageAtPath function should support bmp, gif, jpeg, png and webp formats. Here is an example code:

    Code (CSharp):
    1. NativeGallery.GetImageFromGallery( ( path ) =>
    2. {
    3.     Debug.Log( "Image path: " + path );
    4.     if( path != null )
    5.     {
    6.         // Create Texture from selected image
    7.         Texture2D texture = NativeGallery.LoadImageAtPath( path, 1024 ); // image will be downscaled if its width or height is larger than 1024px
    8.         if( texture == null )
    9.         {
    10.             Debug.Log( "Couldn't load texture from " + path );
    11.             return;
    12.         }
    13.      
    14.         // Use 'texture' here
    15.         // ...
    16.     }
    17. }
     
    Last edited: Apr 5, 2018
    garethlamyh likes this.
  19. garethlamyh

    garethlamyh

    Joined:
    Jul 25, 2017
    Posts:
    5
    yasirkula, thanks for writing such a great plugin. I can really import a bmp image from android gallery and set it as the texture2D of a raw image. However, when I tried to use getpixel() functions to read pixel data from the texture, the texture turns white. And I do not understand what's wrong......

    here's my code:
     
  20. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    NativeGallery.LoadImageAtPath has an optional parameter called markTextureNonReadable, which is set to true by default. Can you try loading the image with it set to false, instead:

    Texture2D texture = NativeGallery.LoadImageAtPath(BMPPath, 1024, false);
     
    garethlamyh likes this.
  21. garethlamyh

    garethlamyh

    Joined:
    Jul 25, 2017
    Posts:
    5
    I made a stupid mistake......I forgot to set the texture of the rawImage to Texture2D texture. That's why I can see nothing but only a white image. And I think the pixel data can be read correctly. Thank you for your help!
     
  22. Archviz3d

    Archviz3d

    Joined:
    Apr 4, 2016
    Posts:
    92
    Hey @yasirkula !!! Great improvements on your fantastic asset!!! Just one question, on ios can you create a folder inside photos with your asset, and save your photos there from the Application.persistentDataPath of ios?
     
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Yes, the NativeGallery.SaveImageToGallery( string existingMediaPath, string album, string filenameFormatted, MediaSaveCallback callback = null ) function will create the specified folder (album) in Photos and save the provided image there. If your image is named image.png and is located at the root of the persistentDataPath, then the following code should do the trick:

    Code (CSharp):
    1. NativeGallery.SaveImageToGallery( System.IO.Path.Combine( Application.persistentDataPath, "image.png" ), "Folder Name", "image.png" );
     
  24. Archviz3d

    Archviz3d

    Joined:
    Apr 4, 2016
    Posts:
    92
    @yasirkula WoowwwwWWW thats awesome :)))))) have to try it!!!! Thank you so much :)))))))

    Would your asset also work to save videos for the application.persistentdatapath to a custom folder on photos of iOS ???
     
  25. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Sure it does :)

    Code (CSharp):
    1. NativeGallery.SaveVideoToGallery( System.IO.Path.Combine( Application.persistentDataPath, "video.mp4" ), "Folder Name", "video.mp4" );
     
    Archviz3d likes this.
  26. Archviz3d

    Archviz3d

    Joined:
    Apr 4, 2016
    Posts:
    92
    Thats so cool!! Just what i needed!!!! Thank you so much!!! Hope i can repay some day :)
     
  27. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Lol, you are welcome!
     
    mainVar likes this.
  28. asyranamin

    asyranamin

    Joined:
    Nov 27, 2017
    Posts:
    3
    Hi, Great plugin. i love it... But is there a delete from gallery function?
    Im currently using File.Delete(savepath)

    But in the gallery there is still the thumbnail where the image should have been.. Can you assist with this? Thank You.
     
  29. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    There is a hidden Delete function (see this topic) but it requires you to know the absolute path of the saved image and it works on Android only.

    NativeGallery doesn't return the absolute path of the saved image/video (mainly because it is inaccessible on iOS). However, if your string filenameFormatted parameter doesn't contain a {0}, you can get the absolute path of the saved image on Android by making the NativeGallery.GetSavePath function public and then calling it.
     
  30. asyranamin

    asyranamin

    Joined:
    Nov 27, 2017
    Posts:
    3
    Cheers man.. thanks alot.
     
  31. WoolderSoft

    WoolderSoft

    Joined:
    Apr 1, 2018
    Posts:
    3
    Hello @yasirkula, I want to import an image from the gallery on android, but I don't know how I have to use this plugin. I am making a puzzle game and I want to puzzle with my own photo's, but I can't get this working. I can't even open the gallery on my phone (maybe that sounds stupid and I looked at your online documentation, but I am a beginner with Unity). Can you help me with this? Thank you.
     
  32. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Here's a simplified version of the example code:

    Code (CSharp):
    1. public Texture2D pickedImage;
    2.  
    3. public void PickImageFromGallery( int maxSize = 1024 )
    4. {
    5.     NativeGallery.GetImageFromGallery( ( path ) =>
    6.     {
    7.         if( path != null )
    8.         {
    9.             // Create Texture from selected image
    10.             pickedImage = NativeGallery.LoadImageAtPath( path, maxSize );
    11.         }
    12.     }, maxSize: maxSize );
    13. }
    After you call the PickImageFromGallery function, you'll be able to pick an image from the Gallery (if image is larger than maxSize px, it will be downscaled for better memory usage). After you pick an image, it will be stored at the pickedImage variable.
     
  33. WoolderSoft

    WoolderSoft

    Joined:
    Apr 1, 2018
    Posts:
    3
    Thank you, for sending the solution. Now I can open the gallery, show the image in my app and it looks gorgious. You have made an amazing plugin!
     
  34. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    You are welcome :)
     
  35. pertz

    pertz

    Joined:
    Jan 8, 2015
    Posts:
    44
    Awesome plugin. Thanks a lot. It took me less than 2 minutes to have it working for opening a photo from the gallery.

    I had all the rest of the code already working and tested (I was using a system dialog to test it on the editor), so using your plugin was a breeze.

    Congrats for the great work and thanks for providing it.
     
    yasirkula likes this.
  36. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula ,
    I am not able to save video from StreamingAssets in Android/IOS Gallery.
    Please help.
     
  37. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    On Android, StreamingAssets is bundled inside a .jar/.apk file. You have to extract the file somehow. For example, if you want to save StreamingAssets/image.png to gallery on Android, you can use the following function:

    Code (CSharp):
    1. public void SaveImageToGalleryFromStreamingAssets()
    2. {
    3.     StartCoroutine( SaveToGalleryCoroutine() );
    4. }
    5.  
    6. private IEnumerator SaveToGalleryCoroutine()
    7. {
    8.     string url = System.IO.Path.Combine( Application.streamingAssetsPath, "image.png" );
    9.     WWW www = new WWW( url );
    10.     yield return www;
    11.    
    12.     NativeGallery.SaveImageToGallery( www.bytes, "Album name", "image.png" );
    13. }
    Saving from StreamingAssets on iOS should work, though. Are you getting any errors in the console?
     
  38. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula Thanks for your revert but i have one more problem regarding Android.
    You have mentioned
    • for Android: set Write Permission to External (SDCard) in Player Settings
    But is this is possible without External(SDCard) because now Android Smartphones are having enough memory so no one inserts external SDCard.

    Please Help in this also
     
  39. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    The term "external storage" is a confusing one because it doesn't actually mean a "removable storage". AFAIK, it just means the files/directories that your app can't access to without permission. For example, your app can access its cache/temp directory without permission because it is "internal" storage but your app can't access images/videos on the device without permission because they are "external" storage. You'll need Write External Storage permission to write new media to Gallery.
     
    pmtechllp likes this.
  40. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula Is that possible to save Audio files with your plugin.
    Thanks for your support.
     
  41. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    On Android, it might be possible with the following code:

    NativeGallery.SaveImageToGallery( "PATH_TO_MUSIC", "Album might not work", "music.mp3" );


    I haven't tried it myself, though.
     
  42. kendev

    kendev

    Joined:
    Aug 9, 2015
    Posts:
    9
    Hi @yasirkula Thanks for a GREAT plugin!

    It works great on Android, but I'm having a problem in the linker phase on iOS. I'm using Unity 2017.3 and Xcode 9.3 and get the following linker errors:

    Undefined symbols for architecture armv7:
    "_kUTTypeVideo", referenced from:
    +[UNativeGallery pickMedia:savePath:] in NativeGallery.o
    "_kUTTypeImage", referenced from:
    +[UNativeGallery pickMedia:savePath:] in NativeGallery.o
    +[UNativeGallery imagePickerController:didFinishPickingMediaWithInfo:] in NativeGallery.o
    "_OBJC_CLASS_$_PHAssetCollection", referenced from:
    objc-class-ref in NativeGallery.o
    "_OBJC_CLASS_$_PHFetchOptions", referenced from:
    objc-class-ref in NativeGallery.o
    "_kUTTypeMovie", referenced from:
    +[UNativeGallery pickMedia:savePath:] in NativeGallery.o
    "_OBJC_CLASS_$_PHAssetCollectionChangeRequest", referenced from:
    objc-class-ref in NativeGallery.o
    "_OBJC_CLASS_$_PHAssetChangeRequest", referenced from:
    objc-class-ref in NativeGallery.o
    "_OBJC_CLASS_$_PHPhotoLibrary", referenced from:
    objc-class-ref in NativeGallery.o
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    Have you seen this before? Looks like I'm missing something so any ideas are most appreciated.

    Thanks,

    Ken
     
  43. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    It looks like NGPostProcessBuild is somehow not executed. Did you set NGPostProcessBuild.ENABLED to false by mistake? If not, can you copy&paste the Other Linker Flags of your project here? Thanks!
     
  44. kendev

    kendev

    Joined:
    Aug 9, 2015
    Posts:
    9
    Hi @yasirkula I checked that NGPostProcessBuild is set to true. And here are the Other Linker flags:

    upload_2018-5-2_11-13-20.png

    Looks like they're empty...
     
  45. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    I'm downloading Unity 2017.4 to my Mac to test it there (with Xcode 9.2). In the meantime, can you test the plugin on a blank Unity project to see if something changes?
     
  46. kendev

    kendev

    Joined:
    Aug 9, 2015
    Posts:
    9
    Yes, will do!
     
    yasirkula likes this.
  47. kendev

    kendev

    Joined:
    Aug 9, 2015
    Posts:
    9
    Hi @yasirkula I created a new project using only Native Gallery and it compiles, links, and works on iOS!

    Seems to be a conflict somewhere in my main project (I'm using Vuforia, NatCam, and several other plugins) so if you have any ideas please let me know. I'll update you whenever I find the problem...

    Thanks for your prompt replies!
     
  48. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    Can you search for the term [PostProcessBuild in scripts located inside Editor folder(s) in your project and send any matches to yasirkula@gmail.com? One of them might be reverting the changes NativeGallery applies to the Xcode project.

    In the meantime, as a workaround, you can apply the steps mentioned in Manual Setup for iOS to your existing project to get rid of the errors.
     
  49. Rlapham

    Rlapham

    Joined:
    Dec 5, 2016
    Posts:
    5
    This is great, thank you yasirkula!

    Do you know if it's possible to change the layout of the image gallery. On iOS it appears as a small box in the top right corner.
    Thanks!
     
  50. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    835
    I'm using a native class (UIImagePickerController) to show the gallery on iOS and I'm afraid it doesn't support any customization. But the gallery should appear either as a popup at the center of the screen on iPads, or as a fullscreen view on iPhones. I haven't seen it appearing at the top right corner of the screen :D Can you post a screenshot?