Android App-targetSDKVersion28升级为30

Android App-targetSDKVersion28升级为30

码农世界 2024-06-18 后端 100 次浏览 0个评论

为什么要修改targetSDKVersion?

1、应用开发平台要求(小米)

2、更好的兼容新版本的手机

有targetSDKVersion的位置:

  • App的targetSDKVersion
  • Module中的targetSDKVersion
  • 引入的第三方库中有targetSDKVersion

    修改了App和Module中的targetSDKVersion。

    存储权限和存储位置问题

    修改原因:

    Android10(targetSdkVersion29)以后加入了分区存储,针对App设置了外置私有存储空间,卸载App时会被删除,一定程度上解决了卸载App后外置内存仍占用问题。

    Android10在获取存储权限上和之前版本有区别。

    修改前:

    • targetSDKVersion28
    • 使用EasyPermission框架获取权限。(长时间不更新且不支持新版本Android)
    • 视频、音频、文件存储在外置存储卡【Environment.getExternalStorageDirectory()】中。

      修改后:

      • targetSDKVersion30(Android 11)
      • 使用Permission替换EasyPermission获取权限
      • 视频、音频、文件存储存储在私有外置存储中【context.getExternalFilesDir()】。

        修改内容:

        • 兼容Android不同版本获取权限。
        • App新版本要处理老版本存储在外置存储卡中的内容。

          知识点:

          使用创建、读写文件测试对Environment.getExternalStorageDirectory()和context.getExternalFilesDir()目录的使用。

          Environment.getExternalStorageDirectory()

          • Android13:同Android11
          • Android11:
            • 动态获取Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE权限后创建读写文件时显示permission denied。
            • 动态获取Manifest.permission.MANAGE_EXTERNAL_STORAGE权限后可以创建并读写文件,获取权限方式是通过Intent intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)跳转至设置页面,用户自行打开允许访问所有文件权限看后才可创建读写文件。
            • Android10:同Android11
            • Android9 动态获取Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE权限后可以创建并读写文件。
            • Android6:动态获取Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE权限后可以创建并读写文件。
            • Android5:不用获取权限可以创建并读写文件。

              context.getExternalFilesDir();

              • Android13:不用获取权限可以创建并读写文件。
              • Android11:不用获取权限可以创建并读写文件。
              • Android10:不用获取权限可以创建并读写文件。
              • Android9:不用获取权限可以创建并读写文件。
              • Android6:不用获取权限可以创建并读写文件。
              • Android5:不用获取权限可以创建并读写文件。

                修改方案:

                • 修改视频、音频和文件存储位置为外置私有存储空间且不需要获取权限。
                • 为兼容App旧版本存储在外置存储卡中的视频、音频和文件,在读取外置存储卡中的视频、音频和文件时需获取存储权限。

                  读取相册照片和视频

                  修改原因:

                  • Android10之后读取相册的权限不同且方法也不同。

                    修改前:

                    • 使用RxGalleryFinal框架(长时间不更新且不适配新版本Android)

                      修改后:

                      • 使用PictureSelector框架(适配Android10以后版本-内置有获取权限功能)

                        保存图片至相册

                        修改原因:

                        • Android10 添加至相册方式和位置不同。

                          修改后:

                          • 兼容不同Android版本

                            处理方法:

                            • Android9及之前版本,将图片保存至外置存储卡,然后通知将其添加到相册数据库,并刷新即可(需存储权限)。
                            • Android10及以后版本,不能将图片放置在私有外置存储空间(ContentResolver不支持,会提示错误),将图片放在公共媒体存放位置,然后刷新,使用ContentResolver实现。

                              实现代码如下:

                              package com.ypkj.kfpt.http;
                              import android.content.ContentResolver;
                              import android.content.ContentValues;
                              import android.content.Context;
                              import android.content.Intent;
                              import android.graphics.Bitmap;
                              import android.graphics.BitmapFactory;
                              import android.net.Uri;
                              import android.os.Build;
                              import android.os.Environment;
                              import android.os.Handler;
                              import android.os.Message;
                              import android.provider.MediaStore;
                              import android.text.TextUtils;
                              import android.text.format.DateUtils;
                              import android.util.Log;
                              import android.widget.Toast;
                              import androidx.fragment.app.FragmentActivity;
                              import com.learn.base.permission.PermissionsUtil;
                              import com.ypkj.kfpt.R;
                              import java.io.File;
                              import java.io.FileOutputStream;
                              import java.io.IOException;
                              import java.io.InputStream;
                              import java.io.OutputStream;
                              import java.net.URL;
                              import java.util.UUID;
                              /**
                               * 下载图片至相册的工具类
                               */
                              public class DonwloadSaveImg {
                                  private static Context context;
                                  private static String filePath;
                                  private static Bitmap mBitmap;
                                  private static String mSaveMessage = "失败";
                                  private final static String TAG = "PictureActivity";
                                  public static void donwloadImg( Context contexts, String filePaths) {
                                      context = contexts;
                                      filePath = filePaths;
                                      PermissionsUtil.getInstance().requestStoragePerm((FragmentActivity) contexts, "", new PermissionsUtil.BaseRequestCallback() {
                                          @Override
                                          public void onCallBack() {
                                              new Thread(saveFileRunnable).start();
                                          }
                                      });
                                  }
                                  private static Runnable saveFileRunnable = new Runnable() {
                                      @Override
                                      public void run() {
                                          try {
                                              if (!TextUtils.isEmpty(filePath)) { //网络图片
                                                  // 对资源链接
                                                  URL url = new URL(filePath);
                                                  //打开输入流
                                                  InputStream inputStream = url.openStream();
                                                  //对网上资源进行下载转换位图图片
                                                  mBitmap = BitmapFactory.decodeStream(inputStream);
                                                  inputStream.close();
                                              }
                                              saveBitmap(context, mBitmap);
                                              mSaveMessage = "图片保存成功!";
                                          } catch (IOException e) {
                                              mSaveMessage = "图片保存失败!";
                                              e.printStackTrace();
                                          } catch (Exception e) {
                                              e.printStackTrace();
                                          }
                                          messageHandler.sendMessage(messageHandler.obtainMessage());
                                      }
                                  };
                                  private static Handler messageHandler = new Handler() {
                                      @Override
                                      public void handleMessage(Message msg) {
                                          Log.d(TAG, mSaveMessage);
                                          Toast.makeText(context, mSaveMessage, Toast.LENGTH_SHORT).show();
                                      }
                                  };
                              
                                  // 保存bitmap到相册,并兼容AndroidQ
                                  public static boolean saveBitmap(Context context, Bitmap bitmap) {
                                      if (bitmap == null) {
                                          return false;
                                      }
                                      boolean isSaveSuccess;
                                      if (Build.VERSION.SDK_INT < 29) {
                                          isSaveSuccess = saveImageToGallery(context, bitmap);
                                      } else {
                                          isSaveSuccess = saveImageToGalleryQ(context, bitmap);
                                      }
                                      return isSaveSuccess;
                                  }
                                  /**
                                   * android 10 以下版本
                                   */
                                  private static boolean saveImageToGallery(Context context, Bitmap image) {
                                      // 首先保存图片
                                      String storePath = getBitmapFileDir();
                                      File appDir = new File(storePath);
                                      if (!appDir.exists()) {
                                          appDir.mkdir();
                                      }
                                      String fileName = UUID.randomUUID().toString() + ".png";
                                      File file = new File(appDir, fileName);
                                      try {
                                          FileOutputStream fos = new FileOutputStream(file);
                                          // 通过io流的方式来压缩保存图片
                                          boolean isSuccess = image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                                          fos.flush();
                                          fos.close();
                                          // 保存图片后发送广播通知更新数据库
                                          Uri uri = Uri.fromFile(file);
                                          context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
                                          if (isSuccess) {
                                              return true;
                                          } else {
                                              return false;
                                          }
                                      } catch (IOException e) {
                                          e.printStackTrace();
                                      }
                                      return false;
                                  }
                                  /**
                                   * android 10 以上版本
                                   */
                                  private static boolean saveImageToGalleryQ(Context context, Bitmap image) {
                                      long mImageTime = System.currentTimeMillis();
                                      String mImageFileName = UUID.randomUUID().toString() + ".png";
                                      final ContentValues values = new ContentValues();
                                      values.put(MediaStore.MediaColumns.RELATIVE_PATH, getBitmapFileDir());
                                      values.put(MediaStore.MediaColumns.DISPLAY_NAME, mImageFileName);
                                      values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
                                      values.put(MediaStore.MediaColumns.DATE_ADDED, mImageTime / 1000);
                                      values.put(MediaStore.MediaColumns.DATE_MODIFIED, mImageTime / 1000);
                                      values.put(MediaStore.MediaColumns.DATE_EXPIRES, (mImageTime + DateUtils.DAY_IN_MILLIS) / 1000);
                                      values.put(MediaStore.MediaColumns.IS_PENDING, 1);
                                      ContentResolver resolver = context.getContentResolver();
                                      final Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                                      try {
                                          OutputStream out = resolver.openOutputStream(uri);
                                          if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                                              return false;
                                          }
                                          values.clear();
                                          values.put(MediaStore.MediaColumns.IS_PENDING, 0);
                                          values.putNull(MediaStore.MediaColumns.DATE_EXPIRES);
                                          resolver.update(uri, values, null, null);
                                      } catch (Exception e) {
                                          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                                              resolver.delete(uri, null);
                                          }
                                          return false;
                                      }
                                      return true;
                                  }
                                  public static String getBitmapFileDir() {
                                      String BITMAP_FILE_DIRECTORY = context.getString(R.string.appname);
                                      if (Build.VERSION.SDK_INT < 29) {
                                          // android 10 以下版本
                                          return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + BITMAP_FILE_DIRECTORY;
                                      } else {
                                          return Environment.DIRECTORY_PICTURES + File.separator + BITMAP_FILE_DIRECTORY;
                                      }
                                  }
                              }
                              

                              参考文档:

                              • 一篇文章搞定《Android权限问题(全版本)》https://blog.csdn.net/weixin_45112340/article/details/128905213
                              • [ ]应用TargetSdkVersion 30升级适配指南 https://dev.mi.com/distribute/doc/details?pId=1738#_2

转载请注明来自码农世界,本文标题:《Android App-targetSDKVersion28升级为30》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,100人围观)参与讨论

还没有评论,来说两句吧...

Top