android 崩溃捕获

In this tutorial, we’ll be developing an application which displays images captured from camera or gallery using FileProvider. We’ve already developed a similar application in the past. But with the introduction of Android Nougat, it gives a runtime crash saying FileUriExposedException.

在本教程中,我们将开发一个应用程序,该应用程序显示使用FileProvider从相机或画廊捕获的图像。 过去我们已经开发了类似的应用程序 。 但是随着Android Nougat的引入,它给出了FileUriExposedException这样的运行时崩溃信息。

文件提供者 (FileProvider)

FileProvider is a special subclass of ContentProvider which allows sharing of files between application through content URI instead of file:// URI.

FileProvider是ContentProvider的特殊子类,它允许通过内容URI(而不是file:// URI)在应用程序之间共享文件。

Using file:// URI is not the best idea. It gives all apps the permission to access the files once the Storage Permissions are granted.

使用file:// URI并不是最好的主意。 授予存储权限后,它将为所有应用程序授予访问文件的权限。

We somehow need to restrict this such that the user knows the applications with which it would be sharing the files.

我们需要以某种方式进行限制,以使用户知道与之共享文件的应用程序。

For this, we use FileProviders which allow temporary access permissions to the files. Otherwise, we were able to access files from other apps by simply getting their URI from Uri.parse()

为此,我们使用FileProviders ,它们允许对文件的临时访问权限。 否则,我们只需从Uri.parse()获取其URI,便能够从其他应用访问文件。

WRITE_EXTERNAL_STORAGE permission everytime.WRITE_EXTERNAL_STORAGE权限。

定义FileProvider (Defining FileProvider)

To define a FileProvider in our android application, we need to do the following things:

要在我们的android应用程序中定义FileProvider,我们需要做以下事情:

  • Define the FileProvider in your AndroidManifest file在您的AndroidManifest文件中定义FileProvider
  • Create an XML file that contains all paths that the FileProvider will share with other applications创建一个XML文件,其中包含FileProvider将与其他应用程序共享的所有路径
<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="${applicationId}.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths"/></provider>

Create an xml folder inside the res directory.
Add the provider_paths.xml file in it:

在res目录中创建一个xml文件夹。
在其中添加provider_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="https://schemas.android.com/apk/res/android"><external-path name="external_files" path="."/>
</paths>

Depending on the storage we need to access, we pass the value in the external-path.
Example of other values that can be passed – sdcard

根据我们需要访问的存储,我们在外部路径中传递值。
可以传递的其他值的示例– sdcard

Now let’s write our Version 2.0 Application of Capturing Image from Camera And Gallery that works on Android Nougat and above.

现在,让我们编写适用于Android Nougat及更高版本的从Camera and Gallery捕获图像的2.0版应用程序。

项目结构 (Project Structure)

The AndroidManifest.xml with all the permissions looks like:

具有所有权限的AndroidManifest.xml如下所示:

码 (Code)

The code for the activity_main.xml layout is:

activity_main.xml布局的代码为:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"xmlns:app="https://schemas.android.com/apk/res-auto"xmlns:tools="https://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><RelativeLayoutandroid:id="@+id/content_main"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="16dp"app:layout_behavior="@string/appbar_scrolling_view_behavior"><ImageViewandroid:id="@+id/imageView"android:layout_width="250dp"android:layout_height="250dp"android:layout_centerInParent="true"android:adjustViewBounds="true"android:scaleType="centerCrop" /></RelativeLayout><android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="16dp"app:srcCompat="@android:drawable/ic_menu_camera" /></android.support.design.widget.CoordinatorLayout>

The code for the MainActivity.java is given below:

MainActivity.java的代码如下:

package com.journaldev.androidfileprovidercameragallery;import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;import java.io.File;
import java.util.ArrayList;
import java.util.List;import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;public class MainActivity extends AppCompatActivity {Uri picUri;private ArrayList<String> permissionsToRequest;private ArrayList<String> permissionsRejected = new ArrayList<>();private ArrayList<String> permissions = new ArrayList<>();private final static int ALL_PERMISSIONS_RESULT = 107;private final static int IMAGE_RESULT = 200;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FloatingActionButton fab = findViewById(R.id.fab);fab.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {startActivityForResult(getPickImageChooserIntent(), IMAGE_RESULT);}});permissions.add(CAMERA);permissions.add(WRITE_EXTERNAL_STORAGE);permissions.add(READ_EXTERNAL_STORAGE);permissionsToRequest = findUnAskedPermissions(permissions);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (permissionsToRequest.size() > 0)requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]), ALL_PERMISSIONS_RESULT);}}public Intent getPickImageChooserIntent() {Uri outputFileUri = getCaptureImageOutputUri();List<Intent> allIntents = new ArrayList<>();PackageManager packageManager = getPackageManager();Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);for (ResolveInfo res : listCam) {Intent intent = new Intent(captureIntent);intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));intent.setPackage(res.activityInfo.packageName);if (outputFileUri != null) {intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);}allIntents.add(intent);}Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);galleryIntent.setType("image/*");List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0);for (ResolveInfo res : listGallery) {Intent intent = new Intent(galleryIntent);intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));intent.setPackage(res.activityInfo.packageName);allIntents.add(intent);}Intent mainIntent = allIntents.get(allIntents.size() - 1);for (Intent intent : allIntents) {if (intent.getComponent().getClassName().equals("com.android.documentsui.DocumentsActivity")) {mainIntent = intent;break;}}allIntents.remove(mainIntent);Intent chooserIntent = Intent.createChooser(mainIntent, "Select source");chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toArray(new Parcelable[allIntents.size()]));return chooserIntent;}private Uri getCaptureImageOutputUri() {Uri outputFileUri = null;File getImage = getExternalFilesDir("");if (getImage != null) {outputFileUri = Uri.fromFile(new File(getImage.getPath(), "profile.png"));}return outputFileUri;}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == Activity.RESULT_OK) {ImageView imageView = findViewById(R.id.imageView);if (requestCode == IMAGE_RESULT) {String filePath = getImageFilePath(data);if (filePath != null) {Bitmap selectedImage = BitmapFactory.decodeFile(filePath);imageView.setImageBitmap(selectedImage);}}}}private String getImageFromFilePath(Intent data) {boolean isCamera = data == null || data.getData() == null;if (isCamera) return getCaptureImageOutputUri().getPath();else return getPathFromURI(data.getData());}public String getImageFilePath(Intent data) {return getImageFromFilePath(data);}private String getPathFromURI(Uri contentUri) {String[] proj = {MediaStore.Audio.Media.DATA};Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);cursor.moveToFirst();return cursor.getString(column_index);}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);outState.putParcelable("pic_uri", picUri);}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);// get the file urlpicUri = savedInstanceState.getParcelable("pic_uri");}private ArrayList<String> findUnAskedPermissions(ArrayList<String> wanted) {ArrayList<String> result = new ArrayList<String>();for (String perm : wanted) {if (!hasPermission(perm)) {result.add(perm);}}return result;}private boolean hasPermission(String permission) {if (canMakeSmores()) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {return (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);}}return true;}private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {new AlertDialog.Builder(this).setMessage(message).setPositiveButton("OK", okListener).setNegativeButton("Cancel", null).create().show();}private boolean canMakeSmores() {return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);}@TargetApi(Build.VERSION_CODES.M)@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case ALL_PERMISSIONS_RESULT:for (String perms : permissionsToRequest) {if (!hasPermission(perms)) {permissionsRejected.add(perms);}}if (permissionsRejected.size() > 0) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {showMessageOKCancel("These permissions are mandatory for the application. Please allow access.",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {requestPermissions(permissionsRejected.toArray(new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT);}}});return;}}}break;}}
}

