Android(安卓)拍照7.0适配(源码)
16lz
2021-01-25
Android 拍照7.0适配(源码)
从Android 7.0开始,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException。
解决方法:FileProvider方式
源码(没封装)
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks{ @BindView(R.id.bt_choice) TextView bt_choice; @BindView(R.id.bt_take) TextView bt_take; @BindView(R.id.ll_select) LinearLayout ll_select; @BindView(R.id.iv_test) ImageView iv_test; private static String photoName; private static File f_save; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick({R.id.bt_take,R.id.bt_choice}) public void onClick(View view){ switch (view.getId()){ case R.id.bt_choice: if(hasMashroom()){ EasyPermissions.requestPermissions(this,"需要访问网络",2000,new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}); chosePhoto(MainActivity.this,1); }else { chosePhoto(MainActivity.this,1); } break; case R.id.bt_take: if(hasMashroom()){ EasyPermissions.requestPermissions(this,"需要访问网络",2000,new String[] {Manifest .permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}); takePhoto(MainActivity.this,2); }else { takePhoto(MainActivity.this,2); } break; } } public static boolean hasMashroom() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } @Override public void onPermissionsGranted(int requestCode, List perms) { } @Override public void onPermissionsDenied(int requestCode, List perms) { } private static void takePhoto(Activity activity, int cameraRequestCode){ Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 下面这句指定调用相机拍照后的照片存储的路径 Uri uri; String path = Environment.getExternalStorageDirectory()+ "/mycap/"; File file = new File(path); if(!file.exists()){ file.mkdirs(); } photoName=System.currentTimeMillis()+".jpg"; f_save = new File(path, photoName); if (hasMashroom()) { intent1.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); uri = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName()+ ".provider", f_save); } else { uri = Uri.fromFile(f_save); } intent1.putExtra(MediaStore.EXTRA_OUTPUT, uri); activity.startActivityForResult(intent1, cameraRequestCode); } private static void chosePhoto(Activity activity,int photoRequestCode){ Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); // activity.startActivityForResult(intent, photoRequestCode); ComponentName componentName = intent.resolveActivity(activity.getPackageManager()); if (componentName != null) { activity.startActivityForResult(intent, photoRequestCode); } } Uri cropUri; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case 2: cropUri = cropPicture(MainActivity.this,f_save); if(null == data){ Log.i("info", "======拍照回来=data=null==22222222"); }else { if (null == data && null == data.getData()) { Log.i("info", "======拍照回来=data.getData()=nullo=="); } else { if (null == parsePicturePath(this, data.getData())) { Log.i("info", "======拍照回来获取路径null=="); } } } break; case 1: if (data != null){ cropUri = cropPicture(this,new File(parsePicturePath(this, data.getData()))); } break; default:break; } } public static Uri cropPicture(Activity mActivity,File file) { // String cropImageName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault()).format(new Date()) + // "-1-" + System.currentTimeMillis() + ".jpg"; //file 是资源 String cropImageName ="mycropimge.jpg"; String path=mActivity.getExternalCacheDir()+"/basePic/"; File pathFile=new File(path); //这里要创建目录 不然部分手机不支持 if (!pathFile.exists()) { pathFile.mkdirs(); } File cropFile = new File(pathFile, cropImageName); Intent intent = new Intent("com.android.camera.action.CROP"); //注意到此处使用的file:// uri类型. //Uri cropUri= Uri.fromFile(cropFile); Uri cropUri ;//剪裁 Uri sourceUri;//资源 if (hasMashroom()) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); sourceUri = FileProvider.getUriForFile(mActivity, mActivity.getApplicationContext().getPackageName()+ ".provider", file); // sourceUri = getImageContentUri(mActivity, file); cropUri= Uri.fromFile(cropFile); } else { sourceUri= Uri.fromFile(file); cropUri = Uri.fromFile(cropFile); } intent.setDataAndType(sourceUri, "image/*"); //此处有问题 intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra("return-data", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); ComponentName componentName = intent.resolveActivity(mActivity.getPackageManager()); if (componentName != null) { mActivity.startActivityForResult(intent, 3); } return cropUri; } public static String parsePicturePath(Context context, Uri uri) { if (null == context || uri == null) return null; boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentUri if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageDocumentsUri if (isExternalStorageDocumentsUri(uri)) { String docId = DocumentsContract.getDocumentId(uri); String[] splits = docId.split(":"); String type = splits[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + File.separator + splits[1]; } } // DownloadsDocumentsUri else if (isDownloadsDocumentsUri(uri)) { String docId = DocumentsContract.getDocumentId(uri); Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); return getDataColumn(context, contentUri, null, null); } // MediaDocumentsUri else if (isMediaDocumentsUri(uri)) { String docId = DocumentsContract.getDocumentId(uri); String[] split = docId.split(":"); String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } String selection = "_id=?"; String[] selectionArgs = new String[]{split[1]}; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (general) else if ("content".equalsIgnoreCase(uri.getScheme())) { if (isGooglePhotosContentUri(uri)) return uri.getLastPathSegment(); return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } private static boolean isExternalStorageDocumentsUri(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } private static boolean isDownloadsDocumentsUri(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } private static boolean isMediaDocumentsUri(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } private static boolean isGooglePhotosContentUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); } private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; String column = "_data"; String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { int index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } finally { try { if (cursor != null) cursor.close(); } catch (Exception e) { e.printStackTrace(); } } return null; }}
布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" tools:context="com.youngch.android.taskphoto.MainActivity"> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <ImageView android:layout_width="200dp" android:layout_height="200dp" android:id="@+id/iv_test" android:background="@mipmap/ic_launcher"/> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:id="@+id/ll_select" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:textSize="18sp" android:gravity="center" android:layout_marginTop="10dp" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:id="@+id/bt_take" android:text="拍照"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:layout_marginTop="10dp" android:background="@color/colorAccent" android:gravity="center" android:id="@+id/bt_choice" android:text="选择照片"/> LinearLayout> LinearLayout> ScrollView>LinearLayout>
文件路径设置
在项目res文件夹下创建xml文件夹
在里面新建file_path.xml文件,如上图
文件中的内容为:
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_files" path="."/> <cache-path name="cache_files" path="."/> paths>
清单文件设置
在application标签下配置provider,如下
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path" /> provider>
代码关联就是在上面源码中的这一句
uri = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName()+ ".provider", f_save);
路还很长,慢慢走
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android使用Google Map API创建的一个根据经纬度定位的程序二
- Android(安卓)Jni , 不同 arm 架构 兼容
- Kotlin的配置(一)
- android如何阻止app_name在标题栏中闪现
- Android问题集锦之四十六:改包名后出现Error type 3
随机推荐
- android 进程与线程 - 开发文档翻译 - 进
- C#、Golang、Python、Java(Android)之间Des
- android_API -- Android(安卓)包的分类
- Android应用开发Android(安卓)常见的设计
- Android(安卓)Native与Html互相调用
- Android(安卓)TextView设置个别字体样式
- 详解 Android(安卓)的 Activity 组件
- Android(安卓)studio 如何在android选项
- Android(安卓)studio下gradle Robolectri
- Android的init过程(二):初始化语言(init.rc)解