Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Android camera focus with Unity3D WebCamTexture

Discussion in 'Android' started by drhmiri, Jun 16, 2017.

  1. drhmiri

    drhmiri

    Joined:
    Jun 17, 2014
    Posts:
    82
    When using WebCamTexture in Unity3D (and then building and deploying to Android) the camera does not focus correctly, which becomes a big problem when developing apps that scan QR codes or perform OCR.

    Currently, there seems to be no way to focus the device camera on Android from within Unity3D, but there are a few posts that suggest you can force Android auto-focus by creating an Android Java plug-in for Unity3D which sets auto-focus and then calls it from within a C# script of your Unity3D project.

    Inspired by the existing posts, I set out to do exactly this in Android Studio and put an end to it once and for all! (twice actually -- once with Blank Activity and once with No Activity. Which one should be used for plug-in development?)

    What I have so far is as follows, though it does not seem to be working at all. I wonder if yould would take a look and make suggestions, or better still give it a try and help me understand what I am missing or doing wrong. It is very easy to follow what I have done...

    I would very much welcome and appreciate any help or hint, as this has consumed me for a while now. I have also included little questions in my code comments if you would also address those please.

    I wrote the following code in Android Studio, while following this tutorial:

    Code (CSharp):
    1.  
    2. package com.example.unityplugin;
    3.  
    4. import java.util.List;
    5. import android.hardware.Camera;
    6. import android.util.Log;
    7.  
    8. public class OcrFocusPluginClass
    9. {
    10.     public static void EnableAutofocus()
    11.     {
    12.         System.out.println("Entered the method...");
    13.  
    14.         Camera camera = Camera.open();
    15.         Camera.Parameters parameters = camera.getParameters();
    16.  
    17.         List<String> focusModes = parameters.getSupportedFocusModes();
    18.  
    19.         if ( focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO) )
    20.         {
    21.             parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    22.  
    23.             Log.i("app", "camera focus set");
    24.         }
    25.  
    26.         camera.setParameters(parameters);
    27.     }
    28. }
    29.  
    30. // I have tried all 3 modes:
    31. // FOCUS_MODE_AUTO
    32. // FOCUS_MODE_CONTINUOUS_PICTURE
    33. // FOCUS_MODE_CONTINUOUS_VIDEO
    34.  
    The following is the C# script in my Unity3D project that calls the built library; the outcome of building the above in Android Studio and making a Module out of it:

    Code (CSharp):
    1.  
    2. public class OcrAndroidFocus : MonoBehaviour
    3.     {
    4.         public static void Focus()
    5.         {
    6.             #if UNITY_ANDROID
    7.             try
    8.             {
    9.                 using ( AndroidJavaObject androidJavaObject = new AndroidJavaObject("com.example.unityplugin.OcrFocusPluginClass") ) // AndroidJavaObject or AndroidJavaClass ?
    10.                 {
    11.                     if (androidJavaObject != null)
    12.                     {
    13.                         androidJavaObject.CallStatic("EnableAutofocus"); // .Call or .CallStatic ?  Do I also need <void> return type ?
    14.                         Debug.Log("androidJavaObject != null success!");
    15.                     }
    16.                 }
    17.             }
    18.             catch (Exception e)
    19.             {
    20.                 Debug.LogException(e);
    21.             }
    22.             #endif
    23.         }
    24.     }
    25.  
    In another Unity3D C# script in the same name space, I have the following method that creates the texture and calls the jar file's method:

    Code (CSharp):
    1.  
    2. public void StartWebcam()
    3.         {
    4.             if (!_isRunning)
    5.             {
    6.                 _webCamTexture = new WebCamTexture();
    7.                 gameObject.GetComponent<RawImage>().texture = _webCamTexture;
    8.  
    9.                 OcrAndroidFocus.Focus(); // Do I need to cancel this at some point?
    10.  
    11.                 _webCamTexture.Play();
    12.                 _isRunning = true;
    13.             }
    14.         }
    15.  
    Of course, I have the following in my AndroidManifest.xml

    Code (CSharp):
    1.  
    2.     <uses-permission android:name="android.permission.CAMERA"/>
    3.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
    4.     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    5.     <uses-permission android:name="android.permission.INTERNET"/>
    6.  
    7.     <uses-feature android:glEsVersion='0x00020000'/>
    8.     <uses-feature android:name="android.hardware.camera" android:required="true"/>
    9.     <uses-feature android:name="android.hardware.camera.autofocus" android:required="true"/>
    10.     <uses-feature android:name="android.hardware.camera.front" android:required="true"/>
    11.  
    Although, at this point, I must admit that this manifest exists (from before) in my Unity3D project's Assets/Plugins/Android though the tutorial (the link I put in the beginning of this post) told me to place the resulting classes.jar file and AndroidManifest.xml files in Assets/Plugins/Android/libs which I have done so. Is this right?

    So... I build my Unity3D app for Android but when I start it on a Galaxy tablet, I notice nothing different...

    Could someone please test this and see perhaps I missed a step or maybe I am doing something wrong? Please let me know if I can provide more info in this post to facilitate a solution at the end. It seems that from the time of this post/petition and this petition/post which go as far back as April 2014, the WebCamTexture is still problematic on Android.

    Many thanks in advance,
     
    Last edited: Jun 16, 2017
  2. WiliHert

    WiliHert

    Joined:
    Jul 26, 2017
    Posts:
    1
    this way can't solve the problem,i have try to do it like this two mouths again.we use unity's webcamtexture to capture camera,but it can't set focus on Samsung devices. maybe this plugin (https://www.assetstore.unity3d.com/en/#!/content/56083)can help in assetstore. this plugin supports autofocus by publisher native camera tool,hope can help you.
     
    drhmiri and HamFar like this.
  3. Zazery

    Zazery

    Joined:
    Jul 9, 2013
    Posts:
    3
    I'm also trying to figure this out. From this thread it seems you need to access the camera UnityPlayer already has open instead of opening a new camera. I've tried decompiling classes.jar from Unity 5.6.2f1 to search for the appropriate class but was unable to find a reference to android.hardware.camera. The 'm' class contains code for the media player, which isn't the same.
     
    drhmiri likes this.