兼容7.0下载安装及打开相机相册适配问题记录
2017-09-05 16:59
501 查看
一、兼容7.0安装新版本及安装之后打开app
//安装工具类 public class InstallUtil { /** * 通过非Root模式安装 * * @param context * @param apkPath */ public static void install(Context context, String apkPath) { //提升读写权限,否则可能出现解析异常 setPermission(apkPath); installNormal(context, apkPath); } /** * 提升读写权限 * @param filePath 文件路径 * @return * @throws IOException */ public static void setPermission(String filePath) { String command = "chmod " + "777" + " " + filePath; Runtime runtime = Runtime.getRuntime(); try { runtime.exec(command); } catch (IOException e) { e.printStackTrace(); } } //普通安装 private static void installNormal(Context context, String apkPath) { Intent intent = new Intent(Intent.ACTION_VIEW); //加上这句话解决安装之后可以显示开打app的页面配合Process.killProcess(Process.myPid());使用 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //版本在7.0以上是不能直接通过uri访问的 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { File file = (new File(apkPath)); //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 由于没有在Activity环境下启动Activity,设置下面的标签 //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致 参数3 共享的文件 Uri apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".fileprovider", file); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(new File(apkPath)), "application/vnd.android.package-archive"); } context.startActivity(intent); //加上这句话解决安装之后可以显示开打app的页面配合FLAG_ACTIVITY_NEW_TASK使用 Process.killProcess(Process.myPid()); } }
在AndroidManifest.xml中配置
<!-- 解决7.0以上文件权限问题 --> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path" /> </provider>
在res新建xml文件夹,新建file_path.xml文件
<?xml version="1.0" encoding="utf-8"?> <paths> <!-- xml文件是唯一设置分享的目录 ,不能用代码设置 1.<files-path> getFilesDir() /data/data//files目录 2.<cache-path> getCacheDir() /data/data//cache目录 3.<external-path> Environment.getExternalStorageDirectory() SDCard/Android/data/你的应用的包名/files/ 目录 4.<external-files-path> Context#getExternalFilesDir(String) Context.getExternalFilesDir(null). 5.<external-cache-path> Context.getExternalCacheDir(). --> <!-- path :代表设置的目录下一级目录 eg:<external-path path="images/" 整个目录为Environment.getExternalStorageDirectory()+"/images/" name: 代表定义在Content中的字段 eg:name = "myimages" ,并且请求的内容的文件名为default_image.jpg 则 返回一个URI content://com.example.myapp.fileprovider/myimages/default_image.jpg --> <!--下载apk--> <external-path name="sdcard_files" path="" /> <!--相机相册裁剪--> <external-files-path name="camera_has_sdcard" path="file/" /> <files-path name="camera_no_sdcard" path="" /> <root-path name="external_files" path="/storage" /> </paths>
二、打开相机及相册适配问题
/** * Created by xiaoyao on 2017/8/24. * <p> * 带有拍照和读取相册功能的基类 */ public abstract class BaseCameraActivity extends BaseAppActivity { private static final int IMAGE_REQUEST_CODE = 100; private static final int SELECT_PIC_NOUGAT = 101; private static final int RESULT_REQUEST_CODE = 102; private static final int CAMERA_REQUEST_CODE = 104; BottomCameraDialog bottomCameraDialog; String path = Environment.getExternalStorageDirectory() + "/Android/data/" + AppUtils.getPackageName() + "/files/"; File mCameraFile; File mCropFile; File mGalleryFile; /** * 底部Dialog */ public void showBottomDialog() { mCameraFile = new File(path, String.valueOf(System.currentTimeMillis()) + "camera_name.jpg");//照相机的File对象 mCropFile = new File(path, String.valueOf(System.currentTimeMillis()) + "crop_name.jpg");//裁剪后的File对象 mGalleryFile = new File(path, String.valueOf(System.currentTimeMillis()) + "gallery_name.jpg");//相册的File对象 requestRuntimePermission(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, new PermissionListener() { @Override public void onGranted() { bottomCameraDialog = new BottomCameraDialog(BaseCameraActivity.this).builder(); bottomCameraDialog .setCancelable(true) .setCanceledOnTouchOutside(true) .setOnClickListener(new BottomCameraDialog.OnClickListener() { @Override public void gotoOpenCamera() { openCamera(); } @Override public void gotoOpenGallery() { openGallery(); } }) .show(); } @Override public void onDenied(List<String> deniedPermission) { } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { //照相后返回 case CAMERA_REQUEST_CODE: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri inputUri = FileProvider.getUriForFile(this, AppUtils.getPackageName() + ".fileprovider", mCameraFile);//通过FileProvider创建一个content类型的Uri startPhotoZoom(inputUri);//设置输入类型 } else { Uri inputUri = Uri.fromFile(mCameraFile); startPhotoZoom(inputUri); } break; //版本<7.0 图库后返回 case IMAGE_REQUEST_CODE: if (data != null) { // 得到图片的全路径 Uri uri = data.getData(); //crop(uri); startPhotoZoom(uri); } break; //版本>= 7.0 case SELECT_PIC_NOUGAT: if (data != null) { File imgUri = new File(GetImagePath.getPath(this, data.getData())); Uri dataUri = FileProvider.getUriForFile (this, AppUtils.getPackageName() + ".fileprovider", imgUri); // Uri dataUri = getImageContentUri(data.getData()); startPhotoZoom(dataUri); } break; case RESULT_REQUEST_CODE: Uri inputUri = FileProvider.getUriForFile(this, AppUtils.getPackageName() + ".fileprovider", mCropFile);//通过FileProvider创建一个content类型的Uri Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(inputUri)); } catch (FileNotFoundException e) { e.printStackTrace(); } getCameraGalleryImg(mCropFile, bitmap); break; } } /** * 打开相册 */ public void openGallery() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//如果大于等于7.0使用FileProvider Uri uriForFile = FileProvider.getUriForFile (this, AppUtils.getPackageName() + ".fileprovider", mGalleryFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivityForResult(intent, SELECT_PIC_NOUGAT); } else { intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mGalleryFile)); startActivityForResult(intent, IMAGE_REQUEST_CODE); } } /** * 开启摄像机 */ public void openCamera() { Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0及以上 Uri uriForFile = FileProvider.getUriForFile(this, AppUtils.getPackageName() + ".fileprovider", mCameraFile); intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile); intentFromCapture.addFlags(FLAG_GRANT_READ_URI_PERMISSION); intentFromCapture.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION); } else { intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mCameraFile)); } startActivityForResult(intentFromCapture, CAMERA_REQUEST_CODE); } /** * 裁剪图片方法实现 * * @param inputUri */ public void startPhotoZoom(Uri inputUri) { if (inputUri == null) { Log.e("error", "The uri is not exist."); return; } Intent intent = new Intent("com.android.camera.action.CROP"); //sdk>=24 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri outPutUri = Uri.fromFile(mCropFile); intent.setDataAndType(inputUri, "image/*"); intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri); intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION); } else { Uri outPutUri = Uri.fromFile(mCropFile); if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { String url = ImageUtils.getPath(this, inputUri);//这个方法是处理4.4以上图片返回的Uri对象不同的处理方法 intent.setDataAndType(Uri.fromFile(new File(url)), "image/*"); } else { intent.setDataAndType(inputUri, "image/*"); } intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri); } // 设置裁剪 intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 0.1); intent.putExtra("aspectY", 0.1); // outputX outputY 是裁剪图片宽高 intent.putExtra("outputX", 800); intent.putExtra("outputY", 500); intent.putExtra("return-data", false); intent.putExtra("noFaceDetection", false);//去除默认的人脸识别,否则和剪裁匡重叠 intent.putExtra("outputFormat", "JPEG"); //intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());// 图片格式 startActivityForResult(intent, RESULT_REQUEST_CODE);//这里就将裁剪后的图片的Uri返回了 } public abstract void getCameraGalleryImg(File imgFile, Bitmap bitmap); }
解决Android4.4分水岭问题类
public class GetImagePath { // 4.4以上 content://com.android.providers.media.documents/document/image:3952 // 4.4以下 content://media/external/images/media/3951 @SuppressLint("NewApi") public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final 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; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{ split[1] }; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { // Return the remote address if (isGooglePhotosUri(uri)) return uri.getLastPathSegment(); return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } //Android 4.4以下版本自动使用该方法 public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); } }
相关文章推荐
- Android调用系统相机、相册功能,适配6.0权限获取以及7.0以后获取URI(兼容多版本)
- Android 7.0+相机、相册、裁剪适配问题
- 彻底解决兼容问题:Windows 7下载安装 Visual C++ 6.0(VC6) 全程图解
- 在网上整理的关于打开相机和相册并设置成头像的问题
- android 打开相机/打开相册(版本兼容)-获取照片,压缩100K一下保存到本地
- 下载的apk无法安装等问题,文件无法打开
- 打开相册和相机时状态栏不隐藏的问题
- JS中兼容实现android和ios系统手机打开相机并可选择相册功能
- Android webview支持type="file" 打开相机和相册兼容5.0+
- Android 7.0实际开发中调用系统相机和获取相册照片遇到的坑具备向下兼容
- Android解决小米手机相机和相册的问题(适配小米手机相机和相册)
- discuz论坛和PHP7.0有兼容问题安装不了
- 【转载】解决浏览器和discuz7.0论坛不兼容的方法,解决快捷回复弹出下载窗口的问题
- MySQL导出记录到Excel表格下载打开后乱码问题
- 关于小米4 以及酷派手机安卓开发 调用相机相册适配的问题
- 彻底解决兼容问题:Windows 7下载安装 Visual C++ 6.0(VC6) 全程图解
- iOS企业发布问题记录一(为什么iOS的应用安装到一半时提示"无法下载应用程序"?)
- 安卓开发小米4,酷派 手机适配和调用系统相机相册做图片上传的问题
- 解决 在线视频,当打开页面时,如果安装了迅雷,会提示下载的问题。
- Android基础--调用系统相机,打开相册,展示到界面,出现的一些问题Uri为空,data为null,图片错乱问题