RK Android7.1 Camera2 预览、内置客户SDK预览

 一.预览

1.SurfaceView 

  activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <SurfaceView
        android:id="@+id/sfv_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

 AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gatsby.ypcamerdemo">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.YpCamerDemo">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>  

Mainactivity.java

package com.gatsby.ypcamerdemo;

import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private SurfaceView sfv_preview;
    private Camera camera = null;
    private SurfaceHolder.Callback cpHolderCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            startPreview();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            stopPreview();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }

    private void bindViews() {
        sfv_preview = (SurfaceView) findViewById(R.id.sfv_preview);
        sfv_preview.getHolder().addCallback(cpHolderCallback);
    }

    //开始预览
    private void startPreview() {
        camera = Camera.open();
        try {
            camera.setPreviewDisplay(sfv_preview.getHolder());
            camera.setDisplayOrientation(0);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //停止预览
    private void stopPreview() {
        camera.stopPreview();
        camera.release();
        camera = null;
    }

}

2.TextureView

  • CameraManager: 管理手机上的所有摄像头设备,它的作用主要是获取摄像头列表和打开指定的摄像头
  • CameraDevice: 具体的摄像头设备,它有一系列参数(预览尺寸、拍照尺寸等),可以通过CameraManager的getCameraCharacteristics()方法获取。它的作用主要是创建CameraCaptureSession和CaptureRequest
  • CameraCaptureSession: 相机捕获会话,用于处理拍照和预览的工作(很重要)
  • CaptureRequest: 捕获请求,定义输出缓冲区以及显示界面(TextureView或SurfaceView)等  

activity_main.xml   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextureView
        android:id="@+id/textureview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Mainactivity.java

package com.gatsby.textureviewtest;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    private TextureView textureView;
    private String TAG="Gatsby";

    private HandlerThread mThreadHandler;
    private Handler mHandler;

    private CaptureRequest.Builder mPreviewBuilder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mThreadHandler = new HandlerThread("CAMERA2");
        mThreadHandler.start();
        mHandler = new Handler(mThreadHandler.getLooper());

        textureView= (TextureView) findViewById(R.id.textureview);
        textureView.setSurfaceTextureListener(textureListener);

    }

    private TextureView.SurfaceTextureListener textureListener=new TextureView.SurfaceTextureListener() {
        @SuppressLint("MissingPermission")
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
            Log.e(TAG,"可用");

            //CameraManaer 摄像头管理器,用于检测摄像头,打开系统摄像头
            CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
            try {
                String[] CameraIdList=cameraManager.getCameraIdList();//获取可用相机列表
                Log.e(TAG,"可用相机的个数是:"+CameraIdList.length);
                //获取某个相机(摄像头特性)
                CameraCharacteristics cameraCharacteristics=cameraManager.getCameraCharacteristics(CameraIdList[0]);
                cameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);//检查支持
                cameraManager.openCamera(CameraIdList[0],mCameraDeviceStateCallback, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
            Log.e(TAG,"change");
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            Log.e(TAG,"destroy");
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
            Log.e(TAG,"update");
        }
    };

    //CameraDeviceandroid.hardware.Camera也就是Camera1的Camera
    private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(CameraDevice camera) {
            try {
                startPreview(camera);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(CameraDevice camera) {

        }

        @Override
        public void onError(CameraDevice camera, int error) {

        }
    };

    /**
     * @param camera
     * @throws CameraAccessException
     * 开始预览
     */
    private void startPreview(CameraDevice camera) throws CameraAccessException {
        SurfaceTexture texture = textureView.getSurfaceTexture();
        texture.setDefaultBufferSize(textureView.getWidth(), textureView.getHeight());
        Surface surface = new Surface(texture);
        try {
            //CameraRequest表示一次捕获请求,用来对z照片的各种参数设置,比如对焦模式、曝光模式等。CameraRequest.Builder用来生成CameraRequest对象
            mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        mPreviewBuilder.addTarget(surface);
        camera.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, mHandler);
    }

    //CameraCaptureSession 这个对象控制摄像头的预览或者拍照
    //setRepeatingRequest()开启预览,capture()拍照
    //StateCallback监听CameraCaptureSession的创建
    private CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(CameraCaptureSession session) {
            Log.e(TAG,"相机创建成功!");
            try {
                session.capture(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);//拍照
                session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);//返回结果
            } catch (CameraAccessException e) {
                e.printStackTrace();
                Log.e(TAG,"这里异常");
            }
        }

        @Override
        public void onConfigureFailed(CameraCaptureSession session) {
            Log.e(TAG,"相机创建失败!");
        }
    };


    //CameraCaptureSession.CaptureCallback监听拍照过程
    private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {

        @Override
        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
            Log.e(TAG,"这里接受到数据"+result.toString());
        }

        @Override
        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult){

        }};
}

 