Following is are the methods which get the content uri from the filepath provided that the FileProvider has granted the appropriate permissions:

以下是在FileProvider授予适当权限的情况下从文件路径获取内容uri的方法:

The output of the above application in action is given below:

上面应用程序的输出如下:

This brings an end to this tutorial. You can download the project from the link below:

本教程到此结束。 您可以从下面的链接下载项目:

AndroidFileProviderCameraGalleryAndroidFileProviderCameraGallery
Github Project LinkGithub项目链接

翻译自: https://www.journaldev.com/23219/android-capture-image-camera-gallery-using-fileprovider

android 崩溃捕获

android 崩溃捕获_Android使用FileProvider捕获图像相机图库相关推荐

  1. android 崩溃捕获_Android从相机和图库捕获图像

    android 崩溃捕获 In this tutorial we'll develop an application that picks an image from camera or galler ...

  2. android 崩溃日志捕获,安卓Java崩溃的捕获和日志记录

    Android的两种崩溃 Android 崩溃分为 Java 崩溃和 Native崩溃两种. Java崩溃的知识点 Java崩溃.png Java崩溃的原因 简单来说,Java崩溃就是在Java代码中 ...

  3. 基于tcpdump的Android智能移动终端数据包捕获完整解决方案

    基于tcpdump的Android智能移动终端数据包捕获完整解决方案 参考文章: (1)基于tcpdump的Android智能移动终端数据包捕获完整解决方案 (2)https://www.cnblog ...

  4. Photoneo3D相机以每秒40米的速度捕获运动中的物体图像

    在结构光或主动照明设置中,光源(如激光器或LED)将窄带光或图案投射到目标表面.当从光源以外的观察角度成像时,图案会出现扭曲.该图案由摄像机获取,并用于表面形状的几何重建.         结构光技术 ...

  5. MFC 程序崩溃自动重启 和 未捕获到的异常写退出栈

    MFC 程序崩溃自动重启 和 未捕获到的异常写退出栈 2013-09-11 09:39:04|  分类: VS编译集合|举报|字号 订阅 下载LOFTER 我的照片书  | http://blog.c ...

  6. android surfaceview 大小_Android 使用Camera2 API采集视频数据

    Android 视频数据采集系列的最后一篇出炉了,和前两篇文章想比,这篇文章从系统API层面进行一些探索,涉及到的细节更多.初次接触 Camera2 API 会觉得它的使用有些繁琐,涉及到的类有些多, ...

  7. Android总是闪退,怎么办?Android崩溃机制。

    闪退,程序退出这些都是开发中最常见的了.开发过程中,那还好说,遇到就解决被,主要还是应对上线问题.各大平台的捕获机制不少,用就完事了.但,我还是想知道Android崩溃机制. 所谓的闪退就是Andro ...

  8. 【正则表达式系列】一些概念(字符组、捕获组、非捕获组)

    前言 本文介绍一些正则中的常用名词以及对应概念,譬如字符组,捕获组.非捕获组.反向引用.转义和\s \b等 大纲 字符组 捕获组 反向引用 非捕获组 ..\s和\S \b \转义 字符组 []字符组表 ...

  9. 代码:android崩溃日志收集和处理

    用来处理android崩溃日志收集的代码,详情的使用请转:android崩溃日志收集和处理 第一个类 /** * 异常捕捉实现类 */ public class ErrorCaughtimplemen ...

