系统相机折腾了我两天。。。。 本来我是照着视频学的,然鹅出了好几个问题,一会是指定的图片路径不行,一会又是调用相机后点击确认没反应,真的是头疼 经过仔细查阅资料,我发现,因为Android在API24以后对访问权限回收,也就是说,用一个app调用另一个app,第二个app是没有第一个app调用的文件夹的读写权限的。。。自从API23之后真是越来越安全了呢。。。。。 所以,需要向系统相机发送 content://URI,并授予 URI 临时访问权限。而进行此授权的最简单方式是使用 FileProvider类。
步骤如下:
1.在AndroidManifest.xml中加入FileProvider注册
<provider
android:authorities="包名.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
2.配置filepaths文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- external-path:sd ;path:你的应用保存文件的根目录;name随便定义-->
<!-- root-path 手机存储根目录 -->
<root-path path="" name="posture" />
</paths>
3.调用相机代码
public class MainActivity extends AppCompatActivity {
private static int REQ_1=1;
private static int REQ_2=2;
private ImageView mImageView;
private String mFilePath;
private String mFileName;
Button camera2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
camera2 = findViewById(R.id.camerabutton2);
saveInRoot();//这个函数是检测路径用的
mImageView = findViewById(R.id.iv);
mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath+"/postureTemp/";
// Uri photoUri = Uri.parse(mFilePath);
//
// String path = getSDPath();
camera2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
jump2Camera();
}
});
}
// 这是另一个按钮调用相机的,只能在view里显示缩略图
public void startCamera(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
public void jump2Camera() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File path = new File(mFilePath);
if (!path.exists()) {
path.mkdirs();
}
mFileName = System.currentTimeMillis() + ".jpg";
File file = new File(path, mFileName);
if (file.exists()) {
file.delete();
}
// FileUtils.startActionCapture(this,file,REQ_2);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriForFile(this, file));
startActivityForResult(intent, REQ_2);
} else {
Log.e("main","sdcard not exists");
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQ_1){
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
mImageView.setImageBitmap(bitmap);
}
else if(requestCode == REQ_2){
FileInputStream fis = null;
Toast.makeText(MainActivity.this, "拍完了...", Toast.LENGTH_SHORT).show();
// 将图片展示在imageView里
try{
fis = new FileInputStream(mFilePath+mFileName);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
mImageView.setImageBitmap(bitmap);
}catch (FileNotFoundException e){
e.printStackTrace();
}finally {
try{
fis.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
}
}
public static Uri getUriForFile(Context context, File file) {
if (context == null || file == null) {
throw new NullPointerException();
}
Uri uri;
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(), "com.example.posturer.fileprovider", file);
Log.e("qq", "外部存储可用..." + uri.toString());
} else {
uri = Uri.fromFile(file);
}
return uri;
}
public String getSDPath() {
File sdDir = null;
//判断sd卡是否存在
boolean sdCardExist = Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED);
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();//获取根目录
Log.e("qq", "外部存储可用..." + sdDir.toString());
// Toast.makeText(MainActivity.this, "外部存储可用...", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "外部存储不可用...", Toast.LENGTH_SHORT).show();
}
return sdDir.toString();
}
//使用
private void saveInRoot() {
if (getSDPath()!=null) {
String fileName = getSDPath() + "/";
File file = new File(fileName,"postureTemp");//参数
if (!file.mkdir()) {
// Toast.makeText(MainActivity.this, "目录已存在...", Toast.LENGTH_SHORT).show();
} else {
// Toast.makeText(MainActivity.this, "创建新目录...", Toast.LENGTH_SHORT).show();
}
}
}
}
4.别忘了申请权限
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
PS
还有一个采坑点,就是按钮的点击事件不要放布局文件里,最好使用setOnClickListener监听器,更好使~