Android相机的基本使用与自定义相机
2016-07-25 22:32
507 查看
在项目中,经常会用到拍照获取图片以及从图库中选择图片,此篇文章就是自己的总结。
第二步:调取系统自带的拍照界面
系统自带的拍照获取的图片可以是缩略图,也可以为原图,而其中的区别就在于intent的putExtra。
Get Photo Thumbnail
Get Full Size Photo
第三步:加入图库:
我们知道,在OnActivityResult获取的值是一个uri,在android中我们经常遇到两种uri,一种是以content开头的,一种是以file开头的uri,而在图片处理的过程中以content开头的uri不能做任何操作,而在OnActivityResult获取的uri就是content开头的uri,所以我们应该把以content开头的uri转化为以file开头的uri。
此方法的参数是一个以content开头的uri,而返回值是一个以file开头的uri
此方法主要是保存图片到本地,并返回一个以file开头的uri。
而自定义相机的核心姿势是:Camera和SurfaceView
Camera API:
final void autoFocus(Camera.AutoFocusCallback cb)
Starts camera auto-focus and registers a callback function to run when the camera is focused.
static Camera open()
Creates a new Camera object to access the first back-facing camera on the device.
final void release()
Disconnects and releases the Camera object resources.
final void setDisplayOrientation(int degrees)
Set the clockwise rotation of preview display in degrees.
final void setPreviewDisplay(SurfaceHolder holder)
Sets the Surface to be used for live preview.
final void startPreview()
Starts capturing and drawing preview frames to the screen.
final void stopPreview()
Stops capturing and drawing preview frames to the surface, and resets the camera for a future call to startPreview().
final void takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)
Equivalent to takePicture(shutter, raw, null, jpeg).
相机拍照
第一步:就是判断设备是否支持拍照:Intent intentCamer = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if(intentCamer.resolveActivity(getPackageManager()) == null) { Toast.makeText(MainActivity.this, "No Cammer", Toast.LENGTH_SHORT).show(); } else { startActivityForResult(intentCamer, REQUEST_IMAGE_CAPTURE); }
第二步:调取系统自带的拍照界面
系统自带的拍照获取的图片可以是缩略图,也可以为原图,而其中的区别就在于intent的putExtra。
Get Photo Thumbnail
Intent intentCamer = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (intentCamer.resolveActivity(getPackageManager()) == null) { Toast.makeText(MainActivity.this, "No Cammer", Toast.LENGTH_SHORT).show(); } else { startActivityForResult(intentCamer, REQUEST_IMAGE_CAPTURE); }
Get Full Size Photo
Intent intentFullSize = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (intentFullSize.resolveActivity(getPackageManager()) == null) { Toast.makeText(MainActivity.this, "No Cammer", Toast.LENGTH_SHORT).show(); } else { File photoFile = null; try { photoFile = createPhotoFile(); if (photoFile != null) { Uri photoUri = FileProvider.getUriForFile(MainActivity.this, "com.example.android.fileprovider", photoFile); intentFullSize.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(intentFullSize, REQUEST_IMAGE_CAPTURE); } } catch (IOException e) { e.printStackTrace(); } }
private File createPhotoFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile(imageFileName, ".jpg", storageDir); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = "file:" + image.getAbsolutePath(); return image; }
第三步:加入图库:
private void addToGallery() { Intent intentToGallery = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(mCurrentPhotoPath); Uri contentUri = Uri.fromFile(f); intentToGallery.setData(contentUri); this.sendBroadcast(intentToGallery); }
图库获取图片
IntentIntent fileIntent = new Intent(Intent.ACTION_GET_CONTENT); fileIntent.setType("image/*"); startActivityForResult(fileIntent, REQUEST_IMAGE_FILE);
我们知道,在OnActivityResult获取的值是一个uri,在android中我们经常遇到两种uri,一种是以content开头的,一种是以file开头的uri,而在图片处理的过程中以content开头的uri不能做任何操作,而在OnActivityResult获取的uri就是content开头的uri,所以我们应该把以content开头的uri转化为以file开头的uri。
private Uri convertUri(Uri uri) { try { InputStream inputStream = getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); inputStream.close(); return saveBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } }
此方法的参数是一个以content开头的uri,而返回值是一个以file开头的uri
private Uri saveBitmap(Bitmap bitmap) { File temDir = new File(Environment.getExternalStorageDirectory() + "/text"); if (!temDir.exists()) { temDir.mkdirs(); } File img = null; try { img = createPhotoFile(); } catch (IOException e) { e.printStackTrace(); } try { FileOutputStream fileOutputStream = new FileOutputStream(img); bitmap.compress(Bitmap.CompressFormat.PNG, 85, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); return Uri.fromFile(img); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } }
此方法主要是保存图片到本地,并返回一个以file开头的uri。
图片的裁剪
private void startImageZoon(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 150); intent.putExtra("outputY", 150); intent.putExtra("return-data", true); startActivityForResult(intent, REQUEST_IMAGE_ZOOM); }
图片的上传
图片上传到服务器就是把bitMap转化为String,以Base64的方式提交给服务器。private String bitMapToString(Bitmap bitmap){ ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG,85,byteArrayOutputStream); byte[] bytes=byteArrayOutputStream.toByteArray(); return new String(Base64.encode(bytes,Base64.DEFAULT)); }
自定义相机
前面的内容都是利用系统自带的相机界面,有时业务的需求可能需要自定义相机界面。而自定义相机的核心姿势是:Camera和SurfaceView
Camera API:
final void autoFocus(Camera.AutoFocusCallback cb)
Starts camera auto-focus and registers a callback function to run when the camera is focused.
static Camera open()
Creates a new Camera object to access the first back-facing camera on the device.
final void release()
Disconnects and releases the Camera object resources.
final void setDisplayOrientation(int degrees)
Set the clockwise rotation of preview display in degrees.
final void setPreviewDisplay(SurfaceHolder holder)
Sets the Surface to be used for live preview.
final void startPreview()
Starts capturing and drawing preview frames to the screen.
final void stopPreview()
Stops capturing and drawing preview frames to the surface, and resets the camera for a future call to startPreview().
final void takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)
Equivalent to takePicture(shutter, raw, null, jpeg).
布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.myapplication.CustomCameraActivity"> <SurfaceView android:id="@+id/sv_custom" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_custom_camera_capture" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="Capture" android:gravity="center"/> <TextView android:id="@+id/tv_custom_camera_cancel" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="Cancel" android:gravity="center"/> </LinearLayout> </LinearLayout>
核心代码
public class CustomCameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, View.OnClickListener { @BindView(R.id.sv_custom) SurfaceView svCustom; @BindView(R.id.tv_custom_camera_capture) TextView tvCustomCameraCapture; @BindView(R.id.tv_custom_camera_cancel) TextView tvCustomCameraCancel; private SurfaceHolder mSurfaceHolder; private Camera mCamera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_camera); ButterKnife.bind(this); initView(); initListener(); } private void initView() { mSurfaceHolder = svCustom.getHolder(); mSurfaceHolder.addCallback(this); } private void initListener() { tvCustomCameraCapture.setOnClickListener(this); } /** * * @return 摄像机对象 */ private Camera getCamera() { Camera camera; camera = Camera.open(); return camera; } /** * 摄像机与surfaceView的绑定 * @param camera * @param surfaceHolder */ private void startPreview(Camera camera, SurfaceHolder surfaceHolder) { try { camera.setPreviewDisplay(surfaceHolder); camera.setDisplayOrientation(90); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } /** * 释放资源 */ private void releaseCamera() { if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } } @Override protected void onResume() { super.onResume(); if (mCamera == null) { mCamera = getCamera(); if (mSurfaceHolder != null) { startPreview(mCamera, mSurfaceHolder); } } } @Override protected void onPause() { super.onPause(); releaseCamera(); } @Override public void surfaceCreated(SurfaceHolder holder) { startPreview(mCamera, mSurfaceHolder); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mCamera.stopPreview(); startPreview(mCamera, mSurfaceHolder); } @Override public void surfaceDestroyed(SurfaceHolder holder) { releaseCamera(); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.tv_custom_camera_capture: /** * 拍照功能 */ Camera.Parameters parameters=mCamera.getParameters(); parameters.setPictureFormat(ImageFormat.JPEG); parameters.setPictureSize(800,400); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success){ mCamera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File file=new File(Environment.getExternalStorageDirectory(),"temp.jpg"); try { FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(data); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); } } }); break; } } }
相关文章推荐
- Android之关于电话录音原理,目前的方法还是只能录MIC
- android listView下拉刷新试用所有View
- android-NotificationManager
- android-Notification.Style
- android-Notification.InboxStyle
- android-Notification.BigTextStyle
- 关于android程序进入第一个界面出现空白的解决方案
- android-Notification.BigPictureStyle
- Create a background service in Android
- android-Notification.Action
- Android for work总结(上)
- android Binder 学习 博客链接
- android-Notification
- Android初学之Bundle
- android-Parcelable
- 最强的Android Studio的使用技巧和快捷键
- Android性能优化
- 关于Android Studio你可能不知道的10件小事
- Genymotion——强大的Android模拟器
- Android源码编译make的各类错误解决方案汇总