JPEG Orientation


public class MainActivity extends AppCompatActivity { private ActivityResultLauncher<Intent> activityResultLauncher; private static final int CODE_SELECT_IMAGE = 1; private CameraManager mCameraManager; private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceViewHolder; private Handler mHandler; private String mCameraId; private ImageReader mImageReader; private CameraDevice mCameraDevice; private CaptureRequest.Builder mPreviewBuilder; private CameraCaptureSession mSession; private RecyclerView recyclerView; private PhotoAdapter photoAdapter; private List<String> photoPaths = new ArrayList<>(); private Button take_picture_bt, mOpenPhoto, mUploadPhoto; private Handler mainHandler; private static final String TAG = "CameraFragment"; private String mPublicPhotoPath = ""; //创建okHttpClient对象 OkHttpClient mOkHttpClient = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.hide(); } recyclerView = findViewById(R.id.recycler_view); // img_show = (ImageView) findViewById(R.id.img_show); take_picture_bt = (Button) findViewById(R.id.take_picture); mOpenPhoto = (Button) findViewById(R.id.open_photo); mUploadPhoto = (Button) findViewById(R.id.upload_photo); mUploadPhoto.setEnabled(false); // 初始化RecyclerView photoAdapter = new PhotoAdapter(this, photoPaths); recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); recyclerView.setAdapter(photoAdapter); // 注册 Activity Result Launcher activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> handleGalleryResult(result) ); initSurfaceView();//初始化SurfaceView /** * 拍照按钮监听 */ take_picture_bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePicture(); } }); mOpenPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT); albumIntent.setType("image/*"); albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); // 允许多选 activityResultLauncher.launch(albumIntent); } }); mUploadPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 通过AlertDialog.Builder这个类来实例化我们的一个AlertDialog的对象 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); // 设置Title的图标 builder.setIcon(R.drawable.ic_launcher_background); // 设置Title的内容 builder.setTitle("提示框"); // 设置Content来显示一个信息 builder.setMessage("确定上传吗?"); // 设置一个PositiveButton builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, mPublicPhotoPath); if (mPublicPhotoPath == "") { return; } File file = new File(mPublicPhotoPath); Request request = getFileRequest("http://192.168.11.13:10004/api/upload", file, null); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.i(TAG, "上传失败!"); } @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); parseJSONWithGSON(result); //显示UI界面,调用的showResponse方法 Log.i(TAG, result.toString()); //Toast.makeText(MainActivity.this, "success!", Toast.LENGTH_SHORT).show(); } }); } }); // 设置一个NegativeButton builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Toast.makeText(MainActivity.this, "negative: " + which, Toast.LENGTH_SHORT).show(); } }); // 设置一个NeutralButton // 显示出该对话框 builder.show(); } }); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } private void handleGalleryResult(ActivityResult result) { if (result.getResultCode() == RESULT_OK && result.getData() != null) { Intent data = result.getData(); if (data.getClipData() != null) { // 多选 ClipData clipData = data.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { Uri imageUri = clipData.getItemAt(i).getUri(); String path = getRealPathFromURI(imageUri); if (!photoPaths.contains(path)) { photoPaths.add(path); } } } else if (data.getData() != null) { // 单选 Uri imageUri = data.getData(); String path = getRealPathFromURI(imageUri); if (!photoPaths.contains(path)) { photoPaths.add(path); } } photoAdapter.notifyDataSetChanged(); } } private String getRealPathFromURI(Uri contentUri) { Cursor cursor = getContentResolver().query(contentUri, null, null, null, null); if (cursor == null) return contentUri.getPath(); cursor.moveToFirst(); int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); String path = cursor.getString(idx); cursor.close(); return path; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == 1){ for (int grantResult : grantResults) { if(grantResult != PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "对不起,没有权限,无法正常使用相机", Toast.LENGTH_SHORT).show(); return; }else{ System.out.println("正常使用相机!"); } } initCameraAndPreview(); } } public void initSurfaceView() { mSurfaceView = (SurfaceView) findViewById(R.id.mFirstSurfaceView); mSurfaceViewHolder = mSurfaceView.getHolder();//通过SurfaceViewHolder可以对SurfaceView进行管理 mSurfaceViewHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { initCameraAndPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { //释放camera if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } @TargetApi(19) public void initCameraAndPreview() { HandlerThread handlerThread = new HandlerThread("My First Camera2"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); mainHandler = new Handler(getMainLooper());//用来处理ui线程的handler,即ui线程 mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); try { mCameraId = "" + CameraCharacteristics.LENS_FACING_FRONT; mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(), ImageFormat.JPEG,/*maxImages*/7); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mainHandler);//这里必须传入mainHandler,因为涉及到了Ui操作 if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } return; } mCameraManager.openCamera(mCameraId, deviceStateCallback, mHandler); } catch (CameraAccessException e) { Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show(); } } private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { //进行相片存储 //mCameraDevice.close(); Image image = reader.acquireNextImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes);//将image对象转化为byte,再转化为bitmap final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); if (bitmap != null) { //img_show.setImageBitmap(bitmap); mUploadPhoto.setEnabled(true); } savePicture(bytes); } }; private CameraDevice.StateCallback deviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { mCameraDevice = camera; try { takePreview(); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(@NonNull CameraDevice camera) { if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } } @Override public void onError(CameraDevice camera, int error) { Toast.makeText(MainActivity.this, "打开摄像头失败", Toast.LENGTH_SHORT).show(); } }; public void takePreview() throws CameraAccessException { mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewBuilder.addTarget(mSurfaceViewHolder.getSurface()); mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceViewHolder.getSurface(), mImageReader.getSurface()), mSessionPreviewStateCallback, mHandler); } private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { mSession = session; //配置完毕开始预览 try { /** * 设置你需要配置的参数 */ //自动对焦 mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); //打开闪光灯 mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); //无限次的重复获取图像 mSession.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Toast.makeText(MainActivity.this, "配置失败", Toast.LENGTH_SHORT).show(); } }; public void takePicture() { try { CaptureRequest.Builder captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);//用来设置拍照请求的request captureRequestBuilder.addTarget(mImageReader.getSurface()); // 自动对焦 captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 自动曝光 captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); int rotation = getWindowManager().getDefaultDisplay().getRotation(); CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId); captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getJpegOrientation(cameraCharacteristics, rotation));//使图片做顺时针旋转 CaptureRequest mCaptureRequest = captureRequestBuilder.build(); mSession.capture(mCaptureRequest, null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } //获取图片应该旋转的角度,使图片竖直 public int getOrientation(int rotation) { switch (rotation) { case Surface.ROTATION_0: return 90; case Surface.ROTATION_90: return 0; case Surface.ROTATION_180: return 270; case Surface.ROTATION_270: return 180; default: return 0; } } //获取图片应该旋转的角度,使图片竖直 private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) { if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0; int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION); // Round device orientation to a multiple of 90 deviceOrientation = (deviceOrientation + 45) / 90 * 90; // LENS_FACING相对于设备屏幕的方向,LENS_FACING_FRONT相机设备面向与设备屏幕相同的方向 boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT; if (facingFront) deviceOrientation = -deviceOrientation; // Calculate desired JPEG orientation relative to camera orientation to make // the image upright relative to the device orientation int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360; return jpegOrientation; } //将照片存储在相机照片存储位置,这里采用bitmap方式保存 public String savePicture(byte[] imgBytes) { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String imgPath = Environment.getExternalStorageDirectory() + "/DCIM/JPEG_" + timeStamp + ".jpg"; try (FileOutputStream outputStream = new FileOutputStream(imgPath)) { outputStream.write(imgBytes); photoPaths.add(imgPath); photoAdapter.notifyDataSetChanged(); MediaScannerConnection.scanFile(this, new String[]{imgPath}, null, null); } catch (IOException e) { e.printStackTrace(); } return timeStamp; } public static Request getFileRequest(String url, File file, Map<String, String> maps){ MultipartBody.Builder builder= new MultipartBody.Builder().setType(MultipartBody.FORM); if(maps==null){ builder.addPart( Headers.of("Content-Disposition", "form-data; name=\"file\";filename=\"file.jpg\""), RequestBody.create(MediaType.parse("image/png"),file) ).build(); }else{ for (String key : maps.keySet()) { builder.addFormDataPart(key, maps.get(key)); } builder.addPart( Headers.of("Content-Disposition", "form-data; name=\"file\";filename=\"file.jpg\""), RequestBody.create(MediaType.parse("image/png"),file) ); } RequestBody body=builder.build(); return new Request.Builder().url(url).post(body).build(); } private void parseJSONWithGSON(String jsonData) { //使用轻量级的Gson解析得到的json Gson gson = new Gson(); UploadResult uploadResult = gson.fromJson(jsonData, new TypeToken<UploadResult>() {}.getType()); //控制台输出结果,便于查看 Log.d("MainActivity", "status" + uploadResult.getStatus()); Log.d("MainActivity", "msg" + uploadResult.getMsg()); } } 给出该段工程所有代码的详细中文注释
06-18
package com.example.ju_net; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; 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.media.Image; import android.media.ImageReader; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.provider.MediaStore; //import android.support.annotation.NonNull; //import android.support.v4.app.ActivityCompat; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private ActivityResultLauncher<Intent> activityResultLauncher; private static final int CODE_SELECT_IMAGE = 1; private CameraManager mCameraManager; private SurfaceView mSurfaceView; private SurfaceHolder mSurfaceViewHolder; private Handler mHandler; private String mCameraId; private ImageReader mImageReader; private CameraDevice mCameraDevice; private CaptureRequest.Builder mPreviewBuilder; private CameraCaptureSession mSession; private RecyclerView recyclerView; private PhotoAdapter photoAdapter; private List<String> photoPaths = new ArrayList<>(); private Button take_picture_bt, mOpenPhoto, mUploadPhoto; private Handler mainHandler; private static final String TAG = "CameraFragment"; private String mPublicPhotoPath = ""; //创建okHttpClient对象 OkHttpClient mOkHttpClient = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.hide(); } recyclerView = findViewById(R.id.recycler_view); // img_show = (ImageView) findViewById(R.id.img_show); take_picture_bt = (Button) findViewById(R.id.take_picture); mOpenPhoto = (Button) findViewById(R.id.open_photo); mUploadPhoto = (Button) findViewById(R.id.upload_photo); mUploadPhoto.setEnabled(false); // 初始化RecyclerView photoAdapter = new PhotoAdapter(this, photoPaths); recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); recyclerView.setAdapter(photoAdapter); // 注册 Activity Result Launcher activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> handleGalleryResult(result) ); initSurfaceView();//初始化SurfaceView /** * 拍照按钮监听 */ take_picture_bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePicture(); } }); mOpenPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT); albumIntent.setType("image/*"); albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); // 允许多选 activityResultLauncher.launch(albumIntent); } }); mUploadPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 通过AlertDialog.Builder这个类来实例化我们的一个AlertDialog的对象 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); // 设置Title的图标 builder.setIcon(R.drawable.ic_launcher_background); // 设置Title的内容 builder.setTitle("提示框"); // 设置Content来显示一个信息 builder.setMessage("确定上传吗?"); // 设置一个PositiveButton builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, mPublicPhotoPath); if (mPublicPhotoPath == "") { return; } File file = new File(mPublicPhotoPath); Request request = getFileRequest("http://192.168.11.13:10004/api/upload", file, null); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.i(TAG, "上传失败!"); } @Override public void onResponse(Call call, Response response) throws IOException { String result = response.body().string(); parseJSONWithGSON(result); //显示UI界面,调用的showResponse方法 Log.i(TAG, result.toString()); //Toast.makeText(MainActivity.this, "success!", Toast.LENGTH_SHORT).show(); } }); } }); // 设置一个NegativeButton builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //Toast.makeText(MainActivity.this, "negative: " + which, Toast.LENGTH_SHORT).show(); } }); // 设置一个NeutralButton // 显示出该对话框 builder.show(); } }); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } private void handleGalleryResult(ActivityResult result) { if (result.getResultCode() == RESULT_OK && result.getData() != null) { Intent data = result.getData(); if (data.getClipData() != null) { // 多选 ClipData clipData = data.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { Uri imageUri = clipData.getItemAt(i).getUri(); String path = getRealPathFromURI(imageUri); if (!photoPaths.contains(path)) { photoPaths.add(path); } } } else if (data.getData() != null) { // 单选 Uri imageUri = data.getData(); String path = getRealPathFromURI(imageUri); if (!photoPaths.contains(path)) { photoPaths.add(path); } } photoAdapter.notifyDataSetChanged(); } } private String getRealPathFromURI(Uri contentUri) { Cursor cursor = getContentResolver().query(contentUri, null, null, null, null); if (cursor == null) return contentUri.getPath(); cursor.moveToFirst(); int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); String path = cursor.getString(idx); cursor.close(); return path; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == 1){ for (int grantResult : grantResults) { if(grantResult != PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "对不起,没有权限,无法正常使用相机", Toast.LENGTH_SHORT).show(); return; }else{ System.out.println("正常使用相机!"); } } initCameraAndPreview(); } } public void initSurfaceView() { mSurfaceView = (SurfaceView) findViewById(R.id.mFirstSurfaceView); mSurfaceViewHolder = mSurfaceView.getHolder();//通过SurfaceViewHolder可以对SurfaceView进行管理 mSurfaceViewHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { initCameraAndPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { //释放camera if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } @TargetApi(19) public void initCameraAndPreview() { HandlerThread handlerThread = new HandlerThread("My First Camera2"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); mainHandler = new Handler(getMainLooper());//用来处理ui线程的handler,即ui线程 mCameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); try { mCameraId = "" + CameraCharacteristics.LENS_FACING_FRONT; mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(), ImageFormat.JPEG,/*maxImages*/7); mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mainHandler);//这里必须传入mainHandler,因为涉及到了Ui操作 if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } return; } mCameraManager.openCamera(mCameraId, deviceStateCallback, mHandler); } catch (CameraAccessException e) { Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show(); } } private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { //进行相片存储 //mCameraDevice.close(); Image image = reader.acquireNextImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes);//将image对象转化为byte,再转化为bitmap final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); if (bitmap != null) { //img_show.setImageBitmap(bitmap); mUploadPhoto.setEnabled(true); } savePicture(bytes); } }; private CameraDevice.StateCallback deviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { mCameraDevice = camera; try { takePreview(); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(@NonNull CameraDevice camera) { if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } } @Override public void onError(CameraDevice camera, int error) { Toast.makeText(MainActivity.this, "打开摄像头失败", Toast.LENGTH_SHORT).show(); } }; public void takePreview() throws CameraAccessException { mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewBuilder.addTarget(mSurfaceViewHolder.getSurface()); mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceViewHolder.getSurface(), mImageReader.getSurface()), mSessionPreviewStateCallback, mHandler); } private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { mSession = session; //配置完毕开始预览 try { /** * 设置你需要配置的参数 */ //自动对焦 mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); //打开闪光灯 mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); //无限次的重复获取图像 mSession.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { Toast.makeText(MainActivity.this, "配置失败", Toast.LENGTH_SHORT).show(); } }; public void takePicture() { try { CaptureRequest.Builder captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);//用来设置拍照请求的request captureRequestBuilder.addTarget(mImageReader.getSurface()); // 自动对焦 captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 自动曝光 captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); int rotation = getWindowManager().getDefaultDisplay().getRotation(); CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId); captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getJpegOrientation(cameraCharacteristics, rotation));//使图片做顺时针旋转 CaptureRequest mCaptureRequest = captureRequestBuilder.build(); mSession.capture(mCaptureRequest, null, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } //获取图片应该旋转的角度,使图片竖直 public int getOrientation(int rotation) { switch (rotation) { case Surface.ROTATION_0: return 90; case Surface.ROTATION_90: return 0; case Surface.ROTATION_180: return 270; case Surface.ROTATION_270: return 180; default: return 0; } } //获取图片应该旋转的角度,使图片竖直 private int getJpegOrientation(CameraCharacteristics c, int deviceOrientation) { if (deviceOrientation == android.view.OrientationEventListener.ORIENTATION_UNKNOWN) return 0; int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION); // Round device orientation to a multiple of 90 deviceOrientation = (deviceOrientation + 45) / 90 * 90; // LENS_FACING相对于设备屏幕的方向,LENS_FACING_FRONT相机设备面向与设备屏幕相同的方向 boolean facingFront = c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT; if (facingFront) deviceOrientation = -deviceOrientation; // Calculate desired JPEG orientation relative to camera orientation to make // the image upright relative to the device orientation int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360; return jpegOrientation; } //将照片存储在相机照片存储位置,这里采用bitmap方式保存 public String savePicture(byte[] imgBytes) { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String imgPath = Environment.getExternalStorageDirectory() + "/DCIM/JPEG_" + timeStamp + ".jpg"; try (FileOutputStream outputStream = new FileOutputStream(imgPath)) { outputStream.write(imgBytes); photoPaths.add(imgPath); photoAdapter.notifyDataSetChanged(); MediaScannerConnection.scanFile(this, new String[]{imgPath}, null, null); } catch (IOException e) { e.printStackTrace(); } return timeStamp; } public static Request getFileRequest(String url, File file, Map<String, String> maps){ MultipartBody.Builder builder= new MultipartBody.Builder().setType(MultipartBody.FORM); if(maps==null){ builder.addPart( Headers.of("Content-Disposition", "form-data; name=\"file\";filename=\"file.jpg\""), RequestBody.create(MediaType.parse("image/png"),file) ).build(); }else{ for (String key : maps.keySet()) { builder.addFormDataPart(key, maps.get(key)); } builder.addPart( Headers.of("Content-Disposition", "form-data; name=\"file\";filename=\"file.jpg\""), RequestBody.create(MediaType.parse("image/png"),file) ); } RequestBody body=builder.build(); return new Request.Builder().url(url).post(body).build(); } private void parseJSONWithGSON(String jsonData) { //使用轻量级的Gson解析得到的json Gson gson = new Gson(); UploadResult uploadResult = gson.fromJson(jsonData, new TypeToken<UploadResult>() {}.getType()); //控制台输出结果,便于查看 Log.d("MainActivity", "status" + uploadResult.getStatus()); Log.d("MainActivity", "msg" + uploadResult.getMsg()); } }逐段分析所有代码
06-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值