【android开发-21】android中调用系统摄像头camera拍照和相册的用法详解

1,调用摄像头

在Android中,调用系统摄像头拍照需要使用Intent来启动Camera应用,并在应用中设置相应的权限。下面是一个简单的例子:

cpp 复制代码
// 创建一个Intent对象,指定要执行的动作是拍照  
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  
// 确保应用程序有权限访问相机  
if (intent.resolveActivity(getPackageManager()) != null) {  
    // 创建一个临时的文件来保存拍摄的照片  
    File photoFile = null;  
    try {  
        photoFile = createImageFile();  
    } catch (IOException ex) {  
        // 处理文件创建失败的情况  
    }  
    // 如果文件已成功创建,则继续执行下面的代码  
    if (photoFile != null) {  
        // 将文件URI传递给Intent对象  
        Uri photoURI = FileProvider.getUriForFile(this, "com.example.android.fileprovider", photoFile);  
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);  
        // 启动相机应用,拍摄照片并保存到指定的文件中  
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);  
    }  
}

其中,createImageFile()方法用于创建一个临时文件来保存拍摄的照片。你需要实现该方法并在其中指定文件的名称和保存位置。例如:

cpp 复制代码
private File createImageFile() throws IOException {  
    // 创建一个保存照片的目录  
    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);  
    // 保存文件的路径,用于共享文件  
    mCurrentPhotoPath = image.getAbsolutePath();  
    return image;  
}

在上面的代码中,REQUEST_IMAGE_CAPTURE是一个整数常量,用于标识启动相机的请求。你需要在Activity类中定义一个成员变量来保存该常量,并在onActivityResult()方法中处理拍照结果。例如:

cpp 复制代码
private static final int REQUEST_IMAGE_CAPTURE = 1;  
  
@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {  
        // 处理拍摄的照片,例如显示在ImageView中或保存到数据库中  
        Bundle extras = data.getExtras();  
        Bitmap imageBitmap = (Bitmap) extras.get("data");  
        mImageView.setImageBitmap(imageBitmap);  
    }  
}

在Android中,要调用系统摄像头拍照,需要在AndroidManifest.xml文件中声明必要的权限,并在需要使用摄像头拍照的地方请求这些权限。此外,还需要使用Content Provider来注册摄像头提供者。以下是一个简单的例子:

首先,在AndroidManifest.xml文件中声明权限:

cpp 复制代码
<uses-permission android:name="android.permission.CAMERA" />  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

然后,在需要使用摄像头拍照的地方请求这些权限。例如,在一个Activity中,可以使用以下代码:

cpp 复制代码
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {  
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);  
}

请注意,你需要在你的应用的Manifest文件中注册你的Provider,例如:

cpp 复制代码
<provider android:name=".MyProvider" android:authorities="com.example.android.fileprovider" />

其中,"com.example.android.fileprovider"是你自己定义的authority名称,需要与你在createImageFile()方法中的"com.example.android.fileprovider"相匹配。

FileProvider是Android中用于实现不同应用间文件共享的工具。它继承自ContentProvider,主要用于在应用间共享文件时提供文件访问的接口。

要使用FileProvider,首先需要在AndroidManifest.xml文件中注册该Provider,并声明其权限。例如:

cpp 复制代码
<provider android:name="androidx.core.content.FileProvider"   
          android:authorities="com.example.app.fileprovider"  
          android:exported="false"  
          android:grantUriPermissions="true">  
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS"   
              android:resource="@xml/file_paths"></meta-data>  
</provider>

其中,android:authorities属性指定了该Provider的权限,android:grantUriPermissions属性允许其他应用通过URI访问该Provider所共享的文件,android:exported属性表示该Provider是否允许其他应用访问。

在上述代码中,我们使用标签来指定共享文件的路径。这些路径需要在res/xml/file_paths.xml文件中定义。例如:

cpp 复制代码
<paths>  
    <files-path name="shared_images" path="shared_images/"/>  
</paths>

在应用中,我们可以使用FileProvider来获取共享文件的URI,并通过该URI来访问共享文件。例如:

cpp 复制代码
File file = new File(context.getExternalFilesDir(null), "shared_images/test.jpg");  
Uri fileUri = FileProvider.getUriForFile(context, "com.example.app.fileprovider", file);

上述代码中,我们首先创建一个File对象,表示共享文件的路径。然后,我们使用FileProvider的静态方法getUriForFile()来获取该文件的URI。该URI可以用于在应用中访问该文件,例如将其显示在ImageView中或将文件保存到另一个应用中。

