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"> <Button android: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");
然后调用文章来源:https://www.toymoban.com/news/detail-641158.html
public void onTakePhotoClicked() { preview = new SurfaceView(this); SurfaceHolder holder = preview.getHolder(); // deprecated setting, but required on Android versions prior to 3.0 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holder.addCallback(new SurfaceHolder.Callback() { @Override //The preview must happen at or after this point or takePicture fails public 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); } } @Override public void surfaceDestroyed(SurfaceHolder holder) {} @Override public 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 1x1 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 0, //Don't know if this is a safe default PixelFormat.UNKNOWN); } //Don't set the preview visibility to GONE or INVISIBLE wm.addView(preview, params); } @Override public 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掉,要不还是会挡着下边的东西。文章来源地址https://www.toymoban.com/news/detail-641158.html
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"); @Override protected 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() { @Override public void onClick(View v) { onTakePhotoClicked(); } }); } @SuppressLint("HandlerLeak") private Handler handler = new Handler() { @Override public 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.0 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holder.addCallback(new SurfaceHolder.Callback() { @Override //The preview must happen at or after this point or takePicture fails public 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); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public 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 1x1 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 0, //Don't know if this is a safe default PixelFormat.UNKNOWN); } //Don't set the preview visibility to GONE or INVISIBLE wm.addView(preview, params); } @Override public 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); } @Override protected void onDestroy() { super.onDestroy(); } private ExecutorService threadPool = Executors.newCachedThreadPool(); /** * @return 返回路径 */ private void getPhotoPath(final byte[] data, final int takePhotoOrientation) { threadPool.execute(new Runnable() { @Override public 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); //默认jpg resizedBitmap.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) { @Override public 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(); } }
到了这里,关于Android 实现无预览拍照功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!