最新文章

  1. php引入PHPMailer发送邮件
  2. centos 6.0 启动失败提示。
  3. c++ socket 连接超时_Web性能优化之-HTTP长连接
  4. c# 索引器基础理论
  5. 支持本地 持久化的 单机版 consul 服务
  6. 本地连接 阿里云 window 服务器mysql 总是2003
  7. Redis单机配置多实例,实现主从同步
  8. 【Matlab】离散点拟合曲面
  9. php基础编程教程 pdf,手把手教你编程打印出PDF_PHP教程
  10. java 区位码转中文_国标码、区位码、机内码之间的转换关系
  11. 《经济机器是怎样运行的》笔记(一)
  12. 原始套接字 发送 TCP SYN 包
  13. [滴滴校招]末尾0的个数
  14. 饭谈:盘点六种错误的技术问题提问
  15. 因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies
  16. mingw+msys windows下配置
  17. 画手cv什么意思_b站cv和op是什么意思
  18. 前端的你平时都在哪找免费的可商业用的图片素材?
  19. 验证码的几种方式-普通图形验证码,滑动拼图,图中点选
  20. 用一个原始密码针对不同软件生成不同密码并保证相对安全

热门文章

  1. [转载] 终于来了!TensorFlow 2.0入门指南(上篇)
  2. [转载] Python数据分析:python与numpy效率对比
  3. [转载] URL短网址生成算法原理
  4. [转载] 卷积神经网络做mnist数据集识别
  5. 机器学习-数据科学库-day1
  6. 题解-Codeforces671D Roads in Yusland
  7. 返回表对象的方法之一--bulk collect into
  8. Postman界面介绍及实例(转)
  9. CSS样式(一)- 基本语法
  10. Finalshell软件安装使用