Android笔记——调用系统相机并保存到指定地址

mac2025-08-01  1

系统相机折腾了我两天。。。。 本来我是照着视频学的,然鹅出了好几个问题,一会是指定的图片路径不行,一会又是调用相机后点击确认没反应,真的是头疼 经过仔细查阅资料,我发现,因为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监听器,更好使~

最新回复(0)