您现在的位置是:首页 > 文章详情

Android Camera2使用

日期:2018-06-24点击:565

1. 相机使用流程

img_fe9897bef6d4544f03b6f23a64f60009.jpe
图1.jpg

2. SurfaceView

/** * Android 5.0 使用Camera2 照相 * 使用SurfaceView显示 * 主要步骤: * 1. 获得摄像头管理器CameraManager mCameraManager,mCameraManager.openCamera()来打开摄像头 * 2. 指定要打开的摄像头,并创建openCamera()所需要的CameraDevice.StateCallback stateCallback * 3. 在CameraDevice.StateCallback stateCallback中调用takePreview(),这个方法中,使用CaptureRequest.Builder创建预览需要的CameraRequest,并初始化了CameraCaptureSession,最后调用了setRepeatingRequest(previewRequest, null, childHandler)进行了预览 * 4. 点击拍照按钮,调用takePicture(),这个方法内,最终调用了capture(mCaptureRequest, null, childHandler) * 5. 在new ImageReader.OnImageAvailableListener(){}回调方法中,将拍照拿到的图片进行展示 */ public class CameraSurfaceFragment extends Fragment { /**照相机设备请求码*/ private static final int REQUEST_CAMERA_CODE = 0x100; /**拍照*/ private Button mBtnTake; /**显示拍照好的图片*/ private ImageView mIvShow; /**预览窗口*/ private SurfaceView mSurfaceView; /**预览窗口Holder*/ private SurfaceHolder mSurfaceHolder; /**子线程Handler*/ private Handler mChildHandler; /**主线程Handler*/ private Handler mMainHandler; /**照相机ID,标识前置,后置*/ private String mCameraId; /**图片读取器*/ private ImageReader mImageReader; /**摄像头管理者*/ private CameraManager mCameraManager; /**照相机设备*/ private CameraDevice mCameraDevice; /**照相会话*/ private CameraCaptureSession mCameraCaptureSession; /**方向列表*/ private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); /** * 摄像头状态监听 */ private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { // 打开摄像头 mCameraDevice = camera; // 开启预览 takePreview(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { // 关闭摄像头 if (null != mCameraDevice) { // 关闭摄像头 mCameraDevice.close(); mCameraDevice = null; } } @Override public void onError(@NonNull CameraDevice camera, int error) { // 摄像头异常 Toast.makeText(getContext(), "摄像头开启失败", Toast.LENGTH_SHORT).show(); } }; static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_camera_surface, container, false); initView(root); initListener(); return root; } /** * 初始化View */ private void initView(View view) { // 绑定View mIvShow = view.findViewById(R.id.iv_show); mBtnTake = view.findViewById(R.id.btn_take); mSurfaceView = view.findViewById(R.id.sv_camera); // 获取Holder mSurfaceHolder = mSurfaceView.getHolder(); // 设置屏幕常量 mSurfaceHolder.setKeepScreenOn(true); // 设置SurfaceView回调 mSurfaceHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { // SurfaceView 创建 initCamera(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // SurfaceView 改变 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // SurfaceView 销毁 // 销毁照相机设备 if (null != mCameraDevice) { mCameraDevice.close(); mCameraDevice = null; } } }); } /** * 初始化监听器 */ private void initListener() { mBtnTake.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePicture(); } }); } /** * 初始化照相机 */ private void initCamera() { // 创建Handler线程并启动 HandlerThread handlerThread = new HandlerThread("Camera"); handlerThread.start(); // 创建子线程Handler mChildHandler = new Handler(handlerThread.getLooper()); // 创建主线程Handler mMainHandler = new Handler(Looper.getMainLooper()); // 设置后置摄像头ID mCameraId = String.valueOf(CameraCharacteristics.LENS_FACING_FRONT); // 创建图片读取器 mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1); // 图片读取器设置图片可用监听 mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { showImage(reader); } }, mMainHandler); // 获取摄像头管理 mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); // 打开摄像头 try { if (ActivityCompat.checkSelfPermission (getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // 申请权限 requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE); } else { // 打开摄像头 mCameraManager.openCamera(mCameraId, mStateCallback, mMainHandler); } } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (REQUEST_CAMERA_CODE == requestCode) { // 权限允许 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { try { if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return; } mCameraManager.openCamera(mCameraId, mStateCallback, mMainHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } else { // 权限拒绝 Toast.makeText(getContext(), "无权限", Toast.LENGTH_SHORT).show(); } } } /** * 图片可用后,读取并显示图片 * @param reader 图片读取器 */ private void showImage(ImageReader reader) { // 拿到图片数据 Image image = reader.acquireNextImage(); // 获取字节缓冲 ByteBuffer buffer = image.getPlanes()[0].getBuffer(); // 创建与缓冲区相同的字节数组 byte[] bytes = new byte[buffer.remaining()]; // 将数据读取字节数组 buffer.get(bytes); // 创建图片 final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); // 显示图片 if (null != bitmap) { mIvShow.setImageBitmap(bitmap); } } /** * 预览 */ private void takePreview() { try { // 创建预览需要的CaptureRequest.Builder final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 将SurfaceView的surface作为Builder的目标 builder.addTarget(mSurfaceHolder.getSurface()); // 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求 mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { // 检测设备是否为空 if (null == mCameraDevice) return; // 配置 // 当摄像头已经准备好时,开始显示预览 mCameraCaptureSession = session; try { // 自动对焦 builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 打开闪光灯 builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); // 显示预览 CaptureRequest request = builder.build(); // 会话设置重复请求 mCameraCaptureSession.setRepeatingRequest(request, null, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Toast.makeText(getContext(), "配置失败", Toast.LENGTH_SHORT).show(); } }, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } /** * 拍照 */ private void takePicture() { // 判断设备是否为空 if (null == mCameraDevice) return; // 创建拍照需要的CaptureRequest.Builder final CaptureRequest.Builder builder; try { // 创建拍照请求 builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); // 将imageReader的surface作为CaptureRequest.Builder的木白哦 builder.addTarget(mImageReader.getSurface()); // 自动对焦 builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 自动曝光 builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); // 获取手机方向 int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); // 根据设备方向计算设置照片的方向 builder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); // 拍照 CaptureRequest request = builder.build(); // 拍照会话执行拍照 mCameraCaptureSession.capture(request, null, mChildHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } } 

3. TextureView

/** * Camera2 与 Texture使用 */ public class CameraTextureFragment extends Fragment { /**相机权限请求标识*/ private static final int REQUEST_CAMERA_CODE = 0x100; /**预览*/ private TextureView mTextureView; /**拍照按钮*/ private Button mBtnTake; /**图片*/ private ImageView mImageView; /**照相机ID,标识前置后置*/ private String mCameraId; /**相机尺寸*/ private Size mCaptureSize; /**图像读取者*/ private ImageReader mImageReader; /**图像主线程Handler*/ private Handler mCameraHandler; /**相机设备*/ private CameraDevice mCameraDevice; /**预览大小*/ private Size mPreviewSize; /**相机请求*/ private CaptureRequest.Builder mCameraCaptureBuilder; /**相机拍照捕获会话*/ private CameraCaptureSession mCameraCaptureSession; /**相机管理者*/ private CameraManager mCameraManager; /**相机设备状态回调*/ private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { // 打开 mCameraDevice = camera; // 开始预览 takePreview(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { // 断开连接 camera.close(); mCameraDevice = null; } @Override public void onError(@NonNull CameraDevice camera, int error) { // 异常 camera.close(); mCameraDevice = null; } }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_camera_texture, container, false); initView(root); initListener(); return root; } /** * 初始化View */ private void initView(View view) { // 初始化View mImageView = view.findViewById(R.id.iv_show); mTextureView = view.findViewById(R.id.tv_camera); mBtnTake = view.findViewById(R.id.btn_take); } @Override public void onResume() { super.onResume(); mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { // SurfaceTexture可用 // 设置相机参数并打开相机 setUpCamera(width, height); openCamera(); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // SurfaceTexture大小改变 } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { // SurfaceTexture 销毁 return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { // SurfaceTexture 更新 } }); } /** * 打开相机 */ private void openCamera() { // 获取照相机管理者 mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); try { if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE); return; } // 打开相机 mCameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (REQUEST_CAMERA_CODE == requestCode) { // 权限允许 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { try { if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return; } mCameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } else { // 权限拒绝 Toast.makeText(getContext(), "无权限", Toast.LENGTH_SHORT).show(); } } } /** * 设置相机参数 * @param width 宽度 * @param height 高度 */ private void setUpCamera(int width, int height) { // 创建Handler mCameraHandler = new Handler(Looper.getMainLooper()); // 获取摄像头的管理者 CameraManager cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); try { // 遍历所有摄像头 for (String cameraId : cameraManager.getCameraIdList()) { // 相机特性 CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); // 获取摄像头是前置还是后置 Integer facing = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING); // 此处默认打开后置摄像头 if (null != facing && CameraCharacteristics.LENS_FACING_FRONT == facing) continue; // 获取StreamConfigurationMap,管理摄像头支持的所有输出格式和尺寸 StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); assert map != null; // 根据TextureView的尺寸设置预览尺寸 mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height); // 获取相机支持的最大拍照尺寸 mCaptureSize = Collections.max( Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() { @Override public int compare(Size lhs, Size rhs) { return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth()); } }); // 此处ImageReader用于拍照所需 setupImageReader(); // 为摄像头赋值 mCameraId = cameraId; break; } } catch (CameraAccessException e) { e.printStackTrace(); } } /** * 设置ImageReader */ private void setupImageReader() { // 2代表ImageReader中最多可以获取两帧图像流 mImageReader = ImageReader.newInstance(mCaptureSize.getWidth(), mCaptureSize.getHeight(), ImageFormat.JPEG, 1); // 设置图像可用监听 mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { // 获取图片 final Image image = reader.acquireNextImage(); // 提交任务,保存图片 mCameraHandler.post(new ImageSaver(image)); // 更新UI getActivity().runOnUiThread(new Runnable() { @Override public void run() { // 获取字节缓冲区 ByteBuffer buffer = image.getPlanes()[0].getBuffer(); // 创建数组之前调用此方法,恢复默认设置 buffer.rewind(); // 创建与缓冲区内容大小相同的数组 byte[] bytes = new byte[buffer.remaining()]; // 从缓冲区存入字节数组,读取完成之后position在末尾 buffer.get(bytes); // 获取Bitmap图像 final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); // 显示 if (null != bitmap) { mImageView.setImageBitmap(bitmap); } } }); } }, mCameraHandler); } /** * 选择SizeMap中大于并且最接近width和height的size * @param sizeMap 可选的尺寸 * @param width 宽 * @param height 高 * @return 最接近width和height的size */ private Size getOptimalSize(Size[] sizeMap, int width, int height) { // 创建列表 List<Size> sizeList = new ArrayList<>(); // 遍历 for (Size option : sizeMap) { // 判断宽度是否大于高度 if (width > height) { if (option.getWidth() > width && option.getHeight() > height) { sizeList.add(option); } } else { if (option.getWidth() > height && option.getHeight() > width) { sizeList.add(option); } } } // 判断存储Size的列表是否有数据 if (sizeList.size() > 0) { return Collections.min(sizeList, new Comparator<Size>() { @Override public int compare(Size lhs, Size rhs) { return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight()); } }); } return sizeMap[0]; } /** * 设置监听 */ private void initListener() { mBtnTake.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePicture(); } }); } /** * 预览 */ private void takePreview(){ // 获取SurfaceTexture SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); // 设置默认的缓冲大小 surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); // 创建Surface Surface previewSurface = new Surface(surfaceTexture); try { // 创建预览请求 mCameraCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 将previewSurface添加到预览请求中 mCameraCaptureBuilder.addTarget(previewSurface); // 创建会话 mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { try { // 配置 CaptureRequest captureRequest = mCameraCaptureBuilder.build(); // 設置session mCameraCaptureSession = session; // 设置重复预览请求 mCameraCaptureSession.setRepeatingRequest(captureRequest, null, mCameraHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { // 配置失败 } }, mCameraHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } /** * 拍照 */ private void takePicture() { try { // 设置触发 mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START); mCameraCaptureBuilder.addTarget(mImageReader.getSurface()); // 拍照 mCameraCaptureSession.capture(mCameraCaptureBuilder.build(), null, mCameraHandler); } catch (CameraAccessException e) { Toast.makeText(getActivity(), "异常", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } /** * 保存图片任务 */ private class ImageSaver implements Runnable { /**图像*/ private Image mImage; ImageSaver(Image image) { this.mImage = image; } @Override public void run() { // 获取字节缓冲区 ByteBuffer buffer = mImage.getPlanes()[0].getBuffer(); // 创建数组之前调用此方法,恢复默认设置--重要 buffer.rewind(); // 创建与字节缓冲区大小相同的字节数组 byte[] data = new byte[buffer.remaining()]; // 将数据读取字节数组 buffer.get(data); // 获取缓存路径 String path = getActivity().getExternalCacheDir().getPath(); // 获取时间戳 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); // 文件名 String fileName = path + "/IMG_" + timeStamp + ".jpg"; // 创建文件输出流 FileOutputStream fos = null; try { // 初始化文件输出流 fos = new FileOutputStream(fileName); // 将数据写入文件 fos.write(data, 0, data.length); // 刷新缓冲区 fos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != fos) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } } 

4. 多功能相机

  • 切换摄像头
 /** * 后置摄像头 */ private static final int CAMERA_FRONT = CameraCharacteristics.LENS_FACING_FRONT; /** * 前置摄像头 */ private static final int CAMERA_BACK = CameraCharacteristics.LENS_FACING_BACK; /** * 照相机ID,标识前置后置 */ private String mCameraId; /** * 切换前后摄像头 */ private void switchCamera() { if (String.valueOf(CAMERA_FRONT).equals(mCameraId)) { // 后置 mCameraId = String.valueOf(CAMERA_BACK); } else if (String.valueOf(CAMERA_BACK).equals(mCameraId)) { // 前置 mCameraId = String.valueOf(CAMERA_FRONT); } closeCamera(); reOpenCamera(); } /** * 重新打开摄像头 */ private void reOpenCamera() { if (mTextureView.isAvailable()) { openCamera(); } else { setTextureListener(); } } /** * 关闭摄像头 */ private void closeCamera() { if (null != mCameraCaptureSession) { mCameraCaptureSession.close(); mCameraCaptureSession = null; } if (null != mCameraDevice) { mCameraDevice.close(); mCameraDevice = null; } if (null != mImageReader) { mImageReader.close(); mImageReader = null; } } 
  • 延时拍摄
 /** * 无延时 */ private static final int DELAY_ZERO = 0; /** * 延时3秒 */ private static final int DELAY_THREE = 3; /** * 延时10秒 */ private static final int DELAY_TEN = 10; /** * 延时拍摄 */ private void delayTake() { switch (mDelayTime) { case DELAY_ZERO: mDelayTime = DELAY_THREE; break; case DELAY_THREE: mDelayTime = DELAY_TEN; break; case DELAY_TEN: mDelayTime = DELAY_ZERO; break; } mBtnDelay.setText("延时" + mDelayTime + "秒"); if (mDelayTime == DELAY_ZERO) { takePicture(); } else { // 定时器 new CountDownTimer(mDelayTime * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { mBtnDelay.setText(String.valueOf(millisUntilFinished/1000) + "秒"); } @Override public void onFinish() { mBtnDelay.setText("延时" + mDelayTime + "秒"); takePicture(); } }.start(); } } 
  • 切换闪光
 /** * 闪光标识--自动开启 */ private static final int FLASH_ZERO = 0; /** * 闪光标识--总是开启 */ private static final int FLASH_ONE = 1; /** * 闪光标识--关闭 */ private static final int FLASH_TWO = 2; /** * 切换闪光模式 */ private void switchFlash() { switch(mFlashMode) { case FLASH_ZERO: mFlashMode = FLASH_ONE; mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); break; case FLASH_ONE: mFlashMode = FLASH_TWO; mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH); break; case FLASH_TWO: mFlashMode = FLASH_ZERO; mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); // 必须设置 mCameraCaptureBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF); break; } try { mCameraCaptureSession.setRepeatingRequest(mCameraCaptureBuilder.build(), null, mCameraHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } 

代码下载

原文链接:https://yq.aliyun.com/articles/663295
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章