引用链接
Android开发之调用相机拍照与本地图库选择图片
Android调用相机实现拍照功能
部分截图
引言
小项目有一个访问相册的需求,在网上查找得到两位大神博客指点,但博客发布时间过旧,难免因更新而产生Bug,我便把Bug进行修改并对代码进行了适量调整,供大家参考
MainActivity2
package com.example.myapplication;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import java.io.File;
public class MainActivity2 extends AppCompatActivity {
private static final String TAG = "图片";
private static final int TAKE_PHOTO = 11;// 拍照
private static final int CROP_PHOTO_TAKE = 12;// 裁剪图片
private static final int CROP_PHOTO_LOCAL = 14;// 裁剪图片
private static final int LOCAL_CROP = 13;// 本地图库
private Button btn_choose_picture;
private ImageView iv_show_picture;
private Uri imageUri;// 拍照时的图片uri
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
setViews();// 初始化控件
setListeners();// 设置监听
requestPermission(); //在其中若用户给予权限则请求相机拍照
}
//动态请求权限
private void requestPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
}
}
/**
* 设置监听
*/
private void setListeners() {
// 展示图片按钮点击事件
btn_choose_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePhotoOrSelectPicture();// 拍照或者调用图库
}
});
}
/**
*
*/
private void takePhotoOrSelectPicture() {
CharSequence[] items = {"拍照", "图库"};// 裁剪items选项
// 弹出对话框提示用户拍照或者是通过本地图库选择图片
new AlertDialog.Builder(MainActivity2.this)
.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
// 选择了拍照
case 0:
// 创建文件保存拍照的图片
File takePhotoImage = new File(Environment.getExternalStorageDirectory(), "take_photo_image.jpg");
try {
// 文件存在,删除文件
if (takePhotoImage.exists()) {
takePhotoImage.delete();
}
// 根据路径名自动的创建一个新的空文件
takePhotoImage.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
// 获取图片文件的uri对象
// imageUri = Uri.fromFile(takePhotoImage);
if (Build.VERSION.SDK_INT >= 24) {
imageUri = FileProvider.getUriForFile(MainActivity2.this,
"com.example.myapplication.MainActivity2", takePhotoImage);
} else {
imageUri = Uri.fromFile(takePhotoImage);
}
// 创建Intent,用于启动手机的照相机拍照
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定输出到文件uri中
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
// 启动intent开始拍照
startActivityForResult(intent, TAKE_PHOTO);
break;
// 调用系统图库
case 1:
// 创建Intent,用于打开手机本地图库选择图片
Intent intent1 = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// 启动intent打开本地图库
startActivityForResult(intent1, LOCAL_CROP);
break;
}
}
}).show();
}
/**
* 调用startActivityForResult方法启动一个intent后,
* 可以在该方法中拿到返回的数据
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PHOTO:// 拍照
if (resultCode == RESULT_OK) {
// 创建intent用于裁剪图片
Intent intent = new Intent("com.android.camera.action.CROP");
// 设置数据为文件uri,类型为图片格式
intent.setDataAndType(imageUri, "image/*");
// 允许裁剪
intent.putExtra("scale", true);
// 指定输出到文件uri中
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 启动intent,开始裁剪
startActivityForResult(intent, CROP_PHOTO_TAKE);
}
break;
case LOCAL_CROP:// 系统图库
if (resultCode == RESULT_OK) {
// 创建intent用于裁剪图片
Intent intent1 = new Intent("com.android.camera.action.CROP");
// 获取图库所选图片的uri
Uri uri = data.getData();
intent1.setDataAndType(uri, "image/*");
// 设置裁剪图片的宽高
intent1.putExtra("outputX", 300);
intent1.putExtra("outputY", 300);
// 裁剪后返回数据
intent1.putExtra("return-data", true);
// 启动intent,开始裁剪
startActivityForResult(intent1, CROP_PHOTO_LOCAL);
}
break;
case CROP_PHOTO_TAKE:// 裁剪后展示图片
if (resultCode == RESULT_OK) {
try {
// 展示拍照后裁剪的图片
if (imageUri != null) {
// 创建BitmapFactory.Options对象
BitmapFactory.Options option = new BitmapFactory.Options();
// 属性设置,用于压缩bitmap对象
option.inSampleSize = 2;
option.inPreferredConfig = Bitmap.Config.RGB_565;
// 根据文件流解析生成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri), null, option);
// 展示图片
iv_show_picture.setImageBitmap(bitmap);
}
} catch (Exception e) {
e.printStackTrace();
}
}
break;
case CROP_PHOTO_LOCAL:// 裁剪后展示图片
if (resultCode == RESULT_OK) {
try {
// 展示图库中选择裁剪后的图片
if (data != null) {
// 根据返回的data,获取Bitmap对象
Bitmap bitmap = data.getExtras().getParcelable("data");
// 展示图片
iv_show_picture.setImageBitmap(bitmap);
}
} catch (Exception e) {
e.printStackTrace();
}
}
break;
}
}
/**
* 控件初始化
*/
private void setViews() {
btn_choose_picture = (Button) findViewById(R.id.btn_choose_picture);
iv_show_picture = (ImageView) findViewById(R.id.iv_show_picture);
}
}
布局activity_main2
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<Button
android:id="@+id/btn_choose_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toTopOf="@+id/iv_show_picture"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_show_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_choose_picture" />
</androidx.constraintlayout.widget.ConstraintLayout>```
manifests中添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
manifests中application添加内容提供者
<!-- 为调用相机拍照设置内容提供者 -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapplication.MainActivity2"
android:exported="false"
android:grantUriPermissions="true"
tools:ignore="WrongManifestParent">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
mainfests中application标签里添加
android:requestLegacyExternalStorage="true"
res\xml目录下新建file_paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path="."/>
</paths>