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

WebCamTexture on Android, focus mode fix

Discussion in 'Android' started by Endless-Cat, May 24, 2015.

  1. Endless-Cat

    Endless-Cat

    Joined:
    Oct 20, 2014
    Posts:
    2
    I am integrating bar-code scanning into my project and tried WebCamTexture as a way of cross-platform accessing the camera of devices. When it comes to camera focusing on Android the things are bad, camera is out of focus and there is no way to switch on the macro mode, or trigger a refocus.

    This problem manifested itself here
    http://stackoverflow.com/questions/19076316/how-to-ask-webcam-to-auto-focus-with-unity3d
    and here http://feedback.unity3d.com/suggestions/better-webcamtexture


    So, inspired by StackOwerflow link above I wrote an Android plugin, although it is not that simple. You cannot call Camera.open() because Unity already opened the camera and there is no way to get instance of it inside Unity player on Android. Or there is one?

    It is, but is is hacky as hell. I noticed that com.unity3d.player.UnityPlayer has a static field called "currentActivity" used in many plugins and started digging some sources we have (Activities) and reverse-engineering classes.jar for any traces of camera management inside. Here is the code

    Code (CSharp):
    1.    
    2. void CrazyFocusPocus()
    3.     {
    4.  
    5.         // Get activity instance (standard way, solid)
    6.         var pl_class = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    7.         var currentActivity = pl_class.GetStatic<AndroidJavaObject>("currentActivity");
    8.  
    9.         // Get instance of UnityPlayer (hacky but will live)
    10.         var pl_inst = currentActivity.Get<AndroidJavaObject>("mUnityPlayer");
    11.  
    12.         // Get list of camera wrappers in UnityPlayer (very hacky, will die if D becomes C tomorrow)
    13.         var list = pl_inst.Get<AndroidJavaObject>("D");
    14.         x = list.Call<int>("size");
    15.  
    16.         if (x == 0) return;
    17.  
    18.         // Get the first element of list (active camera wrapper)
    19.         var cam_holder = list.Call<AndroidJavaObject>("get", 0);
    20.  
    21.         // get camera (this is totally insane, again if "a" becomes not-"a" one day )
    22.         var cam = cam_holder.Get<AndroidJavaObject>("a");
    23.  
    24.         // Call my setup camera routine in Android plugin  (will set params and call autoFocus)
    25.         var jc = new AndroidJavaClass("org.example.ScriptBridge.JavaClass");
    26.         jc.CallStatic("enableAutofocus", new[] { cam });
    27.  
    28.     }
    29.  
    Don't try this at home! Names (list "D", wrapper "a", its field "a" can and will change at some point).

    Now I address you, guys at Unity team who work on Android part. Pardon me for invading into the private section of Unity ;).

    Are my guesses about the camera code correct or it will explode at some point?
    More importantly, is there any way to do it in a less tricky manner?
    And if not, can I expect some API appear or parts of Android player opened at some point?

    Something like public static Camera getRunningCamera() will do the trick, but this is an open discussion. The benefits of this approach are that developers with enough Android skills will be able to do more customization on player, because I understand that asking to wrap the whole Android Camera functionality (focus, flash, etc) in WebCamTexture is insane.

    Thank you for reading this long posting, looking forward for your thoughts on this.
     
  2. Schick

    Schick

    Joined:
    Aug 18, 2015
    Posts:
    9
    Indeed, this is crazy. But it seems to be the only way to access the camera.

    Thanks for the snippet. Let me check if this code is about to explode.
     
  3. Cromfeli

    Cromfeli

    Joined:
    Oct 30, 2014
    Posts:
    202
    I am also very interested in this. Please report back if you found a better / more reliable way. or even some updates on the current approach!
     
  4. lumacode

    lumacode

    Joined:
    Mar 25, 2014
    Posts:
    8
    Thanks for figuring this out.

    For people trying this, D is now y so:

    var list = pl_inst.Get<AndroidJavaObject>("D");

    becomes

    var list = pl_inst.Get<AndroidJavaObject>("y");

    Also you need to call this after you've created your WebcamTexture.

    Crazy that this sort of hack is needed to set Camera Parameters on Android...
     
  5. RegisDeToni

    RegisDeToni

    Joined:
    Jul 11, 2013
    Posts:
    10
    HI, cant make this work. Can you give away a full project working?
     
  6. UltimateWalrus

    UltimateWalrus

    Joined:
    Jul 19, 2014
    Posts:
    10
    This hack looks awesome, and it'd be great if I could use it. However, something's not right on this line:

    pl_inst.Get<AndroidJavaObject>("y");

    This seems to now return an Android "Bundle" class, rather than the List the code seems to expect, resulting in an exception when a call to "get" is attempted.

    I also tried the old "D" but that just throws an exception.

    Would you guys mind sharing how you figured out these arbitrary member names? Is there a java file I'm missing somewhere, in which the UnityPlayer class is defined?

    Thanks!
     
    Cromfeli likes this.
  7. jgb143

    jgb143

    Joined:
    Jun 8, 2010
    Posts:
    132
    You also can't turn on the camera flash for the same reason (camera with no flash???). Would it be possible to use this trick to get around that limitation?
     
  8. moshebitan

    moshebitan

    Joined:
    Nov 13, 2013
    Posts:
    3
    Is there any way we can use that to improve the frame rate from 30fps to 60fps?
     
  9. moshebitan

    moshebitan

    Joined:
    Nov 13, 2013
    Posts:
    3
    There is a method called setPreviewFrameRate we use it?
     
    sstadelman likes this.
  10. tolstenko

    tolstenko

    Joined:
    May 31, 2012
    Posts:
    14
    Any updates? Is this object "y" still working on unity 5.3.1? I am facing this problem too. I need to set some parameters manually. Is this the only way? On iOS was easier to me. I just created a plugin that calls the function: setFocusModeLockedWithLensPosition:completionHandler: and worked fine for the iOS version of the unity app.
     
    sstadelman likes this.
  11. tolstenko

    tolstenko

    Joined:
    May 31, 2012
    Posts:
    14
    Shame on you Unity guys :/ I am trying right now to decompile your jar class to find the way to access the android camera. This is far away from a good solution. Please just expose the var in some intelligible way. We will do the rest, we dont need all camera functions, just some valid pointer to the camera instance.
     
  12. sstadelman

    sstadelman

    Joined:
    Dec 17, 2013
    Posts:
    12
    Slightly tangential question for experts on this thread: does anyone know the location of the source of WebCamTexture?
     
  13. Niguerra

    Niguerra

    Joined:
    Jul 7, 2013
    Posts:
    1
    Seriusly guys ? After all this time !

    I choose Unity to develop my Android projects, but I can even access Android camera :/
     
  14. Troutmonkey

    Troutmonkey

    Joined:
    Jun 11, 2014
    Posts:
    7
    Any update on this? Have been struggling to find a workaround for months.
     
  15. ijoing_TW

    ijoing_TW

    Joined:
    Oct 3, 2016
    Posts:
    1
    "y" did not work on version "5.4.1f1" anymore. it changed to "m".
     
    Cromfeli likes this.
  16. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,306
    Wow, I can't believe this is what we have to do.

    Unity, please just add a function to get the current camera if one. Or better yet, allow us to set the focus mode.
     
  17. softarn88

    softarn88

    Joined:
    Jan 3, 2016
    Posts:
    1
    Last edited: Jan 24, 2017
  18. HamFar

    HamFar

    Joined:
    Nov 16, 2014
    Posts:
    89
    Hi all, Has anybody got this fully working, to access the camera and set the focus? I have the exact same problem in the same area (OCR scanning) and since I use a WebCamTexture, there is no focus. I came across this, so I tried to implement it in my Unity app, but I am struggling with it, because the new Android Camera API has changed a lot. I wonder if you could help me with this?
     
  19. HamFar

    HamFar

    Joined:
    Nov 16, 2014
    Posts:
    89
    @lumacode
    Hi! You mention in your post "you need to call this after you've created your WebcamTexture" meaning you have fully implemented this and can set Android camera focus with it? Have you successfully done this?
     
  20. DeveshPandey

    DeveshPandey

    Joined:
    Sep 30, 2012
    Posts:
    221
    Hi guys,

    Any legal updates on this?
     
  21. neshius108

    neshius108

    Joined:
    Nov 19, 2015
    Posts:
    110
    Has anyone managed to get the torch on while previewing with this lovely hack? :D
     
    jacobgmartin likes this.