二.Android camera2预览界面流程  https://blog.csdn.net/fireness/article/details/50594706

2.1.找到布局

activity_main.xml

<com.android.camera.ui.MainActivityLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_root_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@null">

    <include layout="@layout/camera" />
    <include layout="@layout/camera_filmstrip" />
    <com.android.camera.ui.ModeTransitionView
        android:id="@+id/mode_transition_view"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.android.camera.ui.MainActivityLayout>

 预览布局 camera.xml 

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/camera_app_root"
    android:background="@android:color/black"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextureView
        android:id="@+id/preview_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

2.1.CameraActivity.java  onCreateTasks() 准备预览mCameraAppUI.prepareModuleUI();

   packages\apps\Camera2\src\com\android\camera\app\CameraAppUI.java 

    public void prepareModuleUI() {
        mController.getSettingsManager().addListener(this);
        mModuleUI = (FrameLayout) mCameraRootView.findViewById(R.id.module_layout);
        mTextureView = (TextureView) mCameraRootView.findViewById(R.id.preview_content);
        mTextureViewHelper = new TextureViewHelper(mTextureView, mCaptureLayoutHelper,
                mController.getCameraProvider(), mController);
        mTextureViewHelper.setSurfaceTextureListener(this);
        mTextureViewHelper.setOnLayoutChangeListener(mPreviewLayoutChangeListener);

2.3.TextureViewHelper 初始化 

packages\apps\Camera2\src\com\android\camera\TextureViewHelper.java

    public TextureViewHelper(TextureView preview, CaptureLayoutHelper helper,
            CameraProvider cameraProvider, AppController appController) {
        mPreview = preview;
        mCameraProvider = cameraProvider;
        mPreview.addOnLayoutChangeListener(this);
        mPreview.setSurfaceTextureListener(this);
        mCaptureLayoutHelper = helper;
        mAppController = appController;
        mCameraModeId = appController.getAndroidContext().getResources()
                .getInteger(R.integer.camera_mode_photo);
        mCaptureIntentModeId = appController.getAndroidContext().getResources()
                .getInteger(R.integer.camera_mode_capture_intent);
    } 

 还要去实现  implements TextureView.SurfaceTextureListener

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        // Workaround for b/11168275, see b/10981460 for more details
        if (mWidth != 0 && mHeight != 0) {
            // Re-apply transform matrix for new surface texture
            updateTransform();
        }
        if (mSurfaceTextureListener != null) {
            mSurfaceTextureListener.onSurfaceTextureAvailable(surface, width, height);
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        if (mSurfaceTextureListener != null) {
            mSurfaceTextureListener.onSurfaceTextureSizeChanged(surface, width, height);
        }
    }

packages\apps\Camera2\src\com\android\camera\PhotoUI.java

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mController.onPreviewUIReady();
    }

