ایجاد دوربین سفارشی در اندروید
سه شنبه 12 آبان 1394در این مقاله می خواهیم یک دوربین با امکانات فلش ، عکس گرفتن و برگرداندن گوشی به سمت خود را در اندروید آموزش دهیم.
ابتدا فایل های xml به صورت زیر خواهد بود:
camerademo_activity.xml <RelativeLayout 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" > <SurfaceView android:id="@+id/surfaceView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Camera Demo application\nDeveloped by Ravi Sharma" android:textColor="@android:color/black" /> <Button android:id="@+id/captureImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="@dimen/activity_vertical_margin" android:background="@drawable/btn_broadcast_selected" /> <Button android:id="@+id/flash" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginRight="25dp" android:layout_toLeftOf="@id/captureImage" android:background="@drawable/btn_flash" /> <Button android:id="@+id/flipCamera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/activity_vertical_margin" android:layout_marginLeft="25dp" android:layout_toRightOf="@id/captureImage" android:background="@drawable/btn_flipcamera" /> </RelativeLayout>
در فایل xml سه دکمه وجود دارد
1-برای گرفتن عکس
2-یکی برای خاموش و روشن شدن فلش(اگر دستگاه پشتیبانی کند)
3-تغییر دوربین (پشت یا جلو)
در زیر کلاس CameraDemoActivity را می نویسیم، هدف از ساخت این کلاس تعریف دکمه ها و صفحه ی دوربین است کلاس به صورت زیر خواهد بود:
بعد از این شی surfaceholder را اضافه می کنیم ، callback و listener را با یک دکمه به کلاس اضافه می کنیم ، برای این کار شما باید یک OnclickListener را اضافه کنید تا به surfaceholder پاسخ دهد.
public class CameraDemoActivity extends Activity{ private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera; private Button flipCamera; private Button flashCameraButton; private Button captureImage; private int cameraId; private boolean flashmode = false; private int rotation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camerademo_activity); // camera surface view created cameraId = CameraInfo.CAMERA_FACING_BACK; flipCamera = (Button) findViewById(R.id.flipCamera); flashCameraButton = (Button) findViewById(R.id.flash); captureImage = (Button) findViewById(R.id.captureImage); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); } }
public class CameraDemoActivity extends Activity implements Callback, OnClickListener
قرار دادن کد در متد oncreate
surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); flipCamera.setOnClickListener(this); captureImage.setOnClickListener(this); flashCameraButton.setOnClickListener(this); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
آخرین خط برای نگه داشتن دوربین در صفحه ی نمایش تا زمانی که activity در حال اجرا است.
باید تعداد دوربین ها و اینکه آیا گوشی فلش دارد را بررسی نماییم.
در متد onCreate زیر:
بعد از اضافه کردن Surfaceholder شما باید 3 متد زیر را override نمایید.
if (Camera.getNumberOfCameras() > 1) { flipCamera.setVisibility(View.VISIBLE); } if (!getBaseContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH)) { flashCameraButton.setVisibility(View.GONE); }
@Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { }
@Override public void surfaceCreated(SurfaceHolder holder) { if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) { alertCameraDialog (); } }
در زیر پیغامی برای باز کردن دوربین است یعنی زمانی که برنامه اجرا شد و بخواهید عکس بگیرید و خطا داشت پیغام زیر نمایش داده خواهد شد.
private void alertCameraDialog() { AlertDialog.Builder dialog = createAlert(CameraDemoActivity.this, "Camera info", "error to open camera"); dialog.setNegativeButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); dialog.show(); }
حالا متد باز شدن دوربین:
private boolean openCamera(int id) { boolean result = false; cameraId = id; releaseCamera(); try { camera = Camera.open(cameraId); } catch (Exception e) { e.printStackTrace(); } if (camera != null) { try { setUpCamera(camera); camera.setErrorCallback(new ErrorCallback() { @Override public void onError(int error, Camera camera) { //to show the error message. } }); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); result = true; } catch (IOException e) { e.printStackTrace(); result = false; releaseCamera(); } } return result; }
متد دوم برای این است که زمانی که دوربین جلو فعال بود ، دوربین پشت غیر فعال شود و یا باالعکس
private void releaseCamera() { try { if (camera != null) { camera.setPreviewCallback(null); camera.setErrorCallback(null); camera.stopPreview(); camera.release(); camera = null; } } catch (Exception e) { e.printStackTrace(); Log.e("error", e.toString()); camera = null; } }
روش مهم دیگر این است که فرض کنیم جسم دوربین به عنوان یک پارامتر است ، در این روش مدیریت چرخش گوشی و فلش را بررسی می نماید.
private void setUpCamera(Camera c) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); rotation = getWindowManager().getDefaultDisplay().getRotation(); int degree = 0; switch (rotation) { case Surface.ROTATION_0: degree = 0; break; case Surface.ROTATION_90: degree = 90; break; case Surface.ROTATION_180: degree = 180; break; case Surface.ROTATION_270: degree = 270; break; default: break; } if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { // frontFacing rotation = (info.orientation + degree) % 330; rotation = (360 - rotation) % 360; } else { // Back-facing rotation = (info.orientation - degree + 360) % 360; } c.setDisplayOrientation(rotation); Parameters params = c.getParameters(); showFlashButton(params); List<String> focusModes = params.getSupportedFlashModes(); if (focusModes != null) { if (focusModes .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } } params.setRotation(rotation); }
روش فلش به صورت زیر خواهد بود:
private void showFlashButton(Parameters params) { boolean showFlash = (getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null) && params.getSupportedFlashModes() != null && params.getSupportedFocusModes().size() > 1; flashCameraButton.setVisibility(showFlash ? View.VISIBLE : View.INVISIBLE); }
روش override به صورت زیر:
@Override public void onClick(View v) { switch (v.getId()) { case R.id.flash: flashOnButton(); break; case R.id.flipCamera: flipCamera(); break; case R.id.captureImage: takeImage(); break; default: break; } }
سه روش برای دوربین داریم:
1-فلش
2-دوربین جلو و عقب
3-کلیک بر روی تصویر
کد فلاش به صورت زیر خواهد بود:
private void flashOnButton() { if (camera != null) { try { Parameters param = camera.getParameters(); param.setFlashMode(!flashmode ? Parameters.FLASH_MODE_TORCH : Parameters.FLASH_MODE_OFF); camera.setParameters(param); flashmode = !flashmode; } catch (Exception e) { // TODO: handle exception } } }
کد دوربین جلو و پشت به صورت زیر خواهد بود:
private void flipCamera() { int id = (cameraId == CameraInfo.CAMERA_FACING_BACK ? CameraInfo.CAMERA_FACING_FRONT : CameraInfo.CAMERA_FACING_BACK); if (!openCamera(id)) { alertCameraDialog(); } }
کد گرفتن عکس به صورت زیر:
private void takeImage() { camera.takePicture(null, null, new PictureCallback() { private File imageFile; @Override public void onPictureTaken(byte[] data, Camera camera) { try { // convert byte array into bitmap Bitmap loadedImage = BitmapFactory.decodeByteArray(data, 0, data.length); // rotate Image Matrix rotateMatrix = new Matrix(); rotateMatrix.postRotate(rotation); Bitmap rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0, loadedImage.getWidth(), loadedImage.getHeight(), rotateMatrix, false); String state = Environment.getExternalStorageState(); File folder = null; if (state.contains(Environment.MEDIA_MOUNTED)) { folder = new File(Environment .getExternalStorageDirectory() + "/Demo"); } else { folder = new File(Environment .getExternalStorageDirectory() + "/Demo"); } boolean success = true; if (!folder.exists()) { success = folder.mkdirs(); } if (success) { java.util.Date date = new java.util.Date(); imageFile = new File(folder.getAbsolutePath() + File.separator + new Timestamp(date.getTime()).toString() + "Image.jpg"); imageFile.createNewFile(); } else { Toast.makeText(getBaseContext(), "Image Not saved", Toast.LENGTH_SHORT).show(); return; } ByteArrayOutputStream ostream = new ByteArrayOutputStream(); // save image into gallery rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream); FileOutputStream fout = new FileOutputStream(imageFile); fout.write(ostream.toByteArray()); fout.close(); ContentValues values = new ContentValues(); values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath()); CameraDemoActivity.this.getContentResolver().insert( Images.Media.EXTERNAL_CONTENT_URI, values); } catch (Exception e) { e.printStackTrace(); } } }); }
حالا باید یک سری مجوز دسترسی را به androidmanifest اضافه نماییم:
<uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.FLASHLIGHT" android:permissionGroup="android.permission-group.HARDWARE_CONTROLS" android:protectionLevel="normal" />
برخی از دستگاه ها خطای حافظه می گیرند برای جلوگیری از این خطا از کد زیر استفاده نمایید
<application . . . android:largeHeap="true" android:theme="@style/AppTheme" >
خروجی به صورت زیر خواهد بود:
کد کامل به صورت زیر خواهد بود:
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.sql.Timestamp; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.ErrorCallback; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.provider.MediaStore.Images; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.Toast; public class CameraDemoActivity extends Activity implements Callback, OnClickListener { private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera; private Button flipCamera; private Button flashCameraButton; private Button captureImage; private int cameraId; private boolean flashmode = false; private int rotation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camerademo_activity); // camera surface view created cameraId = CameraInfo.CAMERA_FACING_BACK; flipCamera = (Button) findViewById(R.id.flipCamera); flashCameraButton = (Button) findViewById(R.id.flash); captureImage = (Button) findViewById(R.id.captureImage); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); flipCamera.setOnClickListener(this); captureImage.setOnClickListener(this); flashCameraButton.setOnClickListener(this); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); if (Camera.getNumberOfCameras() > 1) { flipCamera.setVisibility(View.VISIBLE); } if (!getBaseContext().getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH)) { flashCameraButton.setVisibility(View.GONE); } } @Override public void surfaceCreated(SurfaceHolder holder) { if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) { alertCameraDialog(); } } private boolean openCamera(int id) { boolean result = false; cameraId = id; releaseCamera(); try { camera = Camera.open(cameraId); } catch (Exception e) { e.printStackTrace(); } if (camera != null) { try { setUpCamera(camera); camera.setErrorCallback(new ErrorCallback() { @Override public void onError(int error, Camera camera) { } }); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); result = true; } catch (IOException e) { e.printStackTrace(); result = false; releaseCamera(); } } return result; } private void setUpCamera(Camera c) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); rotation = getWindowManager().getDefaultDisplay().getRotation(); int degree = 0; switch (rotation) { case Surface.ROTATION_0: degree = 0; break; case Surface.ROTATION_90: degree = 90; break; case Surface.ROTATION_180: degree = 180; break; case Surface.ROTATION_270: degree = 270; break; default: break; } if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { // frontFacing rotation = (info.orientation + degree) % 330; rotation = (360 - rotation) % 360; } else { // Back-facing rotation = (info.orientation - degree + 360) % 360; } c.setDisplayOrientation(rotation); Parameters params = c.getParameters(); showFlashButton(params); List<String> focusModes = params.getSupportedFlashModes(); if (focusModes != null) { if (focusModes .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } } params.setRotation(rotation); } private void showFlashButton(Parameters params) { boolean showFlash = (getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null) && params.getSupportedFlashModes() != null && params.getSupportedFocusModes().size() > 1; flashCameraButton.setVisibility(showFlash ? View.VISIBLE : View.INVISIBLE); } private void releaseCamera() { try { if (camera != null) { camera.setPreviewCallback(null); camera.setErrorCallback(null); camera.stopPreview(); camera.release(); camera = null; } } catch (Exception e) { e.printStackTrace(); Log.e("error", e.toString()); camera = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void onClick(View v) { switch (v.getId()) { case R.id.flash: flashOnButton(); break; case R.id.flipCamera: flipCamera(); break; case R.id.captureImage: takeImage(); break; default: break; } } private void takeImage() { camera.takePicture(null, null, new PictureCallback() { private File imageFile; @Override public void onPictureTaken(byte[] data, Camera camera) { try { // convert byte array into bitmap Bitmap loadedImage = null; Bitmap rotatedBitmap = null; loadedImage = BitmapFactory.decodeByteArray(data, 0, data.length); // rotate Image Matrix rotateMatrix = new Matrix(); rotateMatrix.postRotate(rotation); rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0, loadedImage.getWidth(), loadedImage.getHeight(), rotateMatrix, false); String state = Environment.getExternalStorageState(); File folder = null; if (state.contains(Environment.MEDIA_MOUNTED)) { folder = new File(Environment .getExternalStorageDirectory() + "/Demo"); } else { folder = new File(Environment .getExternalStorageDirectory() + "/Demo"); } boolean success = true; if (!folder.exists()) { success = folder.mkdirs(); } if (success) { java.util.Date date = new java.util.Date(); imageFile = new File(folder.getAbsolutePath() + File.separator + new Timestamp(date.getTime()).toString() + "Image.jpg"); imageFile.createNewFile(); } else { Toast.makeText(getBaseContext(), "Image Not saved", Toast.LENGTH_SHORT).show(); return; } ByteArrayOutputStream ostream = new ByteArrayOutputStream(); // save image into gallery rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream); FileOutputStream fout = new FileOutputStream(imageFile); fout.write(ostream.toByteArray()); fout.close(); ContentValues values = new ContentValues(); values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath()); CameraDemoActivity.this.getContentResolver().insert( Images.Media.EXTERNAL_CONTENT_URI, values); } catch (Exception e) { e.printStackTrace(); } } }); } private void flipCamera() { int id = (cameraId == CameraInfo.CAMERA_FACING_BACK ? CameraInfo.CAMERA_FACING_FRONT : CameraInfo.CAMERA_FACING_BACK); if (!openCamera(id)) { alertCameraDialog(); } } private void alertCameraDialog() { AlertDialog.Builder dialog = createAlert(CameraDemoActivity.this, "Camera info", "error to open camera"); dialog.setNegativeButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); dialog.show(); } private Builder createAlert(Context context, String title, String message) { AlertDialog.Builder dialog = new AlertDialog.Builder( new ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog)); dialog.setIcon(R.drawable.ic_launcher); if (title != null) dialog.setTitle(title); else dialog.setTitle("Information"); dialog.setMessage(message); dialog.setCancelable(false); return dialog; } private void flashOnButton() { if (camera != null) { try { Parameters param = camera.getParameters(); param.setFlashMode(!flashmode ? Parameters.FLASH_MODE_TORCH : Parameters.FLASH_MODE_OFF); camera.setParameters(param); flashmode = !flashmode; } catch (Exception e) { // TODO: handle exception } } } }
- Android
- 2k بازدید
- 2 تشکر