• (AS笔记)Android选择图片+HttpURLConnection表单POST上传图片到后端


    目录

    一、前言

    二、SpringBoot后端接口

    三、Android布局

    四、Fragment代码实现

            (1)获取View控件

            (2)请求读写权限,授权再次点击+号打开相册

            (3)相册选择回调图片Uri

    五、效果测试 

    六、Android网络请求表单提交图片数据

            (1)HttpUtil请求工具类

            (2)开始调用后端接口,上传图片

            (3)执行成功 

    七、权限工具类

    八、总结


    一、前言

            选择图片上传到后端,生成http:域名:端口:/xxx.jpg,将此URL路径存MySQL,Android查询查询数据库获取URL字段数据,使用Glide加载网络图片。


    二、SpringBoot后端接口

    1. @PostMapping("/uploadFile")
    2. public String uploadFile(@RequestParam(value = "imgFile") MultipartFile imgFile) throws IOException {
    3. if (imgFile != null && !imgFile.isEmpty()) {
    4. //获取文件名
    5. String filename = imgFile.getOriginalFilename(); //图片名
    6. String[] split = new String[0];
    7. if (filename != null) {
    8. split = filename.split("\\.");
    9. }
    10. //只接受jpg、png、jpeg格式图片文件,其它格式的文件可按需添加判断,主要是为了防止上传恶意文件,加强安全性
    11. if ("jpg".equalsIgnoreCase(split[1]) || "png".equalsIgnoreCase(split[1]) || "jpeg".equalsIgnoreCase(split[1])) {
    12. //图片重命名加后缀
    13. String photoName = UUID.randomUUID().toString().replace("-", "") + "." + split[1];
    14. File destFile = new File(logoRealFolderPath + File.separator + photoName);
    15. //判断是否存在, 不存在就创建
    16. if (!destFile.getParentFile().exists()) {
    17. destFile.getParentFile().mkdirs();
    18. }
    19. //压缩图片保存
    20. Thumbnails.of(imgFile.getInputStream()).scale(0.8).toFile(destFile);
    21. //获取协议、服务器IP、端口号、工程路径
    22. String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
    23. String httpUrl = basePath + uploadReflexPath + photoName;
    24. System.out.println("完成URL地址 = " + httpUrl);
    25. //获取到URL后,可以将URL保存到数据库中,以便后续使用,这里就不做演示了,使用Mybatis即可
    26. if (testService.addUrl(httpUrl) == 0) {
    27. return "保存URL到数据库失败";
    28. } else {
    29. return "保存URL到数据库成功,文件地址为:" + httpUrl;
    30. }
    31. }
    32. }
    33. return "请上传文件后重试";
    34. }

            说明:api接口:/uploadFile,post的key(表单的name):imgFile


    三、Android布局

    1. "1.0" encoding="utf-8"?>
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:app="http://schemas.android.com/apk/res-auto"
    4. android:layout_width="match_parent"
    5. android:layout_height="match_parent">
    6. <LinearLayout
    7. android:layout_centerInParent="true"
    8. android:layout_width="match_parent"
    9. android:layout_height="wrap_content"
    10. android:orientation="vertical">
    11. <androidx.appcompat.widget.AppCompatImageView
    12. android:id="@+id/iv_register_permission_logo"
    13. android:layout_width="80dp"
    14. android:layout_height="80dp"
    15. android:scaleType="centerCrop"
    16. android:layout_gravity="center"
    17. android:background="@drawable/bg_box_gray"
    18. android:src="@drawable/ic_baseline_add_24" />
    19. <androidx.appcompat.widget.AppCompatTextView
    20. android:id="@+id/tv_permission_show"
    21. android:layout_width="match_parent"
    22. android:layout_height="wrap_content"
    23. android:layout_marginTop="5dp"
    24. android:gravity="center"
    25. android:text="@string/add_permission_logo"
    26. android:textColor="#1E88E5"
    27. android:textSize="14sp"
    28. android:textStyle="bold" />
    29. LinearLayout>
    30. RelativeLayout>

            bg_box_gray.xml

    1. "1.0" encoding="utf-8"?>
    2. <shape xmlns:android="http://schemas.android.com/apk/res/android">
    3. <solid android:color="#00000000"/>
    4. <stroke
    5. android:width="1dip"
    6. android:color="#383838"/>
    7. <corners android:radius="15dp" />
    8. shape>


    四、Fragment代码实现

            我是在ViewPager2中Fragment进行布局的,你们可以换成Activity,完全不影响。

            代码的话,我进行步骤讲解,涉及到公司业务代码,这里抱歉,不方便全部粘出来,我会尽量按步骤说清楚。

            (1)获取View控件

    1. //图标选择
    2. private AppCompatImageView ivRegisterPermissionLogo;
    3. private AppCompatTextView tvPermissionShow;
    4. //图标选择
    5. ivRegisterPermissionLogo = baseFindView(R.id.iv_register_permission_logo);
    6. tvPermissionShow = baseFindView(R.id.tv_permission_show);
    7. tvPermissionShow.setText(R.string.add_permission_logo);

            (2)请求读写权限,授权再次点击+号打开相册

    1. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    1. //SD存储权限组
    2. private final String[] PERMISSIONS = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    3. //从相册中选择照片Activity的请求码
    4. public static final int CHOOSE_PHOTO = 2;
    5. //回调选中图片到真实路径
    6. private String logoPath = "";
    7. // 多个权限请求Code
    8. private final int REQUEST_CODE_PERMISSIONS = 3;
    1. //图标选择单击事件,触发时获取权限
    2. ivRegisterPermissionLogo.setOnClickListener(v -> requestMorePermissions());
    1. /**
    2. * 自定义申请多个权限
    3. */
    4. private void requestMorePermissions() {
    5. PermissionUtils.checkMorePermissions(fragmentContext, PERMISSIONS, new PermissionUtils.PermissionCheckCallBack() {
    6. @Override
    7. public void onHasPermission() {
    8. // 已授予权限,打开相册获取图片真实路径
    9. Log.i(TAG, "已授予权限");
    10. choosePermissionLogo();
    11. }
    12. @Override
    13. public void onUserHasAlreadyTurnedDown(String... permission) {
    14. // 上一次申请权限被拒绝,可用于向用户说明权限原因,然后调用权限申请方法
    15. Log.i(TAG, "上一次申请权限被拒绝");
    16. showExplainDialog((dialog, which) -> PermissionUtils.requestMorePermissions(fragmentContext, PERMISSIONS, REQUEST_CODE_PERMISSIONS));
    17. }
    18. @Override
    19. public void onUserHasAlreadyTurnedDownAndDonAsk(String... permission) {
    20. // 第一次申请权限或被禁止申请权限,建议直接调用申请权限方法。
    21. Log.i(TAG, "第一次申请权限或被禁止申请权限");
    22. PermissionUtils.requestMorePermissions(fragmentContext, PERMISSIONS, REQUEST_CODE_PERMISSIONS);
    23. }
    24. });
    25. }
    26. /**
    27. * 解释权限的dialog
    28. */
    29. private void showExplainDialog(DialogInterface.OnClickListener onClickListener) {
    30. new AlertDialog.Builder(fragmentContext)
    31. .setTitle("申请内存读写权限")
    32. .setMessage("用于打开相册,读取图片路径")
    33. .setPositiveButton("确定", onClickListener)
    34. .show();
    35. }
    36. /**
    37. * 打开相册选择权限图标
    38. */
    39. private void choosePermissionLogo() {
    40. //如果重复选择的话,先清空,等新图片路径来重新赋值,如果需要多张路的话,需要使用List来存储多张图片到真实路径
    41. logoPath = "";
    42. Intent pickIntent = new Intent(Intent.ACTION_PICK, null);
    43. // 如果限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"
    44. pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
    45. startActivityForResult(pickIntent, CHOOSE_PHOTO);
    46. }
    47. /**
    48. * 回调申请的权限组
    49. */
    50. @Override
    51. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    52. if (requestCode == REQUEST_CODE_PERMISSIONS) {
    53. PermissionUtils.onRequestMorePermissionsResult(fragmentContext, PERMISSIONS, new PermissionUtils.PermissionCheckCallBack() {
    54. @Override
    55. public void onHasPermission() {
    56. // 权限已被授予
    57. choosePermissionLogo();
    58. }
    59. @Override
    60. public void onUserHasAlreadyTurnedDown(String... permission) {
    61. // 拒绝权限
    62. Toast.makeText(fragmentContext, "我们需要" + Arrays.toString(permission) + "权限", Toast.LENGTH_SHORT).show();
    63. }
    64. @Override
    65. public void onUserHasAlreadyTurnedDownAndDonAsk(String... permission) {
    66. //已禁止再次询问权限
    67. Toast.makeText(fragmentContext, "我们需要" + Arrays.toString(permission) + "权限", Toast.LENGTH_SHORT).show();
    68. showToAppSettingDialog();
    69. }
    70. });
    71. }
    72. }

            说明:权限请求完整工具类,文末贴出来。

             (3)相册选择回调图片Uri

    1. //从相册中选择照片Activity的请求码
    2. public static final int CHOOSE_PHOTO = 2;
    3. //回调选中图片到真实路径
    4. private String logoPath = "";
    5. /**
    6. * Android 4.4以上打开相册获取图片真实路径
    7. */
    8. @TargetApi(19)
    9. private String handleImageOnKitKat(Intent data) {
    10. String imagePath = null;
    11. Uri uri = data.getData();
    12. Log.i(TAG, "获取的uri=" + uri);
    13. if (DocumentsContract.isDocumentUri(fragmentContext, uri)) {
    14. //如果是document类型的Uri ,则通过document_id来处理
    15. String docId = DocumentsContract.getDocumentId(uri);
    16. if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
    17. String id = docId.split(":")[1];//解析出数据格式的ID
    18. String selection = MediaStore.Images.Media._ID + "=" + id;
    19. imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
    20. Log.i(TAG, "类型=media.documents");
    21. } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
    22. Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(docId));
    23. imagePath = getImagePath(contentUri, null);
    24. Log.i(TAG, "类型=downloads.documents");
    25. }
    26. } else if ("content".equalsIgnoreCase(uri.getScheme())) {
    27. //如果是普通类型的Uri,则使用普通的方式来处理
    28. imagePath = getImagePath(uri, null);
    29. //imagePath = getRealPathFromURI(uri);
    30. Log.i(TAG, "类型=content");
    31. } else if ("file".equalsIgnoreCase(uri.getScheme())) {
    32. //如果是file类型的uri,直接获取图片路径就可以了
    33. imagePath = uri.getPath();
    34. Log.i(TAG, "类型=file");
    35. }
    36. Log.i(TAG, "图片真实路径=" + imagePath);
    37. return imagePath;
    38. }
    39. /**
    40. * Android4.4以下打开相册获取图片真实路径
    41. */
    42. private String handleImageBeforeKitKat(Intent data) {
    43. Uri uri = data.getData();
    44. String imagePath = getImagePath(uri, null);
    45. Log.i(TAG, "图片真实路径=" + imagePath);
    46. return imagePath;
    47. }
    48. /**
    49. * 相册选择回调图片Uri
    50. */
    51. @SuppressLint({"ObsoleteSdkInt", "SetTextI18n"})
    52. @Override
    53. public void onActivityResult(int requestCode, int resultCode, Intent data) {
    54. // TODO: 从相册获取
    55. if (requestCode == CHOOSE_PHOTO) {
    56. if (resultCode == RESULT_OK) {
    57. if (Build.VERSION.SDK_INT >= 19) {
    58. logoPath = handleImageOnKitKat(data);
    59. } else {
    60. logoPath = handleImageBeforeKitKat(data);
    61. }
    62. }
    63. }
    64. //必须先进行上面两个handleImage方法去解析Uri,将类型转为真实路径的String路径返回给logoPath,然后进行下面的判断操作业务
    65. if (TextUtils.isEmpty(logoPath) && logoPath.equals("")) {
    66. tvPermissionShow.setText("请您选择一张权限图标");
    67. tvPermissionShow.setTextColor(getResources().getColor(R.color.red)); //字体变红色
    68. } else {
    69. //不为空,将图片路径转为Bitmap后,使用图片控件显示出来
    70. ivRegisterPermissionLogo.setImageBitmap(BitmapFactory.decodeFile(logoPath));
    71. tvPermissionShow.setText("当前图片名:" + logoPath.substring(logoPath.lastIndexOf("/") + 1));
    72. tvPermissionShow.setTextColor(getResources().getColor(R.color.blue));
    73. }
    74. super.onActivityResult(requestCode, resultCode, data);
    75. }

    五、效果测试 

     

     


    六、Android网络请求表单提交图片数据

            (1)HttpUtil请求工具类

    1. public class HttpUtil {
    2. private static final String TAG = "HttpUtil";
    3. //边界参数
    4. private String boundary;
    5. //文件上传接口监听
    6. private requestListener requestListener;
    7. /**
    8. * 图片上传
    9. *
    10. * @param urlStr URL
    11. * @param imgPath 图片路径
    12. */
    13. public void upLoadFile(String urlStr, final String imgPath) {
    14. new Thread(() -> {
    15. Looper.prepare();
    16. //自己生一个boundary
    17. boundary = UUID.randomUUID().toString().replace("-", "");
    18. HttpURLConnection conn = null;
    19. try {
    20. String fileName = "zy" + (int) (Math.random() * 1000000) + ".jpg";
    21. StringBuilder sb = new StringBuilder();
    22. //表单数据
    23. sb.append("--").append(boundary).append("\r\n");
    24. //图标
    25. sb.append("Content-Disposition: form-data; name=imgFile" + "; filename=").append(fileName).append("\r\n");
    26. //传图路径创建文件对象
    27. File file = new File(imgPath);
    28. //获取文件名
    29. String filename = file.getName();
    30. //截取文件后缀,对应设置mime-type支持类型
    31. String contentType = "";
    32. if (filename.endsWith(".png")) {
    33. contentType = "image/png";
    34. }
    35. if (filename.endsWith(".jpg")) {
    36. contentType = "image/jpg";
    37. }
    38. if (filename.endsWith(".gif")) {
    39. contentType = "image/gif";
    40. }
    41. if (filename.endsWith(".bmp")) {
    42. contentType = "image/bmp";
    43. }
    44. if (contentType.equals("")) {
    45. contentType = "application/octet-stream";
    46. }
    47. sb.append("Content-Type:").append(contentType).append("\r\n");
    48. sb.append("\r\n");//此时的sd———>Content-Disposition: form-data; name=imgFile; filename=zy+随机数.jpg
    49. //字节流处理
    50. byte[] headerInfo = sb.toString().getBytes(StandardCharsets.UTF_8);
    51. byte[] endInfo = ("\r\n--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8);
    52. conn = (HttpURLConnection) new URL(urlStr).openConnection();
    53. conn.setDoInput(true);
    54. conn.setDoOutput(true);
    55. //文件上传必须为POST
    56. conn.setRequestMethod("POST");
    57. //注意这里的格式,模仿表单,出现一点点错误都会导致上传不成功
    58. conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    59. //数据长度
    60. conn.setRequestProperty("Content-Length", String.valueOf(file.length() + headerInfo.length + endInfo.length));
    61. //通过conn拿到服务器的字节输出流
    62. OutputStream out = conn.getOutputStream();
    63. //需要上传的文件封装成字节输入流
    64. InputStream in = new FileInputStream(file);
    65. out.write(headerInfo);
    66. byte[] buf = new byte[1024];
    67. int len;
    68. while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
    69. out.write(endInfo);
    70. in.close();
    71. out.close();
    72. if (conn.getResponseCode() == 200) {
    73. requestListener.success(new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine());
    74. }
    75. } catch (Exception e) {
    76. e.printStackTrace();
    77. if (Objects.requireNonNull(e.getMessage()).contains("to connect to")) {
    78. Log.i(TAG, "服务器访问失败,请联系管理员修复");
    79. if (requestListener != null) {
    80. requestListener.fail("{ \"code\": 502,\n \"msg\": \"服务器访问失败,请联系管理员处理\",\n \"data\":{}}");
    81. }
    82. } else if (Objects.requireNonNull(e.getMessage()).contains("Unable to resolve host")) {
    83. Log.i(TAG, "服务器访问失败,请检查网络是否可用");
    84. if (requestListener != null) {
    85. requestListener.fail("{ \"code\": 503,\n \"msg\": \"请求失败,请检查网络是否可用\",\n \"data\":{}}");
    86. }
    87. } else {
    88. Log.i(TAG, "服务器访问失败,未知错误:" + e.getMessage());
    89. if (requestListener != null) {
    90. requestListener.fail("{ \"code\": 504,\n \"msg\": \"服务器访问失败,错误原因未知,请联系管理员处理\",\n \"data\":{}}");
    91. }
    92. }
    93. } finally {
    94. if (conn != null) {
    95. conn.disconnect();
    96. }
    97. }
    98. Looper.loop();
    99. }).start();
    100. }
    101. /**
    102. * 上传监听接口
    103. *
    104. * @param requestListener 上传结果回调
    105. */
    106. public void setRequestListener(requestListener requestListener) {
    107. this.requestListener = requestListener;
    108. }
    109. /**
    110. * 定义外部请求结果回调接口
    111. */
    112. public interface requestListener {
    113. /**
    114. * 成功回调
    115. *
    116. * @param resultJson 成功JSON数据
    117. */
    118. void success(String resultJson) throws JSONException;
    119. /**
    120. * 失败回调
    121. *
    122. * @param resultJson 失败JSON数据
    123. */
    124. void fail(String resultJson);
    125. }
    126. }

            (2)开始调用后端接口,上传图片

    1. HttpUtil uploadFileUtil = new HttpUtil();
    2. uploadFileUtil.upLoadFile(Constant.ADD_PERMISSION_INFO);
    3. uploadFileUtil.setRequestListener(new HttpUtil.requestListener() {
    4. @Override
    5. public void success(String resultJson) {
    6. Log.i("zyLogin", "成功: " + resultJson);
    7. }
    8. @Override
    9. public void fail(String resultJson) {
    10. Log.i("zyLogin", "失败: " + resultJson);
    11. }
    12. });

            (3)执行成功 

            说明:执行成功后,后端业务代码处理后,会将图片信息存入到云服务器Linux的硬盘内存上,并将Servlet映射路径后外网可访问的URL地址存进数据库,当Android使用Glide就能直接加载图片信息啦。 


    七、权限工具类

    1. public class PermissionUtils {
    2. /**
    3. * 检测权限
    4. *
    5. * @return true:已授权; false:未授权;
    6. */
    7. public static boolean checkPermission(Context context, String permission) {
    8. if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED)
    9. return true;
    10. else
    11. return false;
    12. }
    13. /**
    14. * 检测多个权限
    15. *
    16. * @return 未授权的权限
    17. */
    18. public static List checkMorePermissions(Context context, String[] permissions) {
    19. List permissionList = new ArrayList<>();
    20. for (int i = 0; i < permissions.length; i++) {
    21. if (!checkPermission(context, permissions[i]))
    22. permissionList.add(permissions[i]);
    23. }
    24. return permissionList;
    25. }
    26. /**
    27. * 请求权限
    28. */
    29. public static void requestPermission(Context context, String permission, int requestCode) {
    30. ActivityCompat.requestPermissions((Activity) context, new String[]{permission}, requestCode);
    31. }
    32. /**
    33. * 请求多个权限
    34. */
    35. public static void requestMorePermissions(Context context, List permissionList, int requestCode) {
    36. String[] permissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
    37. requestMorePermissions(context, permissions, requestCode);
    38. }
    39. /**
    40. * 请求多个权限
    41. */
    42. public static void requestMorePermissions(Context context, String[] permissions, int requestCode) {
    43. ActivityCompat.requestPermissions((Activity) context, permissions, requestCode);
    44. }
    45. /**
    46. * 判断是否已拒绝过权限
    47. * 如果应用之前请求过此权限但用户拒绝,此方法将返回 true;
    48. * 如果应用第一次请求权限或 用户在过去拒绝了权限请求,
    49. * 并在权限请求系统对话框中选择了 Don't ask again 选项,此方法将返回 false。
    50. */
    51. public static boolean judgePermission(Context context, String permission) {
    52. return ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission);
    53. }
    54. /**
    55. * 检测权限并请求权限:如果没有权限,则请求权限
    56. */
    57. public static void checkAndRequestPermission(Context context, String permission, int requestCode) {
    58. if (!checkPermission(context, permission)) {
    59. requestPermission(context, permission, requestCode);
    60. }
    61. }
    62. /**
    63. * 检测并请求多个权限
    64. */
    65. public static void checkAndRequestMorePermissions(Context context, String[] permissions, int requestCode) {
    66. List permissionList = checkMorePermissions(context, permissions);
    67. requestMorePermissions(context, permissionList, requestCode);
    68. }
    69. /**
    70. * 检测权限
    71. * 具体实现由回调接口决定
    72. */
    73. public static void checkPermission(Context context, String permission, PermissionCheckCallBack callBack) {
    74. if (checkPermission(context, permission)) { // 用户已授予权限
    75. callBack.onHasPermission();
    76. } else {
    77. if (judgePermission(context, permission)) // 用户之前已拒绝过权限申请
    78. callBack.onUserHasAlreadyTurnedDown(permission);
    79. else // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
    80. callBack.onUserHasAlreadyTurnedDownAndDonAsk(permission);
    81. }
    82. }
    83. /**
    84. * 检测多个权限
    85. * 具体实现由回调接口决定
    86. */
    87. public static void checkMorePermissions(Context context, String[] permissions, PermissionCheckCallBack callBack) {
    88. List permissionList = checkMorePermissions(context, permissions);
    89. if (permissionList.size() == 0) { // 用户已授予权限
    90. callBack.onHasPermission();
    91. } else {
    92. boolean isFirst = true;
    93. for (int i = 0; i < permissionList.size(); i++) {
    94. String permission = permissionList.get(i);
    95. if (judgePermission(context, permission)) {
    96. isFirst = false;
    97. break;
    98. }
    99. }
    100. String[] unauthorizedMorePermissions = (String[]) permissionList.toArray(new String[permissionList.size()]);
    101. if (isFirst)// 用户之前已拒绝过权限申请
    102. callBack.onUserHasAlreadyTurnedDownAndDonAsk(unauthorizedMorePermissions);
    103. else // 用户之前已拒绝并勾选了不在询问、用户第一次申请权限。
    104. callBack.onUserHasAlreadyTurnedDown(unauthorizedMorePermissions);
    105. }
    106. }
    107. /**
    108. * 检测并申请权限
    109. */
    110. public static void checkAndRequestPermission(Context context, String permission, int requestCode, PermissionRequestSuccessCallBack callBack) {
    111. if (checkPermission(context, permission)) {// 用户已授予权限
    112. callBack.onHasPermission();
    113. } else {
    114. requestPermission(context, permission, requestCode);
    115. }
    116. }
    117. /**
    118. * 检测并申请多个权限
    119. */
    120. public static void checkAndRequestMorePermissions(Context context, String[] permissions, int requestCode, PermissionRequestSuccessCallBack callBack) {
    121. List permissionList = checkMorePermissions(context, permissions);
    122. if (permissionList.size() == 0) { // 用户已授予权限
    123. callBack.onHasPermission();
    124. } else {
    125. requestMorePermissions(context, permissionList, requestCode);
    126. }
    127. }
    128. /**
    129. * 判断权限是否申请成功
    130. */
    131. public static boolean isPermissionRequestSuccess(int[] grantResults) {
    132. if (grantResults.length > 0
    133. && grantResults[0] == PackageManager.PERMISSION_GRANTED)
    134. return true;
    135. else
    136. return false;
    137. }
    138. /**
    139. * 用户申请权限返回
    140. */
    141. public static void onRequestPermissionResult(Context context, String permission, int[] grantResults, PermissionCheckCallBack callback) {
    142. if (PermissionUtils.isPermissionRequestSuccess(grantResults)) {
    143. callback.onHasPermission();
    144. } else {
    145. if (PermissionUtils.judgePermission(context, permission)) {
    146. callback.onUserHasAlreadyTurnedDown(permission);
    147. } else {
    148. callback.onUserHasAlreadyTurnedDownAndDonAsk(permission);
    149. }
    150. }
    151. }
    152. /**
    153. * 用户申请多个权限返回
    154. */
    155. public static void onRequestMorePermissionsResult(Context context, String[] permissions, PermissionCheckCallBack callback) {
    156. boolean isBannedPermission = false;
    157. List permissionList = checkMorePermissions(context, permissions);
    158. if (permissionList.size() == 0)
    159. callback.onHasPermission();
    160. else {
    161. for (int i = 0; i < permissionList.size(); i++) {
    162. if (!judgePermission(context, permissionList.get(i))) {
    163. isBannedPermission = true;
    164. break;
    165. }
    166. }
    167. // 已禁止再次询问权限
    168. if (isBannedPermission)
    169. callback.onUserHasAlreadyTurnedDownAndDonAsk(permissions);
    170. else // 拒绝权限
    171. callback.onUserHasAlreadyTurnedDown(permissions);
    172. }
    173. }
    174. /**
    175. * 跳转到权限设置界面
    176. */
    177. public static void toAppSetting(Context context) {
    178. Intent intent = new Intent();
    179. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    180. if (Build.VERSION.SDK_INT >= 9) {
    181. intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
    182. intent.setData(Uri.fromParts("package", context.getPackageName(), null));
    183. } else if (Build.VERSION.SDK_INT <= 8) {
    184. intent.setAction(Intent.ACTION_VIEW);
    185. intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
    186. intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
    187. }
    188. context.startActivity(intent);
    189. }
    190. public interface PermissionRequestSuccessCallBack {
    191. /**
    192. * 用户已授予权限
    193. */
    194. void onHasPermission();
    195. }
    196. public interface PermissionCheckCallBack {
    197. /**
    198. * 用户已授予权限
    199. */
    200. void onHasPermission();
    201. /**
    202. * 用户已拒绝过权限
    203. *
    204. * @param permission:被拒绝的权限
    205. */
    206. void onUserHasAlreadyTurnedDown(String... permission);
    207. /**
    208. * 用户已拒绝过并且已勾选不再询问选项、用户第一次申请权限;
    209. *
    210. * @param permission:被拒绝的权限
    211. */
    212. void onUserHasAlreadyTurnedDownAndDonAsk(String... permission);
    213. }
    214. }

    八、总结

    仅自己学习记录,如有错误,敬请谅解~,谢谢~~

  • 相关阅读:
    数据结构 编程1年新手视角的平衡二叉树AVL从C与C++实现②
    centos pip失效
    常见加密算法C#实现(一)
    新手炒外汇,如何防止炒外汇被坑?
    Vue 入门案例剖析
    无锁队列Disruptor使用笔记
    爆肝整理,最全单元测试-测试用例总结(全覆盖)及拿即用...
    Python爬虫之Urllib(内置库)
    删除数据后无法恢复的固态盘
    书店漫游记录
  • 原文地址:https://blog.csdn.net/qq_39038178/article/details/126781853