2.4.packages\apps\Camera2\src\com\android\camera\PhotoModule.java 

    @Override
    public void onPreviewUIReady() {
        Log.i(TAG, "onPreviewUIReady");
        startPreview();
    }

    private void startPreview() {
        if (mCameraDevice == null) {
            Log.i(TAG, "attempted to start preview before camera device");
            // do nothing
            return;
        }

…………………………
        Log.i(TAG, "startPreview");
        // If we're using API2 in portability layers, don't use startPreviewWithCallback()
        // b/17576554
        CameraAgent.CameraStartPreviewCallback startPreviewCallback =
            new CameraAgent.CameraStartPreviewCallback() {
                @Override
                public void onPreviewStarted() {
                    mFocusManager.onPreviewStarted();
                    PhotoModule.this.onPreviewStarted();
                    SessionStatsCollector.instance().previewActive(true);
                    if (mSnapshotOnIdle
                            || (mAppController.getSettingsManager().getBoolean
                            (SettingsManager.SCOPE_GLOBAL, Keys.KEY_SMILE_SHUTTER_ON)
                            && DebugPropertyHelper.isSmileShutterAuto())) {
                        mHandler.postDelayed(mDoSmileShutterRunnable, 2000);
                    }
                }
            };

  

 三.内置SDK 预览

3.1.客户demo

    private var mSurfaceTexture: SurfaceTexture? = null
    private var mSurface: Surface? = null


    private val mSurfaceTextureListener: SurfaceTextureListener = object : SurfaceTextureListener {
        override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
            mSurfaceTexture = surface
        }

        override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
            mSurfaceTexture = surface
        }

        override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
            mSurfaceTexture = surface
            return false
        }

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
            mSurfaceTexture = surface
        }
    }


    private fun initView() {
        if (mSurface == null && mSurfaceTexture != null) {
            mSurface = Surface(mSurfaceTexture)
        }

        mYpDevicesManager = YpDevicesManager.getInstance()
        mYpDevicesManager?.setContext(this)
        mYpDevicesManager?.setCodereaderCameraView(mSurface)

3.2.客户是特殊的USB3.0摄像头 走的不是 Camera open(int cameraId) 方法  而Camera2 预览走的流程是标准的 open方法
原计划是在Camera2 预览控件TextureView做动作 现在不走open 表示要大改预览框架

08-17 16:17:35.796 E/CameraService(  244): No camera be found ! check again...
08-17 16:17:35.796 I/CameraService(  244): CameraService process starting
08-17 16:17:35.797 I/CAM2PORT_AndCamAgntImp( 1442): Opening camera 0 with camera1 API
08-17 16:17:35.797 D/CameraHal(  244): Calling process is: com.android.camera2
08-17 16:17:35.798 I/CameraService(  244): CameraService::connect call (PID -1 "com.android.camera2", camera ID 0) for HAL version default and Camera API version 1
08-17 16:17:35.798 E/CameraService(  244): CameraService::connect X (PID 1442) rejected (invalid camera ID 0)
08-17 16:17:35.798 W/CameraBase( 1442): An error occurred while connecting to camera 0: Service not available
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442): RuntimeException during CameraAction[OPEN_CAMERA] at CameraState[1]
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442): java.lang.RuntimeException: Fail to connect to camera service
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at android.hardware.Camera.<init>(Camera.java:496)
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at android.hardware.Camera.open(Camera.java:345)
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at com.android.ex.camera2.portability.AndroidCameraAgentImpl$CameraHandler.handleMessage(AndroidCameraAgentImpl.java:384)
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at android.os.Handler.dispatchMessage(Handler.java:102)
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at android.os.Looper.loop(Looper.java:154)
08-17 16:17:35.799 E/CAM2PORT_AndCamAgntImp( 1442):     at android.os.HandlerThread.run(HandlerThread.java:61)
08-17 16:17:35.801 D/CameraHal(  244): createInstance(1041): open xml file(/etc/cam_board.xml) success
08-17 16:17:35.801 E/CameraHal(  244): cam_board.xml version(v0x0.0x0.0x0) != xml parser version(v0x0.0xf.0x0)

 不使用反射 修改标准Surface 将客户SDK api 封装进去

