Android 自定義相機
Camera
相信大家對相機的使用都不陌生吧,下面我給大家分享一下自定義相機
Android提供了Camera來控制拍照,步驟如下:
(1)呼叫Camera的open()方法開啟相機。
(2)呼叫Camera的getParameters()獲取拍照引數,該方法返回一個Cmera.Parameters物件。
(3)呼叫Camera.Parameters物件對照相的引數進行設定。
(4)呼叫Camera的setParameters(),並將Camera.Parameters物件作為引數傳入,這樣就可以對拍照進行引數控制,Android2.3.3以後不用設定。
(5)呼叫Camerade的startPreview()的方法開始預覽取景,在之前需要呼叫Camera的setPreviewDisplay(SurfaceHolder holder)設定使用哪個SurfaceView來顯示取得的圖片。
(6)呼叫Camera的takePicture()方法進行拍照。
(7)程式結束時,要呼叫Camera的stopPreview()方法停止預覽,並且通過Camera.release()來釋放資源。
Camera需要賦予的許可權:
<uses-permission android:name="android.permission.CAMERA" />
<!-- 閃光燈許可權 -->
<uses-permission android:name="android.permission.FLASHLIGHT" />
<!-- 往SDCard寫入資料許可權 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
接下來就是自定義的程式碼了:
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
import java.util.List;
/**
* Created by DELL on 2018/3/30.
*/
public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback, Camera.AutoFocusCallback {
private final String TAG = "CameraPreview";
/**
* 圖片的偏移
*/
public int moveX = 0;
public int moveY = 0;
public SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
public Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
public Camera.Size mPictureSize;
private List<Camera.Size> mSupportedPictureSizes;
private Camera mCamera;
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CameraPreview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public SurfaceHolder getLouisSurfaceHolder() {
return mHolder;
}
private void init(Context context) {
mSurfaceView = new SurfaceView(context);
ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView(mSurfaceView, layoutParams);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
try {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedPictureSizes = mCamera.getParameters().getSupportedPictureSizes();
for (Camera.Size size : mSupportedPreviewSizes) {
Log.e(TAG, "CameraPreview for mPreviewSize w - h : " + size.width + " - " + size.height);
}
for (Camera.Size size : mSupportedPictureSizes) {
Log.e(TAG, "CameraPreview for mPictureSize w - h : " + size.width + " - " + size.height);
}
mCamera.setDisplayOrientation(90);
} catch (Exception e) {
e.printStackTrace();
}
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 我們故意忽視了孩子的測量,因為它是一個表面檢視的包裝器,它將攝像機的預覽置於中心,而不是拉伸
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
// 需要寬高切換 因為相機有90度的角度
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, height, width);
}
if (mSupportedPictureSizes != null) {
mPictureSize = getOptimalPreviewSize(mSupportedPictureSizes, height, width);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
}
// 將子檢視置於父檢視內
if (width * previewHeight > height * previewWidth) {
final int scaleWidth = width;
final int scaleHeight = width * previewHeight / previewWidth;
moveX = 0;
moveY = (scaleHeight - height) / 2;
if (moveY < 0) {
moveY = 0;
}
child.layout(-moveX, -moveY, scaleWidth, scaleHeight);
} else {
final int scaleHeight = height;
final int scaleWidth = height * previewWidth / previewHeight;
moveX = (scaleWidth - width) / 2;
moveY = 0;
if (moveX < 0) {
moveX = 0;
}
child.layout(-moveX, -moveY, scaleWidth, scaleHeight);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d("", "surface surfaceCreated()");
// 表面已經被創造出來,獲得相機並告訴它在哪裡。
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// 當我們返回時,表面會被破壞,所以停止預覽。
if (mCamera != null) {
mCamera.stopPreview();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera == null) {
return;
}
try {
// 現在已知大小,設定相機引數並開始。
// 預覽
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
mCamera.autoFocus(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onAutoFocus(boolean success, Camera camera) {
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// 試著找出一個尺寸匹配的寬比和大小。
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// 找不到一個匹配的縱橫比,忽略要求。
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
Activity的程式碼:
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.example.dell.facedetection.CameraLine;
import com.example.dell.facedetection.view.CameraPreview;
import com.example.dell.facedetection.DoubleClickConfig;
import com.example.dell.facedetection.R;
import com.example.dell.facedetection.utils.ScreenSwitchUtils;
import com.example.dell.facedetection.utils.Utils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CameraActivity extends AppCompatActivity implements Camera.PictureCallback, Camera.ShutterCallback {
public static final int FLAG_CHOOCE_PICTURE = 2001;
private final int FLAG_AUTO_FOCUS = 1001;
private final int TAKE_PHOTO_FINISH = 1002;
private final int FOCUS_DURATION = 3000;//延遲聚焦
private int mScreenHeight, mScreenWidth;
private int viewHeight;
public static final int ZOOM_FACTOR = 5;//縮放因子
private int zoomValue = 0;
private boolean safeToTakePicture = true;
private CameraPreview mPreview;
Camera mCamera;
int cameraCurrentlyLocked;
private ImageView preview_iv;
private Handler handler;
Bitmap rightBitmap;
ImageView id_iv_flash_switch;
CameraLine mCameraLine;
private int defaultCameraId = 1;
int cameraPosition = 1;
private ScreenSwitchUtils mScreenSwitchInstance;
private boolean isPortrait = true;
private int orientationState = ScreenSwitchUtils.ORIENTATION_HEAD_IS_UP;
private byte[] bytesData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//設定螢幕常亮
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉資訊欄
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//【旋轉問題】首先強制豎屏,手機橫過來時候 控制元件不變
setContentView(R.layout.activity_camera);
mScreenSwitchInstance = ScreenSwitchUtils.init(getApplicationContext());
if (!Utils.checkCameraHardware(this)) {
Toast.makeText(CameraActivity.this, "裝置沒有攝像頭", Toast.LENGTH_SHORT).show();
return;
}
mCameraLine = (CameraLine) findViewById(R.id.id_cl);
preview_iv = (ImageView) findViewById(R.id.id_preview_iv);
RelativeLayout id_rl_cp_view = (RelativeLayout) findViewById(R.id.id_rl_cp_view);
DoubleClickConfig.registerDoubleClickListener(id_rl_cp_view, new DoubleClickConfig.OnDoubleClickListener() {
@Override
public void OnSingleClick(View v) {
zoomDown();//單機縮小
}
@Override
public void OnDoubleClick(View v) {
zoomUp();//雙擊放大
}
});
id_iv_flash_switch = (ImageView) findViewById(R.id.id_iv_flash_switch);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == FLAG_AUTO_FOCUS) {
if (mCamera != null && safeToTakePicture && !TextUtils.isEmpty(mCamera.getParameters().getFlashMode())) {
mCamera.startPreview();
mCamera.autoFocus(null);
}
handler.sendEmptyMessageDelayed(FLAG_AUTO_FOCUS, FOCUS_DURATION);
} else if (msg.what == TAKE_PHOTO_FINISH) {
// byte[] bitmapByte= (byte[]) msg.obj;
if (msg.obj == null) {
return;
}
String filePath = msg.obj.toString();
Intent intent = new Intent(CameraActivity.this, PreviewActivity.class);
intent.putExtra("filePath", filePath);
CameraActivity.this.startActivity(intent);
}
}
};
Log.d("CameraSurfaceView", "CameraSurfaceView onCreate currentThread : " + Thread.currentThread());
// 得到螢幕的大小
WindowManager wManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wManager.getDefaultDisplay();
mScreenHeight = display.getHeight();
mScreenWidth = display.getWidth();
viewHeight = mScreenWidth / 2;
mPreview = (CameraPreview) findViewById(R.id.camera_preview);
startCamera();
}
@Override
protected void onStart() {
super.onStart();
//【重力感應處理】
mScreenSwitchInstance.start(this);
}
@Override
protected void onStop() {
super.onStop();
//【重力感應處理】
mScreenSwitchInstance.stop();
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.id_iv_shutter:
stopFocus();
takePicture(null, null, this);
break;
case R.id.id_iv_flash_switch:
toggleFlash();
break;
case R.id.id_iv_config_line:
mCameraLine.changeLineStyle();
break;
case R.id.id_iv_change:
changeCameraTwo();
break;
default:
break;
}
}
@Override
protected void onResume() {
super.onResume();
startCamera();
}
public void changeCameraTwo() {
//切換前後攝像頭
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();//得到攝像頭的個數
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);//得到每一個攝像頭的資訊
if (cameraPosition == 1) {
Toast.makeText(this, "1現在是後置,變更為前置", Toast.LENGTH_SHORT).show();
//現在是後置,變更為前置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK後置
mCamera.stopPreview();//停掉原來攝像頭的預覽
releaseCamera();
mCamera = Camera.open(i);//開啟當前選中的攝像頭
try {
mCamera.setPreviewDisplay(mPreview.getLouisSurfaceHolder());//通過surfaceview顯示取景畫面
// mCamera.setDisplayOrientation(90); //
mPreview.setCamera(mCamera);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();//開始預覽
cameraPosition = 0;
break;
}
} else {
Toast.makeText(this, "2現在是前置, 變更為後置", Toast.LENGTH_SHORT).show();
//現在是前置, 變更為後置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK後置
mCamera.stopPreview();//停掉原來攝像頭的預覽
releaseCamera();
mCamera = Camera.open(i);//開啟當前選中的攝像頭
try {
mCamera.setPreviewDisplay(mPreview.getLouisSurfaceHolder());//通過surfaceview顯示取景畫面
// mCamera.setDisplayOrientation(90); //
mPreview.setCamera(mCamera);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();//開始預覽
cameraPosition = 1;
break;
}
}
}
}
private void startCamera() {
// Open the default i.e. the first rear facing camera.
try {
if (mCamera == null) {
mCamera = Camera.open();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "啟動照相機失敗,請檢查裝置並開啟許可權", Toast.LENGTH_SHORT).show();
}
cameraCurrentlyLocked = defaultCameraId;
mPreview.setCamera(mCamera);
startFocus();
}
@Override
protected void onPause() {
super.onPause();
stopFocus();
releaseCamera();
}
/**
* 開啟自動對焦
*/
private void startFocus() {
stopFocus();
handler.sendEmptyMessageDelayed(FLAG_AUTO_FOCUS, FOCUS_DURATION);
}
/**
* 關閉自動對焦
*/
private void stopFocus() {
handler.removeMessages(FLAG_AUTO_FOCUS);
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseCamera();
}
/**
* 釋放mCamera
*/
private void releaseCamera() {
// Because the Camera object is a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.release();
mCamera = null;
}
}
/**
* 拍照
*
* @param shutter
* @param raw
* @param jpeg
*/
public void takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw,
Camera.PictureCallback jpeg) {
if (mCamera != null) {
if (safeToTakePicture) {
mCamera.takePicture(shutter, raw, jpeg);
safeToTakePicture = false;
}
}
}
/**
* 縮小
*/
public void zoomDown() {
if (mCamera == null) {
return;
}
Camera.Parameters p = mCamera.getParameters();
if (!p.isZoomSupported()) return;
if (zoomValue > 0) {
zoomValue--;
} else {
zoomValue = 0;
// Toast.makeText(getApplicationContext(), "已縮小到最小級別", Toast.LENGTH_SHORT).show();
return;
}
int value = (int) (1F * zoomValue / ZOOM_FACTOR * p.getMaxZoom());
p.setZoom(value);
mCamera.setParameters(p);
}
/**
* 放大
*/
public void zoomUp() {
if (mCamera == null) {
return;
}
Camera.Parameters p = mCamera.getParameters();
if (!p.isZoomSupported()) return;
if (zoomValue < ZOOM_FACTOR) {
zoomValue++;
} else {
zoomValue = ZOOM_FACTOR;
Toast.makeText(getApplicationContext(), "已放大到最大級別", Toast.LENGTH_SHORT).show();
return;
}
int value = (int) (1F * zoomValue / ZOOM_FACTOR * p.getMaxZoom());
p.setZoom(value);
mCamera.setParameters(p);
}
/**
* 開關閃光燈
* 持續的亮燈FLASH_MODE_TORCH
* 閃一下FLASH_MODE_ON
* 關閉模式FLASH_MODE_OFF
* 自動感應是否要用閃光燈FLASH_MODE_AUTO
*/
public void toggleFlash() {
if (mCamera == null) {
return;
}
Camera.Parameters p = mCamera.getParameters();
if (Camera.Parameters.FLASH_MODE_OFF.equals(p.getFlashMode())) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
mCamera.setParameters(p);
id_iv_flash_switch.setImageDrawable(getResources().getDrawable(R.mipmap.camera_flash_on));
} else if (Camera.Parameters.FLASH_MODE_ON.equals(p.getFlashMode())) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(p);
id_iv_flash_switch.setImageDrawable(getResources().getDrawable(R.mipmap.camera_flash_auto));
} else if (Camera.Parameters.FLASH_MODE_AUTO.equals(p.getFlashMode())) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//持續的亮燈
mCamera.setParameters(p);
id_iv_flash_switch.setImageDrawable(getResources().getDrawable(R.mipmap.camera_flash_light));
} else if (Camera.Parameters.FLASH_MODE_TORCH.equals(p.getFlashMode())) {
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(p);
id_iv_flash_switch.setImageDrawable(getResources().getDrawable(R.mipmap.camera_flash_off));
} else {
Toast.makeText(this, "Flash mode setting is not supported.", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FLAG_CHOOCE_PICTURE && resultCode == RESULT_OK) {
Uri uri = data.getData();
String imgPath = getUrl(uri);
Log.d("", "CameraSurfaceView imgPath : " + imgPath);
}
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
if (data == null || data.length <= 0) {
safeToTakePicture = true;
return;
}
Log.d("CameraSurfaceView", "CameraSurfaceView onPictureTaken data.length : " + data.length);
isPortrait = mScreenSwitchInstance.isPortrait();
orientationState = mScreenSwitchInstance.getOrientationState();
Log.i("xxx", "louis==xx==isPortrait:" + isPortrait);
Log.i("xxx", "louis==xx==orientationState:" + orientationState);
// 儲存圖片
bytesData = data;
safeToTakePicture = true;
handleAndSaveBitmap(data);
}
@Override
public void onShutter() {
Log.d("CameraSurfaceView", "CameraSurfaceView onShutter");
}
/**
* 處理拍照圖片並儲存
*
* @param data
*/
private synchronized void handleAndSaveBitmap(byte[] data) {
// 儲存圖片
//### Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap b = Utils.Bytes2Bitmap(data);
if (cameraPosition == 1) {
//後置攝像頭
//rightBitmap = Utils.rotate(b, 0);
rightBitmap = Utils.rotate(b, 90);//擺正位置
//rightBitmap = Utils.rotate(b, 180);
// rightBitmap = Utils.rotate(b, 270);
//根據重力感應 更正旋轉
switch (orientationState) {
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_UP:
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_DOWN:
rightBitmap = Utils.rotate(rightBitmap, 180);
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_LEFT:
rightBitmap = Utils.rotate(rightBitmap, 270);
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_RIGHT:
rightBitmap = Utils.rotate(rightBitmap, 90);
break;
}
} else {
//前置攝像頭
rightBitmap = Utils.rotate(b, 270);//擺正位置
//根據重力感應 更正旋轉
switch (orientationState) {
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_UP:
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_DOWN:
rightBitmap = Utils.rotate(rightBitmap, 180);
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_LEFT:
rightBitmap = Utils.rotate(rightBitmap, 90);
break;
case ScreenSwitchUtils.ORIENTATION_HEAD_IS_RIGHT:
rightBitmap = Utils.rotate(rightBitmap, 270);
break;
}
}
String filePath = saveImageFile(rightBitmap);
Message message = handler.obtainMessage();
message.what = TAKE_PHOTO_FINISH;
message.obj = filePath;
message.sendToTarget();
}
private String saveImageFile(Bitmap bmp) {
String filePath = null;
File file = Utils.getDiskCacheDir(this, "bitmap");
if (!file.exists()) {
file.mkdirs();
}
File f = new File(file, System.currentTimeMillis() + ".jpg");
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f));
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
filePath = f.getAbsolutePath();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bmp != null && !bmp.isRecycled()) {
bmp.recycle();
bmp = null;
}
}
// /storage/sdcard0/Android/data/com.example.dell.facedetection/cache/bitmap/1522393623105.jpg
return filePath;
}
/**
* 獲取從相簿中選擇的圖片的據對路徑
*
* @param uri
* @return
*/
private String getUrl(Uri uri) {
if (uri == null) {
return null;
}
String[] proj = {MediaStore.Images.Media.DATA};
Cursor actualimagecursor = managedQuery(uri, proj, null, null, null);
int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
actualimagecursor.moveToFirst();
String img_path = actualimagecursor.getString(actual_image_column_index);
return TextUtils.isEmpty(img_path) ? null : img_path;
}
/**
* 重力感應導致橫豎屏切換的條件下:獲取當前螢幕旋轉角度,要是鎖定豎屏就一直返回0了。。。
*
* @param activity
* @return 0表示是豎屏; 90表示是左橫屏; 180表示是反向豎屏; 270表示是右橫屏
*/
public static int getDisplayRotation(Activity activity) {
if (activity == null) {
return 0;
}
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
switch (rotation) {
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
return 0;
}
public String saveImageFilePath() {
String imageFilePath = Environment.getExternalStorageDirectory().getPath();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd");
imageFilePath = imageFilePath + File.separator + "TongueImage";
IfNotExistMkdir(imageFilePath);
String subPath = File.separator + sdf.format(new Date());
imageFilePath += subPath;
IfNotExistMkdir(imageFilePath);
SimpleDateFormat hms = new SimpleDateFormat("HHMMSS");
String FileName = hms.format(new Date());
return imageFilePath = File.separator + imageFilePath + File.separator + FileName + ".jpg";
}
private void IfNotExistMkdir(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
try {
file.mkdir();
} catch (Exception e) {
//no do
}
}
}
public void saveToSDCard(byte[] data) throws IOException {
// Log.d(TAG, "saveToSDCard");
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化時間
String filename = format.format(date) + ".jpg";
File fileFolder = new File(Environment.getExternalStorageDirectory() + "/ansen/");// Environment.getRootDirectory()
if (!fileFolder.exists()) {
fileFolder.mkdir();
}
File jpgFile = new File(fileFolder, filename);
FileOutputStream outputStream = new FileOutputStream(jpgFile); // 檔案輸出流
outputStream.write(data);
outputStream.close();
mCamera.startPreview(); // 拍完照後,重新開始預覽
if (false) {
Bitmap b = Utils.BytesToBitmap(data);
// 獲取手機螢幕的寬高
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
int windowWidth = windowManager.getDefaultDisplay().getWidth();
int windowHight = windowManager.getDefaultDisplay().getHeight();
Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, windowWidth, windowHight);
// 圖片壓縮
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
}
}
}
使用截圖:
預覽圖片:
選擇圖片:
相關推薦
Android自定義相機超詳細講解
了解 catch 實現 4.4 required form 需要 eset 自己 Android自定義相機超詳細講解 轉載請標明出處: http://blog.csdn.net/vinicolor/article/details/49642861; 由於網上關於Andr
Android 自定義相機 Camera 圖片方向問題
相機預覽方向問題 對於相機的預覽方向我們可以通過如下API進行設定 camera.setDisplayOrientation(0);但是,該API影響的是相機的預覽方向,對於照片的儲存方向並沒有什麼影響,最終照片儲存的方向還是由Camera的影象Sensor決定的。 照片儲
Android自定義相機Camera(一)
Time:2018/06/21 因為專案需求,需要實現跟小猿搜題的類似的功能,系統相機直接就被排除了,原本打算是找個一個demo,改吧改吧就直接用了,找的過程中發現程式碼太舊了,目前6.0以上的系統很多不支援,然後按照demo的邏輯,就寫一個相
android自定義相機(帶邊框和按鈕)
前兩個月專案要求不能呼叫系統的相機,那就只能用自定義的了,查了一些資料,自己再研究了一下,自定義的相機還是有點複雜的,佈局和程式碼中都要用到一個重要的SurfaceView。 一、建立佈局,佈局的背景框可以讓美工給出,這裡姑且就是一個藍色的邊框,然後下面有三個按鈕,我里布局檔案activit
Android 自定義相機第二次開啟卡死
原因:相機沒有被正確釋放導致第二次打卡死。 //正確的釋放資原始碼 public void release(){ if (mCamera != null) { mCamera.setPreviewCallback(null) ;
Android 自定義相機Demo 入門學習
Android 自定義相機Demo 本文是參考網上一些自定義相機示例,再結合自己對相機的功能需求寫的,基本上包含了很多基本功能,比如相機對焦、閃光燈,以及在手機預覽介面上繪製自己想要繪製的圖案。 話不多說,先上一張圖: 應用是在Android Studio中開發的,java程
Android自定義相機實現N連拍
/** * 描述:自動連續拍照 * 開發者:開發者的樂趣JRT * 建立時間:2017-3-15 19:16 * CSDN地址:http://blog.csdn.net/Jiang_Rong_Tao/article * E-mail:[email protected] **/ publi
android 自定義相機Camera2
上一篇文章我們已經運用Camera自定義了一個相機,今天我們就用Camera2自定義一個相機。Camera2是android5.0新增的api,Camera2與Camera差別比較大,採用了全新的模式,功能更加強大。今天這個例子就是Camera2拍照TextureView
Android 自定義相機
Camera 相信大家對相機的使用都不陌生吧,下面我給大家分享一下自定義相機 Android提供了Camera來控制拍照,步驟如下: (1)呼叫Camera的open()方法開啟相機。 (2)呼叫Camera的getParameters()獲取
Android自定義相機預覽開始時自動對焦
如果是呼叫系統相機不會存在對焦問題,要實現自己的相機在開始的時候自動自動對焦,只需要新增兩句程式碼: parameters.setFocusMode(Camera.Paramet
簡單談談android自定義相機的實現(上 android.hardware.Camera)
通常情況下,呼叫android系統相機基本上可以滿足拍照的需求,而自定義相機的需求一般來自於開發自己的相機應用,今天我們來簡單聊聊android自定義相機的實現,限於篇幅,我們上篇只討論android.hardware.Camera,下篇我會和大家一起討論一下a
Android自定義相機拍攝黑屏
速記,備查。 1、需求場景 拍攝20秒 + 視訊質量不能太低 + 視訊大小不能超過5M; 2、方案 呼叫系統相機和自定義相機; 1、呼叫系統相機(不滿足需求) 視訊質量只能設定高(1)和低(0),高的話,拍出來的視訊太大;低的話,拍出來的視訊大小滿足,但是質量慘不忍睹;而且
Android自定義相機拍的照片不清楚解決方案
最近做一個專案要用到自定義相機,預覽的時候挺清晰的,但是拍好之後就變模糊了,弄了大半天才解決。 相機照片的尺寸只有幾種固定的,2592×1936,2048×1536,1600×1200,1024×768,320×240等,這些尺寸還要物理裝置支援才有。設定照片的尺寸(當然要
android 自定義相機旋轉問題解決及照片自動旋轉問題解決
//自動旋轉180情況下 myCamera = Camera.open(); myCamera .setDisplayOrientation(180); //圖片旋轉180情況下解決方法 par
Android自定義相機(三) —— 錄影
前面我們已經大致完成了自定義相機的拍照功能,接下來,我們來實現一下錄影的功能。 1、錄影功能簡介 錄影功能的是相對比較簡單,因為步驟是很固定的,google給我們提供的api文件中說的也比較詳細,這裡我們主要用到 MediaRecorder 這個類。
android 自定義相機Camera
專案中,有時系統的相機不能滿足我們的需求,例如:實現美圖,這樣就需要我們進行自定義相機,滿足我們的特殊需求。Android給我們提供了Camera API,可以進行相機的私人訂製。在Android5以後有提供了Camera2 API,廢除了Camera API。但Camera
Android自定義相機實現拍照、預覽、顯示、上傳
自定義相機拍照並存放到本地,可以預覽,用okHttp上傳到伺服器 用法 1.點選登入進入到拍照頁面 2.拍照後進入到上傳介面,需要在Constant中修改BASE_URL為自己伺服器圖片上傳地
Android 自定義相機獲取照片(螢幕適配)
1.在應用程式中自定義相機拍照的大體步驟如下: 1.檢測和訪問相機:檢測裝置是否支援拍照,然後發出訪問裝置相機請求。 2.建立一個預覽類:建立一個繼承自類SurfaceView和實現介面SurfaceHolder介面的相機預覽類,這個類用來預覽從相機得到
android自定義相機、連續(自動)聚焦、點選(觸控)聚焦、變焦、拍照後自定義裁剪、旋轉
最近做了一個圖片識別、以及搜尋的小專案,其中有一個模組是拍照以及拍照後對圖片進行剪下,開始用的系統的相機和裁剪,由於系統的相機和裁剪多出了一些不必要的步驟和啟動慢等等帶給使用者的體驗不好,故自己寫了一個,下面給大家簡要介紹下: 自定義相機:定義SurfaceView得到Su
Android自定義相機,帶邊框截圖
專案需求:要實現自定義拍照介面,並且只取框框中的內容。 問題點:1、通過Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)方式自動對焦,沒有實現觸控對焦 2、myParameters.setPreview