Android 实现无预览拍照功能

这篇具有很好参考价值的文章主要介绍了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">
​
    <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");

然后调用

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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 11.0 MTK Camera2 设置默认拍照尺寸功能实现

    在11.0的系统rom定制化开发中,在mtk平台的camera2关于拍照的一些功能修改中,在一些平台默认需要设置最大的分辨率 来作为拍照的分辨率,所以就需要了解拍照尺寸设置流程,然后来实现相关的功能 如图: Camera API中主要涉及以下几个关键类 CameraManager:相机的实际管理者,调

    2024年01月21日
    浏览(45)
  • Android 12.0 MTK Camera2 设置默认拍照尺寸功能实现

    在12.0的系统rom定制化开发中,在mtk平台的camera2关于拍照的一些功能修改中,在一些平台默认需要设置最大的分辨率 来作为拍照的分辨率,所以就需要了解拍照尺寸设置流程,然后来实现相关的功能 如图:

    2024年02月20日
    浏览(55)
  • Android Camera2(1)-Camera2在textureView中的预览和拍照

    解释上诉示意图,假如想要同时拍摄两张不同尺寸的图片,并且在拍摄过程中闪光灯必须亮起来。整个拍摄流程如下: 创建一个用于从 Pipeline 获取图片的 CaptureRequest。 修改 CaptureRequest 的闪光灯配置,让闪光灯在拍照过程中亮起来。 创建两个不同尺寸的 Surface 用于接收图片

    2024年02月05日
    浏览(47)
  • Android多媒体功能开发(12)——使用Camera类拍照

    Android上用摄像头拍照、录视频有两套API可用,Android5.0(API21)之前使用android.hardware.Camera类,之后推荐使用android.hardware.camera2包。目前这两套API都可以使用,Camera类用起来比较简单易懂,但功能少灵活性差,所以现在降级使用;Camera2框架功能强大,对摄像头的控制灵活,但由于

    2023年04月13日
    浏览(32)
  • Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能

    CameraX是JetPack库之一,通过CameraX可以向应用增加相机的功能。在下列内容中,将介绍一个结合CameraX实现一个简单的拍照应用。本应用必须采用Android SDK 34。并通过该简单示例,了解传统View层次组件的UI组件如何与Compose组件结合实现移动应用界面的定制。 首先,新建一个项目

    2024年02月08日
    浏览(32)
  • Android 9.0 Camera2 拍照功能默认选前摄像头

     在9.0的系统产品开发中,对于app调用系统api来打开摄像头拍照的功能也是常有的功能,而拍照一般是默认打开后置摄像头拍照的,由于 客户的产品特殊要求,需要打开前置摄像头拍照功能,所以需要了解拍照功能的流程,然后修改默认前置摄像头打开拍照功能就可以了 ap

    2024年02月03日
    浏览(55)
  • Android 11.0 Camera2 拍照功能默认选前摄像头

     在11.0的系统rom产品开发中,对于app调用系统api来打开摄像头拍照的功能也是常有的功能,而拍照一般是默认打开后置摄像头拍照的,由于 客户的产品特殊要求,需要打开前置摄像头拍照功能,所以需要了解拍照功能的流程,然后修改默认前置摄像头打开拍照功能就可以了

    2024年02月07日
    浏览(37)
  • Android 13.0 Camera2 拍照功能默认选前摄像头

     在13.0的系统rom产品定制化开发中,对于app调用系统api来打开摄像头拍照的功能也是常有的功能,而拍照一般是默认打开后置摄像头拍照的,由于 客户的产品特殊要求,需要打开前置摄像头拍照功能,所以需要了解拍照功能的流程,然后修改默认前置摄像头打开拍照功能就可

    2024年01月24日
    浏览(43)
  • 十分钟实现 Android Camera2 相机拍照

    因为工作中要使用 Android Camera2 API ,但因为 Camera2 比较复杂,网上资料也比较乱,有一定入门门槛,所以花了几天时间系统研究了下,并在 CSDN 上记录了下,希望能帮助到更多的小伙伴。 上篇文章 我们使用 Camera2 实现了相机预览的功能,这篇文章我们接着上文,来实现 Cam

    2024年02月11日
    浏览(42)
  • 【Android】一步步实现手机拍照、录像及存储至相册(CameraX)

    参考资料 https://developer.android.google.cn/codelabs/camerax-getting-started?hl=zh-cn#0 https://developer.android.google.cn/training/camerax/video-capture?hl=zh-cn //https://blog.csdn.net/teolih/article/details/120423971 对应视频及项目代码 【项目代码】https://gitee.com/hellosunshine/camerax_android_java.git 步骤(java版本) 基本功能

    2024年02月07日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包