diff --git a/frameworks/base/core/java/android/view/Surface.java b/frameworks/base/core/java/android/view/Surface.java
old mode 100644
new mode 100755
index 22e68a3..78c78d0
--- a/frameworks/base/core/java/android/view/Surface.java
+++ b/frameworks/base/core/java/android/view/Surface.java
@@ -31,6 +31,11 @@ import java.lang.annotation.RetentionPolicy;
 
 import dalvik.system.CloseGuard;
 
+import android.os.SystemProperties; 
+import java.lang.reflect.Method;
+import com.yp.ypcodereader.manager.YpDevicesManager;
+import android.view.TextureView;
+
 /**
  * Handle onto a raw buffer that is being managed by the screen compositor.
  *
@@ -158,8 +163,10 @@ public class Surface implements Parcelable {
     public Surface() {
     }
 
+    private Surface xhSurface;
+    
     /**
-     * Create Surface from a {@link SurfaceTexture}.
+     * Create Surface from a {@link SurfaceTex ture}.
      *
      * Images drawn to the Surface will be made available to the {@link
      * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
@@ -178,8 +185,19 @@ public class Surface implements Parcelable {
             mName = surfaceTexture.toString();
             setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
         }
+        if(TextureView.xhSurface_flag) {
+            GetXSurface(surfaceTexture);
+        }                    
     }
 
+    public void GetXSurface(SurfaceTexture surfaceTexture) {
+        TextureView.xhSurface_flag = false;
+        xhSurface = new Surface(surfaceTexture);
+        TextureView.ypDevicesManager.setCodereaderCameraView(xhSurface);
+        TextureView.ypDevicesManager.openCodereaderCamera(null);
+    }
+
+
     /* called from android_view_Surface_createFromIGraphicBufferProducer() */
     private Surface(long nativeObject) {
         synchronized (mLock) {
@@ -225,6 +243,7 @@ public class Surface implements Parcelable {
      */
     public void destroy() {
         release();
+        TextureView.ypDevicesManager.closeCodereaderCamera();
     }
 
     /**
diff --git a/frameworks/base/core/java/android/view/TextureView.java b/frameworks/base/core/java/android/view/TextureView.java
old mode 100644
new mode 100755
index 645ab5c..0582f5d
--- a/frameworks/base/core/java/android/view/TextureView.java
+++ b/frameworks/base/core/java/android/view/TextureView.java
@@ -27,6 +27,14 @@ import android.graphics.SurfaceTexture;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.text.TextUtils;
+import android.os.SystemProperties;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+
+import com.yp.ypcodereader.manager.YpDevicesManager;
+
+import java.util.List;
 
 /**
  * <p>A TextureView can be used to display a content stream. Such a content
@@ -123,6 +131,12 @@ public class TextureView extends View {
     private Canvas mCanvas;
     private int mSaveCount;
 
+    public static YpDevicesManager ypDevicesManager;
+    private String outPackageInfo;
+    private String CLASS_NAME = "com.gatsby.ypcamerademo2.MainActivity";
+    public static boolean xhSurface_flag;
+    
+
     private final Object[] mNativeWindowLock = new Object[0];
     // Set by native code, do not write!
     private long mNativeWindow;
@@ -144,8 +158,27 @@ public class TextureView extends View {
      */
     public TextureView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        boolean packageInfo = isForeground(context,CLASS_NAME);        
+        if(packageInfo){
+            xhSurface_flag = true;
+            ypDevicesManager = new YpDevicesManager().getInstance();
+            ypDevicesManager.setContext(context);                
+        }        
+    }
+
+    public static boolean isForeground(Context context, String className) {
+        if (context == null || TextUtils.isEmpty(className))
+            return false;
+        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(1);
+        if (list != null && list.size() > 0) {
+            ComponentName cpn = list.get(0).topActivity;
+            if (className.equals(cpn.getClassName()))
+                return true;
+        }
+        return false;
     }
-
+    
     /**
      * Creates a new TextureView.
      *

  

 

posted @ 2021-08-14 15:23  CrushGirl  阅读(545)  评论(0编辑  收藏  举报