Search Unity

Native Gallery for Android & iOS [Open Source]

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

  1. kendev

    kendev

    Joined:
    Aug 9, 2015
    Posts:
    10
    Hi @yasirkula,

    Thanks for the workaround and the fix to one of the third-party post processing scripts - no linker errors now and the app runs great on iOS!

    Cheers!
     
  2. Rlapham

    Rlapham

    Joined:
    Dec 5, 2016
    Posts:
    5
    Thanks for responding so quickly.

    Here's the screenshot. It appears there when vertical and in the upper center when horizontal (I'll attach two screenshots). For reference I have a 2017 iPad Pro 10.5", running ARKit 1.5 on iOS 11.2.

    It would be great to be able to position it. I also tried instantiating an object and fed the video path to it's videoplayer and it worked! (the handheld fullscreen didn't seem to work on mine). It's pretty straight forward but I can share that if you're interested.

    Thanks again
     

    Attached Files:

    • s1.png
      s1.png
      File size:
      957.2 KB
      Views:
      1,144
    • s2.png
      s2.png
      File size:
      1.8 MB
      Views:
      1,067
  3. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula
    I am also facing problem in ios. Android is working good but having problem in ios.
    Can u share the script for same (download Videos) in IOS. I am using same i.e


    1. private IEnumerator VideoAndSave()
      {
      yield return new WaitForEndOfFrame();

      string oriPath = Application.persistentDataPath+"/introvideo.mp4";

      Debug.Log("Success" + NativeGallery.SaveVideoToGallery (oriPath, "GalleryTest", "Demo.mp4" ));
      }
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @Rlapham At line 322 of NativeGallery.mm, try changing UIPopoverArrowDirectionAny to
    UIPopoverArrowDirectionDown or UIPopoverArrowDirectionUp, e.g:

    [popup presentPopoverFromRect:CGRectMake( rootViewController.view.frame.size.width / 2, rootViewController.view.frame.size.height / 4, 0, 0 ) inView:rootViewController.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];


    I am not very familiar with Objective-C and that popup code was mostly a copy-paste, so this may not work but let's see, shall we :)

    P.S. You can of course share your VideoPlayer solution here for reference, thank you!

    P.P.S. If changing UIPopoverArrowDirectionAny doesn't work, please give this one a shot, as well (reference: https://stackoverflow.com/a/34610948/2373034):

    [popup presentPopoverFromRect:CGRectMake( rootViewController.view.bounds.size.width / 2, rootViewController.view.bounds.size.height / 2, 1, 1 ) inView:rootViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
     
    Last edited: May 3, 2018
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @jeck001 Your code should work correctly on iOS. Are you sure that the spelling of introvideo.mp4 is correct and that the file is not located in a subfolder of StreamingAssets? I don't think this will change anything but try the following:

    string oriPath = System.IO.Path.Combine(Application.persistentDataPath,"introvideo.mp4");


    Otherwise, can you check the device logs to see if there is an error message there?

    EDIT: I misread persistentDataPath as streamingAssetsPath, sorry. Forget what I said about StreamingAssets.
     
    Last edited: May 3, 2018
  6. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula I am not able to save video in ios , But able to save in Android Please help

    Code (CSharp):
    1. private IEnumerator VideoAndSave()
    2.     {
    3.         yield return new WaitForEndOfFrame();
    4.  
    5.         string oriPath = Application.persistentDataPath+"/introvideo.mp4";
    6.  
    7.         Debug.Log("Success" + NativeGallery.SaveVideoToGallery (oriPath, "GalleryTest", "My Video {0}.mp4" ));
    8.     }
     
  7. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Checking
     
  8. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
  9. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    hi @yasirkula I am getting this error
    Download[434:41628] You are using download over http. Currently unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition, but it will be removed soon. Please consider updating to https.

    2018-05-03 17:49:05.382192+0530 Download[434:42085] NSURLConnection finished with error - code -1002

    ArgumentException: Parameter 'mediaBytes' is null or empty!

    at NativeGallery.SaveImageToGallery (System.String existingMediaPath, System.String album, System.String filenameFormatted, .MediaSaveCallback callback) [0x00000] in <filename unknown>:0

    at CallSave+<SaveToGalleryCoroutine>c__Iterator0.MoveNext () [0x00000] in <filename unknown>:0

    at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0



    (Filename: currently not available on il2cpp Line: -1)
     
  10. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Probably the download got interrupted/canceled (NSURLConnection finished with error - code -1002) and returned a null value. Then passing this null to SaveImageToGallery function threw an ArgumentException. You should first check if the download was successful.

    Regarding the video save issue, try logging the following to the console before calling the SaveVideoToGallery function:

    Debug.Log( oriPath + " " + System.IO.File.Exists( oriPath ) );

    And again, please check the console for error messages. I don't have an Xcode project right now but in the very worst case, I'll send you a working one.
     
  11. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    @yasirkula I am using Unity5.6.2 . Should i update unity version?
     
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    It's not necessary; I'm also using Unity 5.6.2.
     
  13. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    Hi @yasirkula I am using Vuforia may b manifest files are Conflicting Please Support.
     
  14. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I don't think so because otherwise it wouldn't compile in the first place. Again, are there no error messages in the Console (in Xcode)? These console logs are very important, please do check them for error messages. What happens when you try to save the video to Photos? Does the app crash, freeze, or keep running as usual? Does NativeGallery.SaveImageToGallery also not work?
     
  15. jeck001

    jeck001

    Joined:
    Aug 12, 2016
    Posts:
    12
    I am able to do in IOS by using
    Code (CSharp):
    1. Application.streamingAssetsPath
    instead of
    Code (CSharp):
    1. Application.persistentDataPath
    But now i have added Vuforia and now not able to save video in Android

    Not yet tested in IOS.
     
  16. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Always make sure the video does exist at that path. Use File.Exists and see if it returns true. And keep an eye on Xcode Console on iOS and Logcat on Android. If something goes wrong, there is a high chance that there will be an error message there.
     
  17. Rlapham

    Rlapham

    Joined:
    Dec 5, 2016
    Posts:
    5
    I thought I'd share a function that instantiates a video player (from a public prefab) and plays a video chosen from the camera roll in case it helps anyone.

    One note: this will work exactly once, I'm still trying to figure out why. Any ideas is much appreciated!

    Note 2: "DistanceToCamera" is a global variable - I believe I set mine to 15.0f.

    Code (CSharp):
    1. public void PickVideo2()
    2. {
    3. NativeGallery.Permission permission = NativeGallery.GetVideoFromGallery( ( path ) =>
    4. {
    5.     Debug.Log( "Video path: " + path );
    6.     if( path != null )
    7.     {
    8.         // Play the selected video
    9.         // Handheld.PlayFullScreenMovie( "file://" + path );
    10.         Vector3 position = cam.transform.forward * DistanceToCamera + cam.transform.position;
    11.         GameObject obj = (GameObject)Instantiate(vidObj, position, Quaternion.identity);
    12.         obj.transform.rotation = Camera.main.transform.rotation;
    13.         obj.transform.Rotate(90, -90, 90);
    14.  
    15.         videoPlayer = obj.GetComponent<VideoPlayer> ();
    16.         videoPlayer.waitForFirstFrame = true;
    17.         videoPlayer.playOnAwake = true;
    18.  
    19.         videoPlayer.url = "file://" + path;
    20.         Debug.Log( "video url: " + videoPlayer.url );
    21.         Debug.Log( "video path: " + path);
    22.  
    23.  
    24.         obj.transform.localScale = new Vector3( 1f, videoPlayer.texture.height / (float) videoPlayer.texture.width, 1f );
    25.     }
    26.  
    27.     if( path == null ){
    28.         Debug.Log( "path is null big time" );
    29.  
    30.     }
    31. }, "Select a video" );
    32.  
    33. Debug.Log( "Permission result: " + permission );
    34. }
     
    yasirkula likes this.
  18. calebbbarton

    calebbbarton

    Joined:
    Mar 20, 2018
    Posts:
    11
    Hi, thanks for your constant responses OP.

    When using GetImageFromGallery, is there any way to exclude .gifs from appearing? I can see the mime "image/*" in the options, but am unsure how to use it to exclude a filetype.

    Thanks.
     
  19. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    AFAIK, it is not possible. But the NativeGallery.LoadImageAtPath function should be able to load the first frame of a gif as a Texture2D, if it would be of any help.
     
  20. inancatil

    inancatil

    Joined:
    Dec 9, 2016
    Posts:
    13
    Hi, thanks for the great asset!

    Is there any way to assign selected images to texture list asynchronously? I would like to be able to choose more than 100 images and show them in raw images. Following code works but it lags until it finishes converting images to textures.

    Code (CSharp):
    1. private Texture2D texture;
    2. public List<Texture2D> AllTextures;
    3.  
    4. private IEnumerator FillList()
    5. {
    6.  
    7.     isGenerating = false;
    8.     for (int i = 0; i < imgPathList.Count; i++)
    9.     {
    10.         texture = NativeGallery.LoadImageAtPath(imgPathList[i], 1024);
    11.         AllTextures.Add(texture);
    12.  
    13.         if (!isGenerating)
    14.         {
    15.             isGenerating = true;
    16.             StartCoroutine(GenerateImages());
    17.         }
    18.  
    19.         yield return new WaitForEndOfFrame();
    20.     }
    21. }
     
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    NativeGallery.LoadImageAtPath ultimately uses Texture2D.LoadImage, which AFAIK must run on the main thread. Maybe adding an extra "yield return null;" inside the for loop will make it less laggy but in the end, you'll probably have to use external textures for a completely async experience.
     
  22. inancatil

    inancatil

    Joined:
    Dec 9, 2016
    Posts:
    13
    Thanks for the answer. Do you know if it is possible to use async-await ? I tried and it forced close but maybe i did something wrong.
    Another question is that when i load texture as raw image it loses its aspect ratio. I tried to convert to sprite and it kept ratio however creating sprite is even more cpu heavy so i would like to use raw image.

    Thanks in advance
     
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I haven't used async-await in Unity, sorry.

    Probably you were assigning the sprite to an Image with Preserve Aspect selected, which fits the image inside the RectTransform while preserving its aspect ratio. For RawImage, you will have to change the size of the RectTransform manually. For example:

    Code (CSharp):
    1. Vector2 size = rawImage.rectTransform.sizeDelta;
    2. size.y = size.x * texture.height / (float) texture.width;
    3. rawImage.rectTransform.sizeDelta = size;
     
    nikosurfing likes this.
  24. inancatil

    inancatil

    Joined:
    Dec 9, 2016
    Posts:
    13
    Thanks for the reply but I couldnt make it work. My phone takes, for example, 4032 x 3024 photo. When unity load this image into Texture2D variable, its width and height is set to 2048. If i convert it to sprite, it sets to 2048 x 1536. How can i achieve the same resolution with texture2d so later i can assign it to raw image?
     
  25. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    That's unexpected. Are you using texture.width and texture.height and getting 2048 each? I'd tested the PickImage function from the Example Code on several devices and image aspect ratio was always preserved. Maybe aspect ratio is not preserved when the image is too big. Try the following function to load the texture:

    NativeGallery.LoadImageAtPath( path, 1024 );


    If it works, try increasing 1024 to 2048.
     
  26. inancatil

    inancatil

    Joined:
    Dec 9, 2016
    Posts:
    13
    I am already using that code. I think the problem is at Unity side. I uploaded the original picture and what unity shows when I select the image on editor.
     

    Attached Files:

    • unity.png
      unity.png
      File size:
      62.1 KB
      Views:
      1,021
    • org.jpg
      org.jpg
      File size:
      3.4 MB
      Views:
      928
  27. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    For NPOT texture assets, you have to set the value of "Non Power of 2" to None in the Inspector. But it will increase the texture size drastically. Runtime textures (e.g. loaded via NativeGallery.LoadImageAtPath) already have their "Non Power of 2" set to None, so you shouldn't have this issue when loading images runtime.
     
  28. inancatil

    inancatil

    Joined:
    Dec 9, 2016
    Posts:
    13
    Thanks a lot, it is working now. I needed to see in editor to adjust the sizes. Your code to keep aspect ratio is also working
     
  29. imran3

    imran3

    Joined:
    Oct 4, 2015
    Posts:
    1
    Hi,
    first of all, thanks for your library. It saved us a lot of hours and is working pretty fine :)
    I just have one question: is it possible to open the Gallery in Landscape (horizontal) mode instead of Vertical?
    The app we are developing is designed for landscape mode and the Gallery open us in vertical by default and is not really user-friendly this way.

    :)
     
  30. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  31. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    158
    Great plugin! Could you please tell, is there way to open saved image at gallery? I mean open the final image at its path via gallery
     
  32. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Following code might work for versions before Android N (7.0):

    Code (CSharp):
    1. // Credit: https://github.com/ChrisMaire/unity-native-sharing/blob/master/Assets/Plugins/NativeShare.cs
    2. // Credit: https://stackoverflow.com/a/6772455/2373034
    3. public void ShowImageInGallery( string imagePath )
    4. {
    5.     using (AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"))
    6.     using (AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent"))
    7.     {
    8.         using (intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_VIEW")))
    9.         { }
    10.        
    11.         string mime = "image/*";
    12.         string pathLower = imagePath.ToLowerInvariant();
    13.         if( pathLower.EndsWith( ".jpeg" ) || pathLower.EndsWith( ".jpg" ) )
    14.             mime = "image/jpeg";
    15.         else if( pathLower.EndsWith( ".png" ) )
    16.             mime = "image/png";
    17.        
    18.         using (AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri"))
    19.         using (AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse", "file://" + imagePath))
    20.         using (intentObject.Call<AndroidJavaObject>("setDataAndType", uriObject, mime))
    21.         { }
    22.        
    23.         // finally start application
    24.         using (AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    25.         using (AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity"))
    26.         {
    27.             currentActivity.Call("startActivity", intentObject);
    28.         }
    29.     }
    30. }
    Android 7.0 and later requires using a ContentProvider for sharing file uris with other apps. This makes things very complicated in Unity, so I won't be explaining a solution for that.
     
    DrViJ likes this.
  33. DrViJ

    DrViJ

    Joined:
    Feb 9, 2013
    Posts:
    158
    Thank you so much, now I understand what caused the problem of unavailability to open an image in gallery. I am not good at Android and didnt know about providers, Now thats ok, that is my solution, based on yours:

    Code (CSharp):
    1.         AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    2.         AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    3.         AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");
    4.  
    5.         string packageName = unityContext.Call<string>("getPackageName");
    6.         string authority = "com.sponte.patterns.contentprovider";
    7.         AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", mLastSavedFile);
    8.         AndroidJavaClass fileProvider = new AndroidJavaClass("com.yasirkula.unity.UnitySSContentProvider");
    9.         AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", unityContext, authority, fileObj);
    10.  
    11.         AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
    12.         AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
    13.         int FLAG_GRANT_READ_URI_PERMISSION = intentObject.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");
    14.         intentObject.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION);
    15.         intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_VIEW"));
    16.         intentObject.Call<AndroidJavaObject>("setDataAndType", uri, "image/*");
    17.  
    18.         currentActivity.Call("startActivity", intentObject);
    19.  
    20.         unityPlayer.Dispose();
    21.         currentActivity.Dispose();
    22.         unityContext.Dispose();
    23.         fileObj.Dispose();
    24.         fileProvider.Dispose();
    25.         intentClass.Dispose();
    26.         intentObject.Dispose();
    And that is a part of manifest I used:

    <provider
    android:name="com.yasirkula.unity.UnitySSContentProvider"
    android:authorities="com.sponte.patterns.contentprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    </provider>
     
    yasirkula likes this.
  34. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    That's a clever solution, well done :)
     
  35. jakks

    jakks

    Joined:
    Aug 23, 2017
    Posts:
    2
    Yasirkula, thanks for the plugin.

    I have a question though. When I imported this plugin, somehow it messes up my sharing functionality when I press a button to call method 'Share' on Line 39 (https://pastebin.com/YfssnpZz). It won't do anything. My biggest issue here is I dont' have Android device to test to see debug.log. Do you have any clue?
     
  36. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    I couldn't spot any problematic lines in your code. To be honest, NativeGallery shouldn't break other plugins, it doesn't have any dependencies and it just works on its own. I'm afraid you'll have to check the logs, when you get the chance.
     
  37. jakks

    jakks

    Joined:
    Aug 23, 2017
    Posts:
    2
    Thank you so much.
     
  38. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    Started to use this asset because it should provide path to selected image, while most other asset just return texture. I wished to keep that path and load image on iOS app start. The idea is to cache selected images paths and use them when needed without duplicating it to app assets folder.
    Nevertheless I checked the path returned by GetImageFromGallery method, and it looks like that
    Code (CSharp):
    1. /var/mobile/Containers/Data/Application/........../Library/Caches/tmp.png
    Seems it's not a direct path to library but just cached temporary copy.
    Is there a way to get direct path to reach my goal?
     
  39. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    On iOS, returned path doesn't point to the original image file (unlike Android) because AFAIK, this is not possible; the image is stored in an internal directory. Even if we had the actual path, trying to access the file would probably throw a security exception.

    I'd suggest you to move the returned image file to Application.persistentDataPath and cache its path, instead.
     
  40. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    Ok, it's clear now. I thought it is possible somehow :)
     
  41. shuaibimran

    shuaibimran

    Joined:
    Sep 10, 2014
    Posts:
    7
    Hi Yasirkula,
    I am using your library for my unity android game but I am facing some problems:

    Actually, I am trying to take a screenshot and save it into the Android gallery, I am using a opensource library for this purpose "Unity Native Gallery" my code is following:

    NativeGallery.Permission permission = NativeGallery.CheckPermission();
    if (permission == NativeGallery.Permission.Granted) {
    Debug.Log("May proceed");
    }
    else {
    Debug.Log("Not allowed");
    }

    Debug.Log("Path is "+NativeGallery.GetSavePath("GalleryTest","My_img_{0}.png"));
    //Output ==> /storage/emulated/0/DCIM/GalleryTest/My_img_1.png

    Texture2D ss = new Texture2D( Screen.width, Screen.height, TextureFormat.RGB24, false );
    ss.ReadPixels( new Rect( 0, 0, Screen.width, Screen.height ), 0, 0 );
    ss.Apply();

    Debug.Log("Secondlast");
    permission = NativeGallery.SaveImageToGallery( ss, "GalleryTest", "My_img_{0}.png" ) ;

    Debug.Log("Done screenshot");

    but my it never save the screenshot, when i see the console, I get 2 important logs

    1.My Debug log "SecondLast" was print on the console but not the last one "Done screenshot"

    2.There is an exception printed "UnauthorizedAccessException: Access to the path "/storage/emulated/0/DCIM/GalleryTest/My_img_1.png" is denied."

    Important point :- I already set the Write permissions to External (SDCard) in unity player settings. (actually I try with both settings "Internal" and "External")
     
  42. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    This is the first time I see UnauthorizedAccessException while trying to access DCIM folder with the External Storage permission granted. If your phone was connected to your PC while testing, can you try it again while it is disconnected? Out of curiosity, can you also try using the TakeScreenshotAndSave function of the example code and see if it works correctly: https://github.com/yasirkula/UnityNativeGallery#example-code

    P.S. If you navigate to the DCIM folder using the file browser of your device, can you verify that there is a folder named "GalleryTest"?
     
  43. shuaibimran

    shuaibimran

    Joined:
    Sep 10, 2014
    Posts:
    7
    I already did try your example code. But the main problem which I am thinking is: I never ever see a permission dialog. I didn't know that the permission dialog must be appear, As I am iOS developer and don't know much about android, Now one of my friend tell me that the dialog must be appear once. Is he right or wrong ?
     
  44. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    The permission dialog should automatically appear until you either grant the permission or deny the permission with "Don't ask again" selected. But for the permission dialog to appear, WRITE_EXTERNAL_STORAGE permission must be declared in AndroidManifest (it is declared automatically when Write permission is set to "External (SDCard)".

    You can verify that WRITE_EXTERNAL_STORAGE is declared in your manifest by navigating to UNITY_PROJECT_PATH/Temp/StagingArea/AndroidManifest.xml after building your project to Android.

    BTW, If you change your Debug.Log to Debug.Log("Secondlast " + permission), what does it print to the console?

    NOTE: Permission dialog only appears on Android 6.0 and later. On older devices, it is sufficient to declare WRITE_EXTERNAL_STORAGE in the manifest.
     
  45. shuaibimran

    shuaibimran

    Joined:
    Sep 10, 2014
    Posts:
    7
    My device's OS version is 5.1.1
    Here are the permissions mentioned in my Project/Temp/StagingArea/AndroidManifest.xml

    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="27" />
    <uses-feature android:glEsVersion="0x00020000" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
    <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />

    and log result becomes "Secondlast Granted"
    but on the next line output is ' E/Unity (21884) : UnauthorizedAccessException: Access to the path "/storage/emulated/0/DCIM/GalleryTest/My img 1.png" is denied.'
     
  46. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Honestly, everything looks fine to me. Can you check whether or not GalleryTest directory is created in /storage/emulated/0/DCIM folder? If it doesn't exist, please check both internal and external drive to see if it is created in a wrong drive.
     
  47. shuaibimran

    shuaibimran

    Joined:
    Sep 10, 2014
    Posts:
    7
    Yes . On OS 5.1.1 the GalleryTest directory has been created but not image inside it.

    Now I run my project on OS version 7.0, It behaves differently. When I install the project on the device a permission popup appears with text "Allow ProjectA to access photos, media and files on your device?" I tapped on the Allow but when I call the take screenshot function console show logs. (I repeat this process 3 times 'Install and tap on the Allow')

    my code lines are
    Debug.Log("Permissions are "+permission);
    Debug.Log( "Permission result: " + NativeGallery.SaveImageToGallery( ss, "GalleryTest", "My img {0}.png" ) );

    and out is
    1.Permissions are ShouldAsk
    2.Permissions result Denied

    I think it can help to find the problem?
     
  48. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    When you navigate to Settings-YOUR_APP, what is the value of Storage permission? If you test the example code on a new project (change only Bundle Identifier and Write Permission settings after creating the project), does it still not function?
     
  49. NatsupyYui

    NatsupyYui

    Joined:
    Jul 11, 2017
    Posts:
    18
    Can you add the option audio for full feature media? This's awesome
    //edit: I tried with audio, and works ok.
     
    Last edited: Jul 7, 2018
  50. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Did you mean saving/loading audio to device? And it works out-of-the-box? That's surprising news, but not unwelcome, lol.