Native Camera for Android & iOS [Open Source]

If your main project uses ProGuard minification in Player Settings, you should add the following line to the ProGuard filters: -keep class com.yasirkula.unity.* { *; }. Let me know if your project uses a minification other than None and ProGuard.

Otherwise, assuming that both projects have Write Permission set to “External (SDCard)” and have the same AndroidManifest.xml files at exactly the same places, this issue shouldn’t occur.

I created empty project and included both plugins (Native Camera and UnimgPicker). Worked like a charm. No idea why it doesn’t work in my main project. Is it possible that I have a conflict with Firebase or Playfab? Since the Firebase files are in the Android catalogue before I put the Android Manifest there, could they create a conflict?
When the Android Manifest file is not there, build and run works perfect. When I put it in the Android catalogue (which already contains Firebase) the app builds successfully, but won’t install :frowning: I’m a bit desperate…

Was able to track the issue:
After adding your AndroidManifest i get this:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]

I think it solves it… I feel stupid now :slight_smile:

Try changing the value of your android:authorities string.

Thank you, already did it, works like a charm :slight_smile: Anyway, I have last question haha Sorry for bothering you so much :frowning:
I wanted to ask you about the best way to save the photo. I mean I have the code to save it on Android but it doesn’t work in this case.

private void TakePicture( int maxSize )
{
NativeCamera.Permission permission = NativeCamera.TakePicture( ( path ) =>
{
Debug.Log( "Image path: " + path );
if( path != null )
{
// Create a Texture2D from the captured image
cacheTexture = NativeCamera.LoadImageAtPath( path, maxSize );

if( cacheTexture == null )
{
Debug.Log( "Couldn’t load texture from " + path );
return;
}

SaveImageToGallery(cacheTexture, “test”, “test”);

}
}, maxSize );

Debug.Log( "Permission result: " + permission );

}

public string SaveImageToGallery(Texture2D texture2D, string title, string description)
{
using (var mediaClass = new AndroidJavaClass(MediaStoreImagesMediaClass))
{
using (var cr = Activity.Call(“getContentResolver”))
{
var image = Texture2DToAndroidBitmap(texture2D);
var imageUrl = mediaClass.CallStatic(“insertImage”, cr, image, title, description);
return imageUrl;
}
}
}

public AndroidJavaObject Texture2DToAndroidBitmap(Texture2D texture2D)
{
byte[ ] encoded = texture2D.EncodeToPNG();
using (var bf = new AndroidJavaClass(“android.graphics.BitmapFactory”))
{
return bf.CallStatic(“decodeByteArray”, encoded, 0, encoded.Length);
}
}

I also tried doing simply:

imgBytes = texture.EncodeToPNG();
var dirPath = Application.persistentDataPath;
File.WriteAllBytes(dirPath + “Image” + “.png”, imgBytes);

But it saved empty png :frowning:

I managed to solve it by writing this function (where _imgPath = path). Hope it will help someone in the future :):

public void QuickSave(){
if(!String.IsNullOrEmpty(_imgPath)) {
imgBytes = File.ReadAllBytes(_imgPath);
cacheTexture = new Texture2D(2, 2);
cacheTexture.LoadImage(imgBytes);
SaveImageToGallery(cacheTexture, “testCache”, “test”);
}
}
Anyway, this solution is pretty simple and clean, but a bit slow :frowning:

1 Like

Or, you can simply copy the image at “path” to wherever you want via File.Copy. Nothing else can beat its speed. And you should use Path.Combine(dirPath, “Image.png”) to create paths, otherwise you’ll have to handle / and \ characters manually.

1 Like

Thank you, I will definitely try this!

Works great with Application.persistentpath but I have no idea how to copy it to
android.provider.MediaStore$Images$Media

Another thing that I can’t wrap my mind around is it seems to be impossible to adjust the aspect ratio of the image to the texture.
Works in every single scenario besides this:

private void TakePicture( int maxSize )
{
NativeCamera.Permission permission = NativeCamera.TakePicture( ( path ) =>
{
Debug.Log( "Image path: " + path );

_imgPath = path;

if( path != null )
{
// Create a Texture2D from the captured image
Texture2D texture = NativeCamera.LoadImageAtPath( path, maxSize );

if( cacheTexture == null )
{
Debug.Log( "Couldn’t load texture from " + path );
return;
}

//Getting the aspect ratio
float textH = texture.height;
float textW = texture.width;
Debug.Log("H: " + textH + " W: " + textW);

float aspectRation = textH > textW ? textH / textW : textW / textH;

output.GetComponent().aspectRatio = aspectRation;
output.texture = texture;

}
}, maxSize );

Debug.Log( "Permission result: " + permission );

}

You’ll need to do: float aspectRation = textH > textW ? (float) textH / textW : (float) textW / textH;

Also check out Native Gallery to easily save your images to Gallery: Native Gallery for Android & iOS [Open Source]

1 Like

Thank you for the response, unfortunately it didn’t work either :frowning:

Hi! I was testing a little bit with the Quality parameter of the RecordVideo. It doesn’t seem to change much, and the size of the video stays pretty much the same. Is this something that the device camera settings can override?

Some Android camera apps (even built-in camera apps) may not respect the parameters NativeCamera sends to them like quality, video length and etc. It is out of my control, unfortunately. So you shouldn’t 100% rely on them.

Hi yasirkula!
First of, thank you for all of your work not just this one, all are very useful!

I have few questions regarding NativeCamera:

  • Is there a way to take more than just one photo when Camera app is opened? Because, after one photo is shot, there is “retry” and “ok”. It would be great if there is possibility to shot photos as user want, then save them (example, with your NativeGallery to gallery) and when user is done with shooting there is a button to go back to Unity app (I know its impossible to put overlay on Camera app, but back button is enough for now).

  • I tried your example script with your NativeGallery and in Android build (I didn’t tried iOS build yet) images are rotated 90 degrees counterclockwise, is there are way to fix it that I missed inside these plug-ins?

Thank you very much once again!

1 Like

Hi!

  1. It is not possible, sorry. I have no control over the native camera app, even the screen with the retry and OK buttons is shown by the camera app. I regain control only after the camera is closed entirely. You’ll have to call TakePicture continuously inside TakePicture’s callback until the path is null (camera is closed with back button).

  2. If you are loading the image via LoadImageAtPath, that is not the expected behaviour. I think it is the first time I’m hearing about this issue on Android, though. Is this behaviour persistent across all your test devices?

Hi yasirkula!

Thank you for your quick reply.

  1. Oh that’s a real bummer. I have to think something out, it wont be user friendly if user have to tap accept for every photo (and user will have to make around 30 photos in my app). Thats a real bummer…

  2. Update for this problem. I tried on another device and it works fine as it should. So, on Xiaomi Mi 9T works fine, on Samsung S8 Plus is were the problem happens. Just so you know, the problem isn’t on quad in front of the camera (talking about your example script), it happens when you save it to gallery.

For 1), you’ll have to use a plugin that displays camera feed directly inside Unity and also supports capturing a photo with the camera. For example, this plugin might work for you but I haven’t tried it myself, so no guarantees.

  1. There are two SaveImageToGallery overloads: one takes “string path” parameter and the other takes “Texture2D texture” parameter. Can you try using the one you are not currently using and see if it changes anything? And for reference, which Android OS is your S8+ running on?
  1. That’s exactly what I was thinking, NatCam seems good enough for my purpose and a time cutter, I will give it a try.
  2. I tested it out, with “Texture2D texture” parameter it works as it should on S8+. On both devices is Android 9.

Thank you for your effort!

1 Like