2,从相册中选择照片

在Android中,从相册选择照片需要申请读取外部存储的权限。以下是一个示例代码,展示如何在Android中申请读取外部存储的权限:

首先,在AndroidManifest.xml文件中添加以下权限声明:

cpp 复制代码
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

然后,在Activity中,你可以使用以下代码来请求读取外部存储的权限:

cpp 复制代码
// 检查是否已经拥有读取外部存储的权限  
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)  
        != PackageManager.PERMISSION_GRANTED) {  
    // 如果没有权限,则请求权限  
    ActivityCompat.requestPermissions(this,  
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},  
            REQUEST_CODE_PERMISSIONS);  
} else {  
    // 已经拥有权限,可以从相册选择照片了  
    selectPhotoFromGallery();  
}

在上面的代码中,我们首先使用ContextCompat.checkSelfPermission()方法来检查是否已经拥有读取外部存储的权限。如果没有权限,则使用ActivityCompat.requestPermissions()方法来请求权限。在这个示例中,我们将请求码设置为REQUEST_CODE_PERMISSIONS,你可以根据需要进行修改。当用户授予或拒绝权限时,系统会回调onRequestPermissionsResult()方法。因此,你需要在Activity中重写该方法来处理权限请求的结果:

cpp 复制代码
@Override  
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
    if (requestCode == REQUEST_CODE_PERMISSIONS) {  
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
            // 权限已授予,可以从相册选择照片了  
            selectPhotoFromGallery();  
        } else {  
            // 权限被拒绝,无法从相册选择照片  
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();  
        }  
    }  
}

最后,您需要实现selectPhotoFromGallery()方法来启动选择照片的Intent。以下是一个示例实现:

cpp 复制代码
// 请求码,用于在AndroidManifest.xml中声明权限  
private static final int REQUEST_SELECT_PHOTO = 1;  
  
// 创建一个选择照片的Intent  
private void selectPhotoFromGallery() {  
    Intent intent = new Intent();  
    // 设置Intent类型和操作,为了从相册中选择照片  
    intent.setType("image/*");  
    intent.setAction(Intent.ACTION_GET_CONTENT);  
    // 启动Intent,并在选择照片后返回到当前Activity  
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), REQUEST_SELECT_PHOTO);  
}  
  
// 重写onActivityResult方法,处理从相册返回的照片  
@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);  
    if (requestCode == REQUEST_SELECT_PHOTO && resultCode == RESULT_OK && data != null && data.getData() != null) {  
        Uri selectedImageUri = data.getData();  
        try {  
            // 使用BitmapFactory从Uri获取Bitmap对象  
            Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImageUri));  
            // 在这里处理选定的图片,例如显示在ImageView中或保存到文件中。  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        }  
    }  
}

这段代码首先创建一个类型为"image/*"、操作为"GET_CONTENT"的Intent,然后使用Intent.createChooser()创建一个选择器,标题为"Select Picture"。然后,调用startActivityForResult()启动这个Intent,在用户选择照片后返回到当前Activity。在onActivityResult()方法中,我们检查请求码和结果码是否匹配,然后从返回的Intent中获取照片的URI,并使用BitmapFactory.decodeStream()从该URI获取Bitmap对象。最后,你可以在此处处理选定的图片,例如将其显示在ImageView中或保存到文件中。

3,完整项目代码

该项目app可以直接实现从相册中适配不同分辨率的照片或者打开摄像头直接拍照,然后把照片直接显示到ImageView中。如下效果:

完整项目app的实现代码下载路径:https://download.csdn.net/download/jiangchaobing_2017/88609936

相关推荐
用户201879283167几秒前
AMS和app通信的小秘密
android
用户2018792831672 分钟前
ThreadPoolExecutor之市场雇工的故事
android
诺诺Okami5 分钟前
Android Framework-Launcher-InvariantDeviceProfile
android
Antonio9151 小时前
【音视频】Android NDK 与.so库适配
android·音视频
buleideli2 小时前
Android相机API2,基于GLSurfaceView+SurfaceTexture实现相机预览,集成的相机算法采用GPU方案,简要说明
数码相机
点云SLAM2 小时前
结构光三维重建原理详解(1)
人工智能·数码相机·计算机视觉·三维重建·结构光重建·gray 编码·标定校正
把玩计算机4 小时前
相机几何 空间点到像素平面转换
数码相机·平面
sun00770010 小时前
android ndk编译valgrind
android
AI视觉网奇11 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空11 小时前
android studio gradle 访问不了
android·ide·android studio