Wednesday, 25 February 2015

Make Your Own Camera Part-2




In this part, We will make our own camera something like above. We have two activities, main activity and camera activity. Once you click on start button in main activity, it will launch the Camera activity. Camera preview will be automatically started and you only need to click the Take button to capture the image. After taking the picture, when you click the OK button it will take you back to the main activity and currently taken Image will be shown in the Image View of Main activity.

First we will create Main Activity java class.


package media.manager;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.Activity;
import android.view.View;
import android.widget.ImageView;


import sub_activities.MyCameraActivity;


public class FunActivity extends Activity     
{


   private static final String TAG=FunActivity.class.getSimpleName();


   public static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 101;
   private Uri imageUri=null;
   ImageView imageView;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
       imageView = (ImageView)findViewById(R.id.imageView);
       
   }


   
   public void buttonCameraClick(View v){
       Intent takePicture = new Intent();
       takePicture.setClass(this,MyCameraActivity.class);
       startActivityForResult(takePicture, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
   }   


   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {        


       if(requestCode==CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
   
           imageUri = data.getData();
           imageView.setImageURI(imageUri);
           }
           
       }            
   }



Next we will create a helper class which we will use inside the Picture activity class. This class contains all the events related to camera activities.

BackCameraController.java


package media.manager;


import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;


public class BackCameraController {


   private static final String TAG = BackCameraController.class.getSimpleName();


   private boolean hasBackCamera;


   public Camera getCamera() {
       return camera;
   }
   public interface BackCameraControllerListener{
       public void afterTakePicture(File pictureFile, boolean finish);
   }


   private Camera camera;
   private Camera.CameraInfo info;
   private BackCameraControllerListener cameraListener;


   private int backCameraId;
   private int rotation;


   public BackCameraController(Context context, int rotation) {


       try {
           cameraListener=(BackCameraControllerListener)context;
       } catch (ClassCastException e) {
           throw new ClassCastException(context.toString()
                   + " must implement BackCameraControllerListener");
       }


       if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
           backCameraId=getBackCameraId();
           hasBackCamera = backCameraId != -1;
       }


       info = new Camera.CameraInfo();
       this.rotation=rotation;
   }


   public boolean hasBackCamera() {
       return hasBackCamera;
   }


   public void getBackCameraInstance(SurfaceView surfaceView) {
       Log.i(TAG, "hasBackCamera 1: " + hasBackCamera());
       camera = null;
       if (hasBackCamera) {
           try {
               camera = Camera.open(backCameraId);
               Log.i(TAG, "Camera is open");
               SurfaceHolder surfaceHolder = surfaceView.getHolder();
               camera.setPreviewDisplay(surfaceHolder);
               setCameraDisplayOrientation(backCameraId);
               camera.startPreview();
               Log.i(TAG, "Start Preview");


               Camera.Parameters params = camera.getParameters();
               params.setJpegQuality(100);
               camera.setParameters(params);


           } catch (Exception e) {
               hasBackCamera = false;
               Log.i(TAG, "Before take picture \n"+e.toString());
           }
       }
   }


   public void takeBackPicture() {
       Log.i(TAG, "hasBackCamera 2: " + hasBackCamera);
       if (hasBackCamera) {
           camera.takePicture(null, null, mBackPicture);
       }
   }


   private Camera.PictureCallback mBackPicture = new Camera.PictureCallback() {
       @Override
       public void onPictureTaken(byte[] data, Camera camera) {


           File pictureFile = getBackMediaFile();
           if (pictureFile == null) {
               Log.i(TAG, "Error creating media file, check storage permissions");
               return;
           }
           try {
               Log.d(TAG, "File created");
               FileOutputStream fos = new FileOutputStream(pictureFile);
               fos.write(data);
               fos.close();
           } catch (Exception e) {
               Log.i(TAG, "File not found: " + e.getMessage());
           }
           cameraListener.afterTakePicture(pictureFile, true);
           releaseCamera();
           Log.i(TAG,"Camera is released");
       }
   };


   private File getBackMediaFile() {


       File pictureDirectory = new File(Environment.getExternalStorageDirectory(),"MyCamera");
       if(!ALF_HOME_DIRECTORY.exists()){
           if(!ALF_HOME_DIRECTORY.mkdir()){
               Log.i(TAG,"Home Directory does not Exists");
           }
       }


       String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
       File picture = new File(pictureDirectory.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
       Log.i(TAG, "mediaFile: " + picture);
       return picture;
   }


   public void releaseCamera() {
       if (camera != null) {
           camera.stopPreview();
           camera.release();
           camera = null;
       }
   }


   private int getBackCameraId() {
       int camId = -1;
       int numberOfCameras = Camera.getNumberOfCameras();
       Camera.CameraInfo ci = new Camera.CameraInfo();


       for (int i = 0; i < numberOfCameras; i++) {
           Camera.getCameraInfo(i, ci);
           if (ci.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
               camId = i;
           }
       }
       return camId;
   }


   private   void setCameraDisplayOrientation(int camId) {


       Camera.getCameraInfo(camId, info);
       int degrees = 0;


       switch (rotation) {
           case Surface.ROTATION_0: degrees = 0; break;
           case Surface.ROTATION_90: degrees = 90; break;
           case Surface.ROTATION_180: degrees = 180; break;
           case Surface.ROTATION_270: degrees = 270; break;
       }


       int result;
       if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
           result = (info.orientation + degrees) % 360;
           result = (360 - result) % 360;  // compensate the mirror
       } else {  // back-facing
           result = (info.orientation - degrees + 360) % 360;
       }
       camera.setDisplayOrientation(result);
   }
}

