Camera相机是属于硬件,每台设备的Camera硬件配置的参数都是不一样的,Camera通常是用来拍照,扫描二维码等等
AndroidManifest.xml配置Camera需要的权限:
<!-- 打开相机是很危险的行为,加入权限 --> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.autofocus"/> <!-- 保存图片到sdcard外部存储 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidManifest.xml配置Activity 横屏显示 + 全屏:
<!-- 设置横屏显示: android:screenOrientation="landscape" 设置无标题+全屏: android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" --> <activity android:name=".MyCameraActivity" android:screenOrientation="landscape" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
activity_camera.xml布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="对焦" android:layout_alignParentBottom="true" android:onClick="focus" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:onClick="takepicture" /> </RelativeLayout>
MyCameraActivity.java
package liudeli.my_media1; import android.app.Activity; import android.hardware.Camera; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Toast; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class MyCameraActivity extends Activity { private final String TAG = MySurfaceViewActivity.class.getSimpleName(); /** * 操作的是SurfaceHolder,所以定义全局变量 */ private SurfaceHolder surfaceHolder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); // 获取在布局文件中定义的SurfaceView SurfaceView surfaceView = findViewById(R.id.surface_view); // 不能直接操作SurfaceView,需要通过SurfaceView拿到SurfaceHolder surfaceHolder = surfaceView.getHolder(); // 使用SurfaceHolder设置屏幕高亮,注意:所有的View都可以设置 设置屏幕高亮 surfaceHolder.setKeepScreenOn(true); // 使用SurfaceHolder设置把画面或缓存 直接显示出来 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); /** * 由于要观察SurfaceView生命周期,所以需要设置监听 * 此监听不一样,是addCallback * */ surfaceHolder.addCallback(callback); } /** * 定义相机对象 */ private Camera camera; /** * 定义SurfaceView监听回调 */ private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() { /** * SurfaceView被创建了 * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { /** * 只有在SurfaceView生命周期方法-->SurfaceView被创建后在打开相机 * 以前我在 onResume 之前去打开相机,结果报错了,所以只有在这里打开相机,才是安全🔐 */ // Camera要选择hardware.Camera,因为Camera属于硬件hardware // Camera.open(1); // 这了传入的值,可以指定为:前置摄像头/后置摄像头 camera = Camera.open(0); /** * 设置Camera与SurfaceHolder关联,Camera的数据让SurfaceView显示 */ try { camera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, "相机设置预览失败"); } /** * 开始显示 */ camera.startPreview(); } /** * SurfaceView发生改变了 * @param holder * @param format * @param width * @param height */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 以后做具体业务功能的时候,才会用到改变的值来处理 // ...... } /** * SurfaceView被销毁了 * @param holder */ @Override public void surfaceDestroyed(SurfaceHolder holder) { /** * SurfaceView被销毁后,一定要释放硬件资源,Camera是硬件 */ camera.stopPreview(); // (一定要有,不然只release也可能出问题) camera.release(); camera = null; System.gc(); } }; /** * 拍照 */ public void takepicture(View view) { if (null != camera) { /** * 参数一:相机的快门,咔嚓,这里用不到 * 参数二:相机原始的数据 * 参数三:相机处理后的数据 */ camera.takePicture(null, null, pictureCallback); } } /** * 相机处理后的数据回调 */ private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() { /** * 拍照完成,可以拿到数据了 * @param data 数据 * @param camera */ @Override public void onPictureTaken(byte[] data, Camera camera) { // 写在指定目录 sdcard 中去 File file = new File(Environment.getExternalStorageDirectory(), "pictureCallback.jpg"); try { // 字节文件输出流,把byte[]数据写入到文件里面去 OutputStream os = new FileOutputStream(file); os.write(data); // 关闭字节文件输出流 os.close(); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "保存失败"); Toast.makeText(MyCameraActivity.this, "照片保存失败", Toast.LENGTH_SHORT).show(); } } }; /** * 对焦 */ public void focus(View view) { // 对焦都是硬件设备来完成的 camera.autoFocus(null); } /** * 当Activity被销毁的时候,一定要移除监听 */ @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, ">>>> onDestroy()"); if (null != callback) surfaceHolder.removeCallback(callback); } }