使用OpenCV4Android时的动态权限获取
2017-10-26 08:51
447 查看
Android6.0之后,一些危险权限不仅要在配置文件中列出(在安装应用时由用户确认),还需要加入动态申请权限代码,从而在运行应用时询问用户以获得动态授权。
OpenCV4Android运行时需要摄像头权限也需要动态申请。
动态权限的申请主要参考Android6.0动态权限申请
特别注意OpenCV4Android的初始化和权限获取之间的顺序:
JavaCameraView对象赋值
动态权限申请
OpenCV组件初始化
代码如下:
OpenCV4Android运行时需要摄像头权限也需要动态申请。
动态权限的申请主要参考Android6.0动态权限申请
特别注意OpenCV4Android的初始化和权限获取之间的顺序:
JavaCameraView对象赋值
动态权限申请
OpenCV组件初始化
代码如下:
package cn.daizhe.opencv4androiddemo; import android.Manifest; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.View; import android.widget.Button; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.CameraBridgeViewBase; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfFloat; import org.opencv.core.MatOfInt; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; import java.util.Arrays; import cn.daizhe.opencv4androiddemo.activity.PermissionsActivity; public class MainActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 { private static final int REQUEST_CODE = 0; // 申请权限的请求码 // 所需的全部权限 static final String[] PERMISSIONS = new String[]{ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private String TAG = "OpenCV_Test"; //OpenCV的相机接口 private CameraBridgeViewBase mCVCamera; //缓存相机每帧输入的数据 private Mat mRgba, mTmp; //按钮组件 private Button mButton; //当前处理状态 private static int Cur_State = 0; private Size mSize0; private Mat mIntermediateMat; private MatOfInt mChannels[]; private MatOfInt mHistSize; private int mHistSizeNum = 25; private Mat mMat0; private float[] mBuff; private MatOfFloat mRanges; private Point mP1; private Point mP2; private Scalar mColorsRGB[]; private Scalar mColorsHue[]; private Scalar mWhilte; private Mat mSepiaKernel; /** * 通过OpenCV管理Android服务,异步初始化OpenCV */ BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: Log.i(TAG, "OpenCV loaded successfully"); mCVCamera.enableView(); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // OpenCV摄像头组件 mCVCamera = (CameraBridgeViewBase) findViewById(R.id.camera_view); mCVCamera.setCvCameraViewListener(this); // 打开前置摄像头 mCVCamera.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT); mButton = (Button) findViewById(R.id.deal_btn); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Cur_State < 8) { //切换状态 Cur_State++; } else { //恢复初始状态 Cur_State = 0; } } }); // 获取权限 permissionSetting(); } @Override public void onResume() { super.onResume(); } /** * 初始化OpenCV */ private void initOpenCV() { if (!OpenCVLoader.initDebug()) { Log.d(TAG, "OpenCV library not found!"); } else { Log.d(TAG, "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); } } /** * 权限设置 */ private void permissionSetting() { boolean isAllGranted = checkPermissionAllGranted( PERMISSIONS ); // 如果这3个权限全都拥有, 则直接初始化OpenCV if (isAllGranted) { initOpenCV(); return; } // 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉 // 将自动弹出授权对话框 ActivityCompat.requestPermissions( this, PERMISSIONS, REQUEST_CODE ); } /** * 检查授权状态 * * @param permissions * @return */ private boolean checkPermissionAllGranted(String[] permissions) { for (String permission : permissions) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { // 只要有一个权限没有被授予, 则直接返回 false return false; } } return true; } /** * 授权回掉函数 * * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE) { boolean isAllGranted = true; // 判断是否所有的权限都已经授予了 for (int grant : grantResults) { if (grant != PackageManager.PERMISSION_GRANTED) { isAllGranted = false; break; } } if (isAllGranted) { // 如果所有的权限都授予了, 则初始化OpenCV initOpenCV(); } else { // 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮 openAppDetails(); } } } private void openAppDetails() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("备份通讯录需要访问 “摄像头”权限,请到 “应用信息 -> 权限” 中授予!"); builder.setPositiveButton("去手动授权", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent); } }); builder.setNegativeButton("取消", null); builder.show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 拒绝时, 关闭页面, 缺少主要权限, 无法运行 if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) { finish(); } } @Override public void onDestroy() { super.onDestroy(); if (mCVCamera != null) { mCVCamera.disableView(); } } /** * 相机开始时调用 * @param width - the width of the frames that will be delivered * @param height - the height of the frames that will be delivered */ @Override public void onCameraViewStarted(int width, int height) { // TODO Auto-generated method stub mRgba = new Mat(height, width, CvType.CV_8UC4); mTmp = new Mat(height, width, CvType.CV_8UC4); mIntermediateMat = new Mat(); mSize0 = new Size(); mChannels = new MatOfInt[]{new MatOfInt(0), new MatOfInt(1), new MatOfInt(2)}; mBuff = new float[mHistSizeNum]; mHistSize = new MatOfInt(mHistSizeNum); mRanges = new MatOfFloat(0f, 256f); mMat0 = new Mat(); mColorsRGB = new Scalar[]{new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255)}; mColorsHue = new Scalar[]{ new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255), new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255), new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255), new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255), new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255) }; mWhilte = Scalar.all(255); mP1 = new Point(); mP2 = new Point(); // Fill sepia kernel mSepiaKernel = new Mat(4, 4, CvType.CV_32F); mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f); mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f); mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f); mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f); } @Override public void onCameraViewStopped() { // TODO Auto-generated method stub mRgba.release(); mTmp.release(); } /** * 图像处理都写在此处 */ @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Size sizeRgba = mRgba.size(); int rows = (int) sizeRgba.height; int cols = (int) sizeRgba.width; Mat rgbaInnerWindow; int left = cols / 8; int top = rows / 8; int width = cols * 3 / 4; int height = rows * 3 / 4; switch (Cur_State) { case 1: //灰化处理 Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4); break; case 2: //Canny边缘检测 mRgba = inputFrame.rgba(); Imgproc.Canny(inputFrame.gray(), mTmp, 80, 100); Imgproc.cvtColor(mTmp, mRgba, Imgproc.COLOR_GRAY2RGBA, 4); break; case 3: //Hist直方图计算 Mat hist = new Mat(); int thikness = (int) (sizeRgba.width / (mHistSizeNum + 10) / 5); if (thikness > 5) thikness = 5; int offset = (int) ((sizeRgba.width - (5 * mHistSizeNum + 4 * 10) * thikness) / 2); // RGB for (int c = 0; c < 3; c++) { Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, hist, mHistSize, mRanges); Core.normalize(hist, hist, sizeRgba.height / 2, 0, Core.NORM_INF); hist.get(0, 0, mBuff); for (int h = 0; h < mHistSizeNum; h++) { mP1.x = mP2.x = offset + (c * (mHistSizeNum + 10) + h) * thikness; mP1.y = sizeRgba.height - 1; mP2.y = mP1.y - 2 - (int) mBuff[h]; Imgproc.line(mRgba, mP1, mP2, mColorsRGB[c], thikness); } } // Value and Hue Imgproc.cvtColor(mRgba, mTmp, Imgproc.COLOR_RGB2HSV_FULL); // Value Imgproc.calcHist(Arrays.asList(mTmp), mChannels[2], mMat0, hist, mHistSize, mRanges); Core.normalize(hist, hist, sizeRgba.height / 2, 0, Core.NORM_INF); hist.get(0, 0, mBuff); for (int h = 0; h < mHistSizeNum; h++) { mP1.x = mP2.x = offset + (3 * (mHistSizeNum + 10) + h) * thikness; mP1.y = sizeRgba.height - 1; mP2.y = mP1.y - 2 - (int) mBuff[h]; Imgproc.line(mRgba, mP1, mP2, mWhilte, thikness); } break; case 4: //Sobel边缘检测 Mat gray = inputFrame.gray(); Mat grayInnerWindow = gray.submat(top, top + height, left, left + width); rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width); Imgproc.Sobel(grayInnerWindow, mIntermediateMat, CvType.CV_8U, 1, 1); Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0); Imgproc.cvtColor(mIntermediateMat, rgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4); grayInnerWindow.release(); rgbaInnerWindow.release(); break; case 5: //SEPIA(色调变换) rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width); Core.transform(rgbaInnerWindow, rgbaInnerWindow, mSepiaKernel); rgbaInnerWindow.release(); break; case 6: //ZOOM放大镜 Mat zoomCorner = mRgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10); Mat mZoomWindow = mRgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100); Imgproc.resize(mZoomWindow, zoomCorner, zoomCorner.size()); Size wsize = mZoomWindow.size(); Imgproc.rectangle(mZoomWindow, new Point(1, 1), new Point(wsize.width - 2, wsize.height - 2), new Scalar(255, 0, 0, 255), 2); zoomCorner.release(); mZoomWindow.release(); break; case 7: //PIXELIZE像素化 rgbaInnerWindow = mRgba.submat(top, top + height, left, left + width); Imgproc.resize(rgbaInnerWindow, mIntermediateMat, mSize0, 0.1, 0.1, Imgproc.INTER_NEAREST); Imgproc.resize(mIntermediateMat, rgbaInnerWindow, rgbaInnerWindow.size(), 0., 0., Imgproc.INTER_NEAREST); rgbaInnerWindow.release(); break; default: //显示原图 mRgba = inputFrame.rgba(); break; } //返回处理后的结果数据 return mRgba; } }
相关文章推荐
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- 对android 6.0 动态获取权限框架 PermissionDispatcher 的使用
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- android 6.0 动态获取权限框架 PermissionDispatcher 的使用
- Android使用easypermission动态获取权限
- PC端使用opencv获取webcam,通过socket把Mat图像传输到android手机端
- 在Android 6.0 设备上动态获取权限
- Android_在Android 6.0设备上动态获取权限
- android之使用signapk打包成系统应用,获取系统权限
- Android 6.0动态获取权限开源项目
- Android M动态申请获取权限android.permission.READ_PHONE_STATE
- Android 广播BroadcastReceiver静态/动态注册,获取系统电量广播【开机广播】,获取网络状态广播,Timer的使用简介
- Android 6.0获取IMEI号是出错,动态获取权限
- 使用Android内部的DownloadProvider下载文件,并获取cache权限
- Android开发动态获取权限(6.0以上API>23)
- Android 6.0动态权限的获取
- android 学习笔记之六 动态获取权限
- Android动态获取资源ID并使用javabean进行赋值
- Android之API 23动态获取权限完美解决
- Android 6.0 中动态获取权限