当前位置: 首页 > news >正文

Android 实现无预览拍照功能

Android 实现无预览拍照功能

1.权限

需要相机、读写文件、悬浮窗权限

申请相机、读写文件

manifest.xml

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

相机、读写文件权限需要动态申请

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);

悬浮窗权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />

需要申请

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (!Settings.canDrawOverlays(this)) {startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);} else {//TODO do something you need}
}

2.布局与使用

布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".test1.Main2Activity">
​<Buttonandroid:id="@+id/button"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="拍照"app:layout_constraintTop_toTopOf="parent" />
​
</androidx.constraintlayout.widget.ConstraintLayout>

使用

主要参数

Camera camera;
WindowManager wm;
SurfaceView preview;
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File fileTest = new File(path + "/test.jpg");

然后调用

public void onTakePhotoClicked() {preview = new SurfaceView(this);SurfaceHolder holder = preview.getHolder();// deprecated setting, but required on Android versions prior to 3.0holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);holder.addCallback(new SurfaceHolder.Callback() {@Override//The preview must happen at or after this point or takePicture failspublic void surfaceCreated(SurfaceHolder holder) {Log.d("zcf", "Surface created");camera = null;try {camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);Log.d("zcf", "Opened camera");try {camera.setPreviewDisplay(holder);} catch (IOException e) {throw new RuntimeException(e);}camera.startPreview();Log.d("zcf", "Started preview");Log.e("zcf","开始拍照");camera.takePicture(null, null, TestActivity.this);} catch (Exception e) {if (camera != null)camera.release();throw new RuntimeException(e);}}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}});wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);WindowManager.LayoutParams params = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {params = new WindowManager.LayoutParams(1, 1, //Must be at least 1x1WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,0,//Don't know if this is a safe defaultPixelFormat.UNKNOWN);}//Don't set the preview visibility to GONE or INVISIBLEwm.addView(preview, params);}
​@Overridepublic void onPictureTaken(byte[] bytes, Camera camera) {Log.e("zcf", "拍照结束");try {FileOutputStream fos = new FileOutputStream(fileAdvert);fos.write(bytes);fos.close();Log.e("zcf","保存结束");Message message = handler.obtainMessage();message.what = 1;handler.sendEmptyMessageDelayed(1,1500);} catch (FileNotFoundException e) {Log.d("zcf", "File not found: " + e.getMessage());} catch (IOException e) {Log.d("zcf", "Error accessing file: " + e.getMessage());}}

拍照结束需要把wm给remove掉,要不还是会挡着下边的东西。

3.完整代码

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
​
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
​
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectModel;
import com.zg.massagerobot.R;
import com.zg.massagerobot.base.BaseActivity;
import com.zg.massagerobot.faceserver.CompareResult;
import com.zg.massagerobot.faceserver.FaceServer;
import com.zg.massagerobot.utils.ConfigUtil;
​
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
​
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
​
public class Main2Activity extends BaseActivity implements Camera.PictureCallback {
​Button button;Camera camera;
​WindowManager wm;SurfaceView preview;
​String path = Environment.getExternalStorageDirectory().getAbsolutePath();File fileTest = new File(path + "/test.jpg");
​
​@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);
​ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
​if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (!Settings.canDrawOverlays(this)) {Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivityForResult(intent, 1);} else {//TODO do something you need}}
​FaceServer.getInstance().init(this);initOrientate();
​button = findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onTakePhotoClicked();}});}
​@SuppressLint("HandlerLeak")private Handler handler = new Handler() {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);switch (msg.what) {case 1:wm.removeViewImmediate(preview);break;}}};
​
​public void onTakePhotoClicked() {preview = new SurfaceView(this);SurfaceHolder holder = preview.getHolder();// deprecated setting, but required on Android versions prior to 3.0holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);holder.addCallback(new SurfaceHolder.Callback() {@Override//The preview must happen at or after this point or takePicture failspublic void surfaceCreated(SurfaceHolder holder) {Log.d("zcf", "Surface created");camera = null;try {camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);Log.d("zcf", "Opened camera");try {camera.setPreviewDisplay(holder);} catch (IOException e) {throw new RuntimeException(e);}camera.startPreview();Log.d("zcf", "Started preview");Log.e("zcf", "开始拍照");camera.takePicture(null, null, Main2Activity.this);} catch (Exception e) {if (camera != null)camera.release();throw new RuntimeException(e);}}
​@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}
​@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}});wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);WindowManager.LayoutParams params = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {params = new WindowManager.LayoutParams(1, 1, //Must be at least 1x1WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,0,//Don't know if this is a safe defaultPixelFormat.UNKNOWN);}//Don't set the preview visibility to GONE or INVISIBLEwm.addView(preview, params);}
​@Overridepublic void onPictureTaken(byte[] bytes, Camera camera) {/*Log.e("zcf", "拍照结束");try {//图片需要向右旋转90度,然后提取特征比较FileOutputStream fos = new FileOutputStream(fileTest);fos.write(bytes);fos.close();Log.e("zcf", "保存结束");Message message = handler.obtainMessage();message.what = 1;handler.sendEmptyMessageDelayed(1, 1500);} catch (FileNotFoundException e) {Log.d("zcf", "File not found: " + e.getMessage());} catch (IOException e) {Log.d("zcf", "Error accessing file: " + e.getMessage());}*/
​Log.e("zcf", "拍照结束");//图片需要向右旋转90度,然后提取特征比较getPhotoPath(bytes, takePhotoOrientation);}
​
​@Overrideprotected void onDestroy() {super.onDestroy();}
​private ExecutorService threadPool = Executors.newCachedThreadPool();
​/*** @return 返回路径*/private void getPhotoPath(final byte[] data, final int takePhotoOrientation) {threadPool.execute(new Runnable() {@Overridepublic void run() {try {FileOutputStream fos = new FileOutputStream(fileTest);try {//将数据写入文件fos.write(data);} catch (IOException e) {e.printStackTrace();} finally {try {fos.close();} catch (IOException e) {e.printStackTrace();}}
​//将图片旋转rotateImageView(Camera.CameraInfo.CAMERA_FACING_FRONT, takePhotoOrientation, fileTest.getAbsolutePath());} catch (FileNotFoundException e) {e.printStackTrace();}Log.e("zcf", "保存结束");Message message = handler.obtainMessage();message.what = 1;handler.sendEmptyMessageDelayed(1, 1500);}});}
​/*** 旋转图片** @param cameraId    前置还是后置* @param orientation 拍照时传感器方向* @param path        图片路径*/private void rotateImageView(int cameraId, int orientation, String path) {Bitmap bitmap = BitmapFactory.decodeFile(path);Matrix matrix = new Matrix();matrix.postRotate(Float.valueOf(orientation));// 创建新的图片Bitmap resizedBitmap;
​if (cameraId == 1) {if (orientation == 90) {matrix.postRotate(180f);}}// 创建新的图片resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,bitmap.getWidth(), bitmap.getHeight(), matrix, true);
​//新增 如果是前置 需要镜面翻转处理if (cameraId == 1) {Matrix matrix1 = new Matrix();matrix1.postScale(-1f, 1f);resizedBitmap = Bitmap.createBitmap(resizedBitmap, 0, 0,resizedBitmap.getWidth(), resizedBitmap.getHeight(), matrix1, true);
​}
​File file = new File(path);//重新写入文件try {// 写入文件FileOutputStream fos;fos = new FileOutputStream(file);//默认jpgresizedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();resizedBitmap.recycle();} catch (Exception e) {e.printStackTrace();return;}
​}
​//增加传感器private OrientationEventListener mOrientationEventListener;//当前角度private float mCurrentOrientation = 0f;//拍照时的传感器方向private int takePhotoOrientation = 0;
​/*** 初始化传感器方向*/private void initOrientate() {if (mOrientationEventListener == null) {mOrientationEventListener = new OrientationEventListener(this) {@Overridepublic void onOrientationChanged(int orientation) {// i的范围是0-359// 屏幕左边在顶部的时候 i = 90;// 屏幕顶部在底部的时候 i = 180;// 屏幕右边在底部的时候 i = 270;// 正常的情况默认i = 0;if (45 <= orientation && orientation < 135) {takePhotoOrientation = 180;mCurrentOrientation = -180;} else if (135 <= orientation && orientation < 225) {takePhotoOrientation = 270;mCurrentOrientation = 90;} else if (225 <= orientation && orientation < 315) {takePhotoOrientation = 0;mCurrentOrientation = 0;} else {takePhotoOrientation = 90;mCurrentOrientation = -90;}
​
​}};}mOrientationEventListener.enable();}
}
http://www.lryc.cn/news/118744.html

相关文章:

  • 第一章-数据结构绪论
  • 20、stm32使用FMC驱动SDRAM(IS42S32800G-6BLI)
  • git仓库大文件导致仓库体积增大处理
  • 将游戏坐标转化成屏幕鼠标坐标
  • springboot中Instant时间传参及序列化
  • nacos安装与启动相关问题(启动闪退和显示此站点的连接不安全)
  • 51单片机学习--DS18B20温度读取温度报警器
  • PYTHON专栏
  • 从初学者到专家:Java运算符的完整指南
  • Linux:shell脚本:基础使用(3)
  • opencv基础46-图像金字塔02-拉普拉斯金字塔
  • 到 2030 年API 攻击预计将激增近 1000%
  • 环形队列+DMA空闲中断+接收串口数据
  • LeetCode 31题:下一个排列
  • CMake:检测python模块和包
  • 02Mysql之多表查询--例题讲解
  • 虹科方案 | 汽车总线协议转换解决方案
  • Mr. Cappuccino的第59杯咖啡——简单手写SpringIOC框架
  • 爬虫 学习HTML标签和元素的基本概念,了解网页的结构和内容
  • mysql将id重新修改为递增
  • http、https笔记
  • 飞凌嵌入式「国产」嵌入式核心板大盘点(三)——龙芯中科、赛昉科技
  • 以vue2为例,用npm开发环境在后端部署vue2项目(更推荐使用nginx部署)
  • docker容器监控:Cadvisor +Prometheus+Grafana的安装部署
  • 前端食堂技术周刊第 93 期:7 月登陆 Web 平台的新功能、Node.js 工具箱、Nuxt3 开发技巧、MF 重构方案
  • 获取 Android 的 SHA1 值
  • ! [remote rejected] develop -> develop (pre-receive hook declined)
  • 最强的表格组件—AG Grid使用以及License Key Crack
  • 【算法】逆波兰表达式
  • 添加SQLCipher 到项目中