Search Unity

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:
    2,879
    You could simply have a button like "Save marker to Photos" and then it'd be user's responsibility to press it as many times as he/she wants.
     
  2. fuzzl

    fuzzl

    Joined:
    May 13, 2019
    Posts:
    4
    Yeah thats what I'll do now, thanks for ur fast responses! I just have to try now that it doenst create multiple image album. It seems like if i copy them by press button, it happens to fast. if i create manually my album before, all images go in the same album
     
  3. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You can set a minimum delay between each button press. If button is pressed too quickly, you can simply ignore the click.
    Time.realtimeSinceStartup
    should be helpful to achieve this.
     
  4. fuzzl

    fuzzl

    Joined:
    May 13, 2019
    Posts:
    4
    the problem is i dont want the user to click more than 1 time to download the marker :/
    thanks for your help!
     
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    What if they delete the marker from Photos after downloading it? You need to let the button download the marker whenever it is pressed.
     
  6. Amorino

    Amorino

    Joined:
    Jul 11, 2013
    Posts:
    4
    I cannot get to make work the LoadFromPath on iOS.

    I get the path using GetImageFromGallery, the path is from: /var/mobile/Containers/Data/Application/..../Library/Caches/tmp.png

    But the Texture2D taken is blank. It works on Unity_Editor and Android.
     
  7. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Are there any error messages? May I see your code?
     
  8. Amorino

    Amorino

    Joined:
    Jul 11, 2013
    Posts:
    4
    Got this log on XCode:

    Code (CSharp):
    1. errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}
    This is my code:
    Code (CSharp):
    1.  
    2. NativeGallery.Permission permission = NativeGallery.GetImageFromGallery((path) =>
    3.            {
    4.                image.gameObject.SetActive(true);
    5.                Debug.Log("Image path: " + path);
    6.                Texture2D texture = NativeGallery.LoadImageAtPath(path);
    7.                if (texture == null)
    8.                {
    9.                    Debug.Log("Couldn't load texture from " + path);
    10.                    return;
    11.                }
    12.                image.texture = texture;
    13.                Destroy(texture);
    14.                //    image.overrideSprite = Sprite.Create(texture, new Rect(0.0f, 0.0f, Screen.width, Screen.height), Vector2.zero);
    15.            }, "Select a PNG image", "image/*", maxSize);
    16. Debug.Log("Permission result: " + permission);
     
  9. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    That error message is normal. The issue with your code is that you are destroying the loaded texture in your code. You shouldn't do that unless you no longer need the texture. Example code destroys the texture after 5 seconds to release its memory because the object that the texture is assigned to is also destroyed after 5 seconds.
     
  10. panoramabeats

    panoramabeats

    Joined:
    Dec 6, 2016
    Posts:
    9
    Hi, I'm getting a
    The Java JAR file “NativeGallery.jar” could not be launched.

    No messages in the console, running 2019.1.1. Any ideas..? Thank you!
     
  11. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Are you trying to open the .jar file?
     
  12. Sczone

    Sczone

    Joined:
    May 9, 2019
    Posts:
    6
    Hello, I am new to Unity and C #. Tell me how I can upload an image from the Internet and save it in the gallery. (Android). I would be very grateful if you provide me with a sample code. Thank! Forgive me for my bad english :)
     
  13. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    To learn how to download the image, please search "unity download file from url"; you'll find plenty of example codes for it. After the image is downloaded, assuming its file path is imagePath, you can call
    NativeGallery.SaveImageToGallery(imagePath,"Album Name", System.IO.Path.GetFileName(imagePath));
     
  14. panoramabeats

    panoramabeats

    Joined:
    Dec 6, 2016
    Posts:
    9
    I am... sorry, I haven't used a JAR file or Java script at all. Upon some research, it looks like I need to place the JAR file in ~Assets/Plugins/Android/bin/ . Is this correct? My apologies, I'm still noob in this area.
     
  15. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  16. Sczone

    Sczone

    Joined:
    May 9, 2019
    Posts:
    6
    Hello again. Please tell me what am i doing wrong? I still need to save the image from the URL to the gallery of the Android device. Thank!

    upload_2019-5-23_13-25-35.png
     

    Attached Files:

  17. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Try replacing the contents of the
    else
    with this:

    NativeGallery.SaveImageToGallery(www.downloadHandler.data,"Album Name", "image.jpg");
     
  18. panoramabeats

    panoramabeats

    Joined:
    Dec 6, 2016
    Posts:
    9
    I actually tried to DM you, as to not fill up the board with novice-level questions, but it got blocked for spam..


    Some questions I have are:

    • After importing, you can simply call the script functions in the scripts? - or does a script need to be placed in a folder or on to a game object?

    For my application, this is currently how I call and assign the texture array, which cycles through on a raw image. What would be the best way to convert this to using the Native Gallery scripting?
    • I have a texture array:
      • public Texture[] imageSet;
    imageSet = Resources.LoadAll<Texture2D>("Image Set");
    print("Loaded Textures Folder");


    Would it work to convert it to this?
    Texture[] imageSet = NativeGallery.LoadImagesAtPath( );
    • Does it need to be gallery/photos? Is it this by default?

    I'm sorry if this is all too basic.
     
  19. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    - Yes you can use NativeGallery immediately after importing. You just have to set "Write Permission" to "External (SDCard)" in Player Settings
    - I don't recommend you to use NativeGallery for loading images in your Resources folder. If you use Resources.Load, you'll get a nice compressed Texture, so it won't consume much memory. If you use NativeGallery.LoadImageAtPath, the Texture will be uncompressed and will consume more memory because it is not possible to load image files into compressed Textures at runtime
    - If you still want to use NativeGallery, you can put your images in StreamingAssets rather than Resources and load them from there one by one. On iOS, simply using
    Texture2D texture = NativeGallery.LoadImageAtPath(System.IO.Path.Combine(Application.streamingAssetsPath, "image file.jpeg"));
    should work but on Android, you have to retrieve the image file from that path via WWW, copy its www.bytes to a temporary image file in Application.temporaryCachePath and call
    Texture2D texture = NativeGallery.LoadImageAtPath(System.IO.Path.Combine(Application.temporaryCachePath, "image file.jpeg"));
     
  20. panoramabeats

    panoramabeats

    Joined:
    Dec 6, 2016
    Posts:
    9
    Awesome, Thank you! Mainly I need to access the local Android folder -
    another issue is that I'm using a Texture[] (and also not a Texture2D[] as far as I know..)
    Can the scripting be easily adapted for arrays of textures?

    I try using something like this below, but get many errors and am not sure where to begin, which variables to name or delete here. The errors seem to all be syntax.

    imageSet = NativeGallery.GetImagesFromGallery(MediaPickMultipleCallback callback, string title = "", string mime = "image/*", int maxSize = -1);
     
    Last edited: May 28, 2019
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You can store Texture2Ds inside a Texture array. The code below will work on only Android 18 or later (iOS not supported).

    Code (CSharp):
    1. NativeGallery.GetImagesFromGallery( ( paths ) =>
    2. {
    3.     if( paths != null )
    4.     {
    5.         imageSet = new Texture[paths.Length];
    6.         for( int i = 0; i < paths.Length; i++ )
    7.             imageSet[i] = NativeGallery.LoadImageAtPath( paths[i] );
    8.     }
    9. } );
     
    panoramabeats likes this.
  22. panoramabeats

    panoramabeats

    Joined:
    Dec 6, 2016
    Posts:
    9
    Yes, it worked! Thank you so much!!

    Ideally, I'd want it to start out automatically running from this specific folder, instead of launching the selection menu in the Android os. Likely, this is doable? However, it is totally fantastic to be able to do selections or Select All in any folder.
     
    Last edited: May 30, 2019
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    It is not possible with NativeGallery, sorry. I'd like to remind you that GetImagesFromGallery works only on Android 18 or later. Glad it works for you!
     
  24. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    Hi @yasirkula, I am trying to use getsavepath() but it tells me i can't do it because of the protection level.
    Texture2D tex = NativeGallery.LoadImageAtPath(NativeGallery.GetSavePath("Liverys",fileName));

    Any idea? Thx for this great plugin :)
     
  25. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  26. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    I already tried someting simelar...hm.. am I doing something wrong with my path?

    saving:
    string fileName = "Livery" + "_" + CarIndex + ".png";
    NativeGallery.SaveImageToGallery(savedTexture, "Livery", fileName);

    loading:
    string fileName = "Livery" + "_" + CarIndex + ".png";
    Texture2D tex = NativeGallery.LoadImageAtPath("Livery"+fileName, 1024, false, false, false);
     
  27. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I see, so you are trying to load the saved image in the next session. If it is not necessary to save the image to the gallery, you should simply save it to Application.persistentDataPath. Otherwise, you should keep a copy of the image in Application.persistentDataPath, save its path (to e.g. PlayerPrefs) and load the image from there in the next session.
     
  28. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    06-12 20:54:24.726: E/Unity(25866): FileNotFoundException: File not found at /storage/emulated/0/Android/data/com.UnityGame.ProjectARG/files/Livery_0.png

    the file is there and the path is correct. but the debugger says not... o_o
     
  29. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Does File.Exists(filePath) return true?
     
  30. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    this is how I now try to load the texture:
    Code (CSharp):
    1.             Texture2D tex = NativeGallery.LoadImageAtPath(Application.persistentDataPath +"/"+ fileName, 1024, false, false, false);
    and
    Code (CSharp):
    1.             Debug.Log(File.Exists(Application.persistentDataPath + "/" + fileName));
    returns false.

    there you can see the filepath on my phone.
    https://imgur.com/a/ahcG7Oo
     
    Last edited: Jun 13, 2019
  31. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Does
    Debug.Log(Application.persistentDataPath + "/" + fileName)
    return the same path? If so, are you attempting to save the image to the Gallery after it is downloaded from the internet? You may have to wait for the download operation to finish first.
     
  32. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    Yes it does, already tested that. No I'm not trying to access a downloaded file.
     
  33. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I don't know why File.Exists would return false for that file but NativeGallery is failing because of it :/
     
  34. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    when i do
    string fileName = "Livery" + "_" + CarIndex + ".png"; //<-----
    NativeGallery.SaveImageToGallery(savedTexture, Application.persistentDataPath, fileName);

    it says in the debug log:

    06-16 22:05:16.947: I/Unity(26341): Saving to gallery: /storage/emulated/0//storage/emulated/0/Android/data/com.UnityGame.ProjectARG/files/Livery_0.png

    why two times /storage/emulated/0/ ? or is this normal?
     
  35. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You should use a single-sentence album name instead of Application.persistentDataPath. For example, try using "My Album".
     
  36. marcell123455

    marcell123455

    Joined:
    Jun 18, 2014
    Posts:
    275
    I could fix it. I added "/storage/emulated/0/" to the loading path.

    Texture2D tex = NativeGallery.LoadImageAtPath("/storage/emulated/0/Livery/" + fileName, 1024, false, false, false);

    Thanks for your help :)
     
    yasirkula likes this.
  37. heyfrey

    heyfrey

    Joined:
    Jun 26, 2018
    Posts:
    7
    This is great, thank you yasirkula!

    Do you know if it's possible to change the layout of the image gallery on Android to fullscreen? Or go directly to Images or Gallery .

    Thanks!
    IMG_3945.jpg
     
  38. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    ryujm likes this.
  39. heyfrey

    heyfrey

    Joined:
    Jun 26, 2018
    Posts:
    7
    Thank you for the quick reply. This is exactly what i want / need. I changed the line 87 in the JAR Source/NativeGalleryMediaPickerFragment.java to startActivityForResult( intent, MEDIA_REQUEST_CODE );
    , rebuild the library and replaced the jar-file in the unity project. But now i get an error-message when i try to open the Gallery.

    Android.JavaException: java.lang.ClassNotFoundException: com.yasirkula.unity.NativeGalleryPermissionReceiver

    So now i don't know if i did the library rebuild right or there is something else wrong.
    Would it possible for you to make the rebuild for me or test the changes on your side?

    thx...
     
  40. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You should open your jar with Winrar and verify that it contains the com/yasirkula/unity/NativeGalleryPermissionReceiver.java file.
     
  41. heyfrey

    heyfrey

    Joined:
    Jun 26, 2018
    Posts:
    7
    my jar container contains...
    • NativeGallery.class
    • NativeGalleryMediaPickerFragment.class
    • NativeGalleryMediaReceiver.class
    • NativeGalleryPermissionFragment.class
    • NativeGalleryPermissionReceiver.class
     
  42. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Looks correct. I'm not sure why your jar doesn't work, though. Please compare its contents with NativeGallery's default jar file and see if their contents match.
     
  43. EdyH

    EdyH

    Joined:
    Jun 20, 2019
    Posts:
    13
    Hi
    First thank you for this plugin.
    I want to know how do you provide the path to Unity?
    Do you copy the image from the original to internal app storage in Android?
    How much is the delay after you pick photo to unity?
     
  44. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    SaveImageToGallery: yes, the image is copied to an internal path. This path is determined via NativeGallery.GetSavePath on Android. On iOS, Photos app copies the file to an internal path that is not exposed to us.

    GetImageFromGallery: if the image's original path in Gallery can be determined, that path is returned on Android. Otherwise the image is copied to a temporary location and that path is returned. On iOS, the image is always copied to a temporary location.

    The delay should be a couple of seconds.
     
  45. EdyH

    EdyH

    Joined:
    Jun 20, 2019
    Posts:
    13
    In another plugin, I was experiencing a delay around 2 seconds. It was always copying the image to a temporary location when picking from gallery. It is not acceptable for user experience so I was seeking for another solution.
    I used GPU to pass texture to Unity. The delay dropped to 20-30 ms
    Unfortunately I have no experience in IOS so I developed the plugin only for Android.
    If you think that you or any person from community can implement GPU transfer in IOS please let me know so I can adapt the solution for Android in your plugin and make a pull request .
    Thanks
     
    Last edited: Jun 21, 2019
  46. blaumeisje

    blaumeisje

    Joined:
    Dec 31, 2017
    Posts:
    19
    Hi Yasirkula,

    this is a great plugin. Works perfectly on the first try, no problems. I am very happy. I use it just to pick/read pictures from IOS and Android Smartphones and use the texture in Unity. All works great, just one little inconvenience:

    On IOS/IPhone, the picked file is stored in the Apps Sandbox. After I have used it, I do never need it again, so I want to delete it from my apps sandbox. Now that does not work, and the local storage size of my app gets bigger and bigger with every picked picture. Here my simple C# code I use to delete the file directly after getting the texture:

    //delete local file on iPhone
    if (Application.platform == RuntimePlatform.IPhonePlayer)
    {
    File.Delete("/private" + Application.persistentDataPath + "/temp.png");


    I had the impression, it sometimes works and sometimes not. Unfortunately I have no FileExplorer on the iPhone to see the files in my App sandbox and their names. I also tried to use the path returned from NativeGallery. It works well to get the image but not with File.Delete().

    NativeGallery.LoadImageAtPath(path, maxSize);


    Can you help me with the correct App sandbox path of the picture files copied from the iPhone Fotos into the Apps sandbox? That would help a lot.

    Thank you very much.
     
  47. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Does
    File.Exists(filePath)
    return true? Also, you can log your files' path to console as an alternative to using a file explorer. To do so, use
    new System.IO.DirectoryInfo(directoryPath).GetFiles("*",System.IO.SearchOption.AllDirectories)
    to get all files in directoryPath (including files inside subdirectories) and Debug.Log their
    FullName
    property.
     
    blaumeisje likes this.
  48. blaumeisje

    blaumeisje

    Joined:
    Dec 31, 2017
    Posts:
    19
    Thanks a lot, will check it out.
     
  49. blaumeisje

    blaumeisje

    Joined:
    Dec 31, 2017
    Posts:
    19
    Confused:
    A) nativeGallery returns image path like: /var/…./Library/Cashes/tmp.png
    B) I load that path's image via WWW (adding file://), works great
    C) I delete exactly that path. Seems to work, no errors to catch

    But D) iPhone Storage shows increased storage volumes for Documents and Data of my App with every new image
    and E) using DirectoryInfo.GetFiles for private/Application.persistentDataPath gives back a path like /private/var/…/Documents/… and shows 2 other files but never increases the quantity of files

    Why is the overal app storage size increasing with each file??
    Does nativeGallery store a picked file twice?
    Once as /var/…./Library/Cashes/tmp.png and
    again as somwhereelsepath/whatevername.png???
     
  50. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879