Next, we will create Camera Activity java class. This class has a layout which contain an three buttons Cancel, Take and OK. When you click the Take button it will take the photo and when you click OK it will be shown in first activity image view.



package media.manager;


import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;


import java.io.File;
import media.manager.BackCameraController;


public class MyCameraActivity extends Activity implements
       BackCameraController.BackCameraControllerListener
{


   private static final String TAG = MyCameraActivity.class.getSimpleName();


   BackCameraController cc;
   SurfaceView surfaceView;
   File picture;


   Button take, ok, cancel;


   boolean canFinish=false;
   boolean canTake=false;


   CameraTakeTask cameraTask;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_my_camera);


       cc = new BackCameraController(this,270);
       surfaceView=(SurfaceView)findViewById(R.id.camera_surfaceView);
       take=(Button)findViewById(R.id.camera_button_take);
       ok=(Button)findViewById(R.id.camera_button_ok);
       cancel=(Button)findViewById(R.id.camera_button_cancel);


       ok.setEnabled(false);


       take.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               canTake=true;
               ok.setEnabled(true);
               cancel.setVisibility(View.INVISIBLE);
           }
       });


       ok.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {


               if(picture!=null){
                   Uri result = Uri.fromFile(picture);
                   Log.i(TAG, "Uri..... : "+result);
                   Intent data = new Intent(Intent.ACTION_PICK, result);
                   setResult(RESULT_OK, data);
               }else {
                   Toast.makeText(MyCameraActivity.this,"Wait..",Toast.LENGTH_SHORT).show();
               }


               if(canFinish)
                   finish();
           }
       });


       cancel.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               cc.releaseCamera();
               finish();
           }
       });


   }


   @Override
   protected void onResume() {
       super.onResume();


       cameraTask=new CameraTakeTask();
       cameraTask.execute();
   }


   @Override
   protected void onPause() {
       super.onPause();
       if(cc!=null){
           if(cc.hasBackCamera()){
               cc.releaseCamera();
           }
           cc=null;
       }
   }


   @Override
   public void afterTakePicture(File pictureFile, boolean finish) {
       picture=pictureFile;
       canFinish=finish;
       ok.setEnabled(true);
   }


   class CameraTakeTask extends AsyncTask<Void,Void,Void>{


       int count=1;
       @Override
       protected Void doInBackground(Void... params) {
           if (cc!=null && cc.getCamera() == null) {
               cc.getBackCameraInstance(surfaceView);
           }else {
               Log.i(TAG, "Camera is occupied");
           }


           for (int i = 0; i < 10; i++) {
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               if(canTake) {
                   cc.takeBackPicture();
                   count++;
               }
               if(count>1)
                   break;
           }


           return null;
       }
   }


}

activity_main.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical
   android:background="#f0800082">


   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="New Text"
       android:id="@+id/textView"
       android:layout_gravity="center_horizontal" />


   <ImageView
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:id="@+id/imageView"
       android:layout_gravity="center_horizontal"
       android:layout_weight="1"
       android:layout_margin="50dp"
       android:src="@drawable/ic_launcher" />


   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Start"
       android:id="@+id/my_camera_button"
       android:layout_gravity="center_horizontal"
andoid:onClick="buttonCameraClick"
       android:layout_margin="20dp" />
</LinearLayout>


activity_my_camera.xml


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:padding="2dp"
   tools:context="sub_activities.MyCameraActivity">


   <TextView
       android:text="@string/hello_world"
       android:layout_width="wrap_content"
       android:visibility="gone"
       android:layout_height="wrap_content" />


   <SurfaceView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/camera_surfaceView"
       />


   <Button
       style="?android:attr/buttonStyleSmall"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/back_camera_ok"
       android:id="@+id/camera_button_ok"
       android:layout_gravity="end|bottom" />


   <Button
       style="?android:attr/buttonStyleSmall"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/back_camera_take"
       android:id="@+id/camera_button_take"
       android:layout_gravity="center_horizontal|bottom" />


   <Button
       style="?android:attr/buttonStyleSmall"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/back_camera_cancel"
       android:id="@+id/camera_button_cancel"
       android:layout_gravity="start|bottom" />


</FrameLayout>


Add following lines inside the your manifest.xml



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="media.manager" >


   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


   <uses-feature android:name="android.hardware.camera.autofocus" />
   <uses-feature android:name="android.hardware.camera" />
   <uses-permission android:name="android.permission.camera" />
   <uses-permission android:name="android.permission.CAMERA" />


   


   <application
       android:allowBackup="true"
       android:icon="@drawable/ic_launcher"
       android:label="MyCamera"
       android:theme="@style/AppTheme" >
       <activity
           android:name=".MainActivity"
           android:label="MyCamera"
           android:screenOrientation="portrait" >
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />


               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
       <activity
           android:name=".MyCameraActivity"
           android:label="Camera"
           android:screenOrientation="portrait" >
       </activity>
      


</manifest>

To store picture in the mobile you need the permission for read and write using uses-permission tag like below inside manifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Hope you will get some thought about creating your own camera in a Android device. Enjoy......

No comments:

Post a Comment