一、主代码编写
package com.example.take_photo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
public static final int TAKE_PHOTO=1;
private ImageView picture;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button takePhoto=findViewById(R.id.take_photo);
picture=findViewById(R.id.picture);
takePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建File对象,用于存储拍照后的图片
/*getExternalCacheDir()对应着应用程序内的外部缓存,同样是
用来存储临时数据的。但是由于其脱离了应用管理,因此并不会在空间
少时被自动清除。存放路径一般是/storage/sdcard/Android/data
/应用包名>/cache目录
*/
File outputImage=new File(getExternalCacheDir(),
"output_image.jpg");
try {
if (outputImage.exists()){
outputImage.delete();
}
outputImage.createNewFile();
//IOException,I/O:inputStream/outputStream,一般在读写数据的时候会出现这种异常
/*
java内部读写数据实现逻辑:
java内部数据的传输都是通过流,或者byte来进行传递的。可以通过in流写入到java中,
同时也可以通过out流从java返还给具体的文件
*/
}catch (IOException e){
e.printStackTrace();
}
//Build.VERSION.SDK_INT代表操作系统的版本号,24表示android 7.0
if (Build.VERSION.SDK_INT>=24){
//FileProvider这个组件是ContentProvider的子类,功能就是用来提供文件在跨进程间的访问能力
imageUri=FileProvider.getUriForFile(MainActivity.this,"com.example.take_photo.fileprovider",outputImage);
}else {
//获取文件的路径
imageUri=Uri.fromFile(outputImage);
}
//启动相机程序
//隐式intent,android.media.action.IMAGE_CAPTURE表示从现有的相机应用中请求一张图片
Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");
//表示将拍照的图片存在我们之前设定的imageUri路径上
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
//表示从主界面跳转到拍照界面然后返回到主界面并且获取到从拍照界面传回来的参数
startActivityForResult(intent,TAKE_PHOTO);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case TAKE_PHOTO:
if (resultCode==RESULT_OK){
try {
//将拍摄的照片显示出来
/*
BitmapFactory:是一个工具类,它提供了大量的方法,这个方法可用于不同的数据源来解析,创建Bitmap对象
decodeStream():用于从指定输入流中解析、创建Bitmap对象
getContentResolver():因为在android中,每个应用程序是可以实现数据共享的,对于每一个应用程序
程序都拥有一个contentProvider实例进行存储,而contentResolver则是用于管理所有程序的contentProvider实例
通过contentResolver可以获得数据,插入数据等...至于getContentResolver()就是获取实例。
*/
Bitmap bitmap=BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
二、在AndroidManifest.xml文件中注册内容提供器
<provider
android:authorities="com.example.take_photo.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
三、在res目录下新建xml文件夹,并创建file_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--external-path就是用来指定Uri共享的,name属性的值可以随便填,path属性值表示共享的具体路径。这里设置空值就表示
将整个SD卡进行共享,当然也可以仅共享我们存放output_image.jpg这张图片的路径-->
<external-path
name="my_images"
path="."/>
</paths>