安卓手机相机应用开发

数据科学实验室 2021-09-27 ⋅ 32 阅读

在今天的移动设备时代,相机已经成为了手机最为常用的功能之一。随着相机硬件的不断升级和智能手机操作系统的发展,开发者们有更多的机会来创建功能丰富、用户友好的相机应用。本篇博客将介绍如何开发拍照功能和相册访问的安卓手机相机应用。

准备工作

在开始编写代码之前,你需要确保你的开发环境已经正确配置。首先,你需要安装Android Studio并进行基本设置。你还需要下载适用于你的设备的Android开发工具包(SDK)。如果你需要在真实设备上测试你的应用,你还需要在设备上启用开发者选项和USB调试模式。

创建新项目

在Android Studio中,选择“Start a new Android Studio project”(创建一个新的Android Studio项目)。你需要为你的项目选择一个合适的名称和位置,并选择你想要的最低SDK版本。

添加权限

首先,你需要在你的AndroidManifest.xml文件中添加必要的权限以访问相机和相册。在<manifest>标签中添加以下代码:

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

这些权限将允许你的应用访问相机和存储设备。

布局文件

现在,我们需要创建一个布局文件来显示相机预览和一些操作按钮。在res/layout目录中创建一个新的XML文件,并命名为activity_camera.xml。在文件中添加以下代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".CameraActivity">

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

    <Button
        android:id="@+id/button_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Capture"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:id="@+id/button_gallery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Gallery"
        android:layout_above="@id/button_capture"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

这个布局文件将显示一个相机预览和两个按钮:一个用于拍照,一个用于访问相册。

创建相机活动

现在,我们需要创建一个新的活动来管理相机功能。在项目中创建一个新的Java类,命名为CameraActivity。在类中添加以下代码:

public class CameraActivity extends AppCompatActivity {

    private Camera mCamera;
    private CameraPreview mCameraPreview;

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

        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);

        FrameLayout preview = findViewById(R.id.camera_preview);
        preview.addView(mCameraPreview);

        Button captureButton = findViewById(R.id.button_capture);
        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.takePicture(null, null, mPicture);
            }
        });

        Button galleryButton = findViewById(R.id.button_gallery);
        galleryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, 0);
            }
        });
    }

    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 处理照片数据和保存照片
        }
    };

    private Camera getCameraInstance(){
        Camera camera = null;
        try {
            camera = Camera.open();
        }
        catch (Exception e){
            Log.e("CameraActivity", "Failed to open camera: " + e.getMessage());
        }
        return camera;
    }
}

在这个活动中,我们获取了相机的实例并创建了一个CameraPreview实例来显示相机预览。当用户点击拍照按钮时,我们调用mCamera.takePicture()方法来拍照。当用户点击相册按钮时,我们通过一个Intent来启动相册。

创建相机预览类

接下来,我们需要创建一个自定义视图类来显示相机预览。在你的项目中创建一个新的Java类,命名为CameraPreview。在类中添加以下代码:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.e("CameraPreview", "Error setting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // 释放相机资源
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 处理相机预览变化
        if (mHolder.getSurface() == null){
            return;
        }

        try {
            mCamera.stopPreview();
        } catch (Exception e){
            Log.e("CameraPreview", "Error stopping camera preview: " + e.getMessage());
        }

        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e){
            Log.e("CameraPreview", "Error starting camera preview: " + e.getMessage());
        }
    }
}

这个自定义视图类实现了SurfaceHolder.Callback接口,并在surfaceCreated()方法中设置相机预览,surfaceDestroyed()方法中释放相机资源,以及surfaceChanged()方法中处理相机预览变化。

处理照片数据和保存照片

最后,我们需要在CameraActivity中处理照片数据并保存照片。在CameraActivity中的onPictureTaken()方法中添加以下代码:

private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        // 创建一个文件路径保存照片
        File pictureFile = getOutputMediaFile();
        if (pictureFile == null){
            Log.e("CameraActivity", "Error creating media file, check storage permissions: ");
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.e("CameraActivity", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.e("CameraActivity", "Error accessing file: " + e.getMessage());
        }

        // 刷新相册以显示新照片
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(pictureFile);
        mediaScanIntent.setData(contentUri);
        sendBroadcast(mediaScanIntent);

        // 重新启动相机预览
        mCamera.startPreview();
    }
};

private File getOutputMediaFile(){
    // 创建一个媒体文件目录
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "CameraApp");

    // 创建一个媒体文件名
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    String filePath = mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg";
    mediaFile = new File(filePath);

    return mediaFile;
}

在这里,我们通过getOutputMediaFile()方法创建了一个文件路径来保存照片。我们使用FileOutputStream来写入照片数据,并使用sendBroadcast()方法来刷新相册以显示新照片。最后,我们重新启动相机预览。

测试应用

现在,你可以运行你的应用并测试拍照和相册访问功能。当你点击拍照按钮时,应用会拍摄一张照片并保存到你的设备上。当你点击相册按钮时,应用会打开系统相册并允许你选择一张照片。

在本篇博客中,我们介绍了如何开发拍照功能和相册访问的安卓手机相机应用。通过使用相机和相册的API,我们可以创建强大的、功能丰富的相机应用,为用户提供更好的拍摄和分享体验。希望本篇博客对你的安卓开发学习有所帮助!


全部评论: 0

    我有话说: