1. Black Friday Sale - 50% off

    B4A Standard for $29 instead of $59!
    Buy Now
    Dismiss Notice

B4A Library Camera library v2.20

Discussion in 'Additional libraries, classes and official updates' started by Erel, Nov 28, 2012.

  1. Erel

    Erel Administrator Staff Member Licensed User

    The camera library was updated.
    It now also supports the front camera.

    There were several internal improvements required for the CameraEx class.

    Installation instructions:
    - Unzip the attached file and copy both files to the internal libraries folder.

    Edit:
    V2.20 is attached. Adds Camera.AutoFocus and Camera.CancelAutoFocus methods. CameraEx class was also updated and it includes a new FocusAndTakePicture method.
    V2.10 is attached. The camera management code was rewritten to fix stability issues.
     

    Attached Files:

    koaunglay likes this.
  2. Roger Garstang

    Roger Garstang Well-Known Member Licensed User

    I see now. Lately with all the issues with older versions then Honeycomb variations problems I restrict most of my apps to a minimum 2.3.3 (API 10), and tend to ignore Homeycomb and jump right to 4+ so a minimum 2.3 wouldn't be an issue with a Class for the 4+ stuff. Will the source code for this be released like it was for Camera1?
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    If anyone is interested then I will post it. It is slightly more complicated than the previous version. Note that in most cases it will be easier to add new methods through CameraEx class.
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    Here is the code:
    Code:
    @ActivityObject
    @Permissions(values={
    "android.permission.CAMERA"})
    @ShortName("Camera")
    @Version(2.01f)
    @Events(values={"Ready (Success As Boolean)", "PictureTaken (Data() As Byte)",
          "Preview (Data() As Byte)"})
    public class CameraW {
       @Hide
       public Camera camera;
       private static ConcurrentHashMap<Integer, Camera> closingCameras = new ConcurrentHashMap<Integer, Camera>();
       private SurfaceView sv;
       private String eventName;
       private BA ba;
       private int currentId;
       private AtomicInteger readyCount = new AtomicInteger();
       /**
        * Initializes the back camera.
        *Panel - The preview images will be displayed on the panel.
        *EventName - Events subs prefix.
        *The Ready event will be raised when the camera has finished opening.
        */
       public void Initialize(final BA ba, ViewGroup Panel, String EventName) {
          shared(ba, Panel, EventName, -1);
       }
       /**
        * Same as Initialize. CameraId is the id of the hardware camera.
        *<b>This method is only available from Android 2.3+.</b>
        */
       public void Initialize2(final BA ba, ViewGroup Panel, String EventName, int CameraId) {
          shared(ba, Panel, EventName, CameraId);
       }
       private void shared(final BA ba, ViewGroup Panel, String EventName, final int CameraId) {
          this.ba = ba;
          currentId = CameraId;
          readyCount.set(0);
          this.eventName = EventName.toLowerCase(BA.cul);
          sv = new SurfaceView(ba.context);
          anywheresoftware.b4a.BALayout.LayoutParams lp = new anywheresoftware.b4a.BALayout.LayoutParams(0, 0,
                Panel.getLayoutParams().width, Panel.getLayoutParams().height);
          Panel.addView(sv, lp);
          camera = closingCameras.get(CameraId);
          closingCameras.remove(CameraId);
          if (camera == null) {
             //release other cached cameras (relevant when switching cameras)
             synchronized (closingCameras) { //make sure that release is only called once.
                for (Camera c : closingCameras.values()) {
                   c.release();
                }
                closingCameras.clear();
             }
          }
          
          sv.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
          sv.getHolder().setFixedSize(Panel.getLayoutParams().width, Panel.getLayoutParams().height);
          sv.getHolder().addCallback(new SurfaceHolder.Callback() {

             @Override
             public void surfaceChanged(SurfaceHolder holder, int format,
                   int width, int height) {
             }

             @Override
             public void surfaceCreated(SurfaceHolder holder) {
                if (readyCount.addAndGet(1) == 2) {
                   ba.raiseEvent(null, eventName + "_ready", true);
                }
                
             }

             @Override
             public void surfaceDestroyed(SurfaceHolder holder) {

             }

          });
          ba.submitRunnable(new Runnable() {

             @Override
             public void run() {
                try {
                   if (camera == null) {
                      if (CameraId == -1)
                         camera = Camera.open();
                      else {
                         Method m = Camera.class.getMethod("open", int.class);
                         camera = (Camera)m.invoke(null, CameraId);
                      }
                   }
                   if (readyCount.addAndGet(1) == 2) {
                      ba.raiseEventFromDifferentThread(null, CameraW.this, -1,eventName +  "_ready", false, new Object[] {true});
                   }
                   if (ba.subExists(eventName + "_preview")) {
                      camera.setPreviewCallback(new Camera.PreviewCallback() {

                         @Override
                         public void onPreviewFrame(byte[] data,
                               Camera camera) {
                            ba.raiseEvent(null, eventName + "_preview", data);
                         }
                         
                      });
                   }
                }
                catch (Exception e) {
                   e.printStackTrace();
                   Release();
                   ba.raiseEventFromDifferentThread(null, CameraW.this, -1,eventName +  "_ready", false, new Object[] {false});
                }
             }

          }, this, -1);
       }
       /**
        * Starts displaying the preview images.
        */
       public void StartPreview() throws IOException {
          camera.setPreviewDisplay(sv.getHolder());
          camera.startPreview();
       }
       /**
        * Stops displaying the preview images.
        */
       public void StopPreview() {
          if (camera != null)
             camera.stopPreview();
       }
       /**
        * Releases the camera object and allows other processes to access the camera.
        */
       public void Release() {
    if (camera != null) {
             camera.setPreviewCallback(null);
             camera.stopPreview();
             closingCameras.put(currentId, camera);
             final Camera c = camera;
             camera = null;
             Thread t = new Thread(new Runnable() {

                @Override
                public void run() {
                   try {
                      Thread.sleep(5000);
                      synchronized (closingCameras) {
                         if (closingCameras.remove(currentId) != null) {
                            c.release();
                         }
                      }
                   } catch (Exception e) {
                      e.printStackTrace();
                   }
                }
                
             });
             t.start();
             
          }
          if (sv != null) {
             ViewGroup vg = (ViewGroup) sv.getParent();
    if (vg != null)
             vg.removeView(sv);
             sv = null;
          }
          
       }
       /**
        * Takes a picture. When the picture is ready, the PictureTaken event will be raised.
        *You should not call TakePicture while another picture is currently taken.
        *The preview images are stopped after calling this method. You can call StartPreview to restart the preview images.
        */
       public void TakePicture() {
          camera.takePicture(null , null, new Camera.PictureCallback() {

             @Override
             public void onPictureTaken(byte[] data, Camera camera) {
                ba.raiseEvent(null, eventName + "_picturetaken", data);
             }
             
          });
       }

    }
    As I previously wrote I think that it will be simpler to extend or modify CameraEx class.
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    V2.01 is attached to the first post.
     
  6. Roger Garstang

    Roger Garstang Well-Known Member Licensed User

    Cool, thanks for the code too. Always good to visualize what is being done and the more advanced folks can add the class stuff in a library too.

    I guess I wasn't paying attention yesterday and now see that the Initialize2 function states it requires 2.3+, and you had said earlier it is 1.6+. Both Initializes call the same function, so is Camera.class.getMethod call in the Runnable the only place requiring 2.3? Might be good just to do a android.os.Build.VERSION.SDK_INT check (Also available since 1.6) there and if not available do camera = Camera.open();. Should eliminate any errors thrown and the same could be done for any other 2.3+ stuff.

    If you still don't plan on integrating the class stuff I'll probably do something after I get my Relative Layout Library done. Main things for me was image orientation matching and capturing GPS both in code with existing GPS library and in Camera EXIF for my Evidence Collection app. Anything else I'll probably leave to the class.

    Also, what changed in 2.01?
     
    Last edited: Nov 29, 2012
  7. Erel

    Erel Administrator Staff Member Licensed User

    Yes.

    I've edited the code with the 2.01 changes. They were only done in the release method.
     
  8. bluedude

    bluedude Well-Known Member Licensed User

    Roger,

    API 10 seems to be a save option as a minimum. Checked some app. stats and biggest chunk of OS is Android 2.3.3 - 2.3.7

    Anyone more stats? Would like to know if 2.3 still exists :)
     
    afefef likes this.
  9. dunski

    dunski Member Licensed User

    Cannot see initialize2

    Hi this updated library looks great the only thing is I cant see initialize2.

    I removed the old library and added the new one but It doesn't seem to have initialize2

    Please help.
     
  10. Erel

    Erel Administrator Staff Member Licensed User

    Make sure that you copy the Camera library to the internal libraries folder. You can see the loaded version in the libraries tab (in the IDE). It should be v2.01.
     
  11. ziomorgan

    ziomorgan Member Licensed User

    Hi,
    I have too the same problem even after copying the library in the internal library folder (Unknown member: initialize2). The IDE show always the same library version 1.10.
    Thanks
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    Have you refreshed the libraries (right click on the libraries list and press refresh)?
     
  13. ziomorgan

    ziomorgan Member Licensed User

    Of course...more than one time
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    Open both libraries folders (internal and additional libraries folder). Delete Camera.xml / Camera.jar.

    Refresh the libraries list and make sure that Camera is not listed. Copy the new library.
     
  15. ziomorgan

    ziomorgan Member Licensed User

    I just did this test: I however find the library version 1.10 ????
    But where is ???
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    It can only be in the internal folder (under Program Files) or the additional folder (Tools - Configure paths).
     
  17. ziomorgan

    ziomorgan Member Licensed User

    Resolved. I have two libraries folder (one of older installation).
    Thank you very much Erel
     
  18. dunski

    dunski Member Licensed User

    Same here

    Same here

    The old version is by default in the libraries directory which is not in configure paths c:/program files/basic4android/libraries

    It seems to come installed there with B4A installation.

    I was adding the new library to my addLibraries folder which is the one in my configured paths for additional libraries which is what I normally do without a problem.

    So I deleted the one in the default library like Ziomorgan

    A well its all sorted now anyway.

    Thanks for the help Erel and Ziomorgan
     
  19. bluedude

    bluedude Well-Known Member Licensed User

    Zoom in preview

    Erel,

    My eyes are getting bad and I have an idea to use my phone when I forget my glasses. Can I use the zoom in preview mode?

    I want to create a small app. that increases the size of the stuff that I need to read, my phone would be perfect for that.

    Cheers,
     
  20. Erel

    Erel Administrator Staff Member Licensed User

    Try adding a SetZoom method to CameraEx. It should be quite simple.

    If you encounter any issue then please post in CameraEx thread.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice