返回

Android TargetSdk升级之路:从22到26的坑与对策

Android

升级 Android TargetSdk:从 22 到 26 的挑战和解决方案

简介

随着 Android 系统的不懈更新,开发者们面临着不断升级 TargetSdk 的挑战。从 TargetSdk 22 到 TargetSdk 26,这一过程中见证了诸多变化,既有新功能的引入,也伴随着一些兼容性问题的出现。为了帮助大家顺利应对升级过程,本文将深入探讨 TargetSdk 从 22 升级到 26 期间遇到的主要问题及相应的解决方案,为广大开发者提供有益的参考。

一、权限问题

TargetSdk 升级后,权限管理机制发生了重大的革新。在 TargetSdk 22 及以下版本中,应用程序在安装时便能获取清单文件中声明的所有权限。而到了 TargetSdk 23 及以上版本,权限申请机制才正式登场,应用程序只有在运行时才会动态请求权限,用户也有权随时授予或撤销权限。

1. 权限申请时机

对于 TargetSdk 23 及以上版本的应用程序而言,务必在使用需要动态申请的权限之前进行权限申请,否则应用程序将抛出 SecurityException 异常。

2. 权限申请方式

权限申请有两种方式可选:

  • ActivityCompat.requestPermissions() 方法: 适用于同时申请多个权限。
  • Context.requestPermissions() 方法: 适用于申请单个权限。

3. 权限申请注意事项

在申请权限时,需要注意以下事项:

  • 申请权限必须在主线程进行。
  • 申请权限时,必须向用户解释为什么需要该权限,即提供权限申请的 rationale。
  • 用户有权随时授予或撤销权限,因此应用程序需要做好权限被撤销后的处理逻辑。

二、文件共享问题

TargetSdk 24 及以上版本对文件共享机制进行了调整。传统的通过 FileProvider 共享文件的方式不再适用,取而代之的是采用 ContentProvider 共享机制。

1. 使用 ContentProvider 共享文件

ContentProvider 是 Android 系统中用于数据共享的一种机制。要使用 ContentProvider 共享文件,需要进行以下步骤:

  • 创建一个 ContentProvider 子类。
  • 在清单文件中注册 ContentProvider。
  • 在 ContentProvider 中实现文件共享的逻辑。

2. 获取文件 Uri

要获取要共享文件的 Uri,可以使用以下方法:

Uri fileUri = FileProvider.getUriForFile(context, "com.example.myapp.fileprovider", file);

3. 共享文件

使用 Uri 获取文件后,即可通过 Intent 进行文件共享:

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(shareIntent, "分享"));

三、相机问题

在 TargetSdk 23 及以上版本中,对相机权限的管理也发生了变化。在 TargetSdk 22 及以下版本中,应用程序在安装时便能获取相机权限。而到了 TargetSdk 23 及以上版本,应用程序在运行时才需要动态请求相机权限。

1. 相机权限申请

要申请相机权限,可以使用以下方法:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_CAMERA);

2. 相机权限申请注意事项

与其他权限申请类似,申请相机权限也需要注意:

  • 申请权限必须在主线程进行。
  • 申请权限时,必须提供权限申请的 rationale。
  • 用户有权随时授予或撤销权限。

四、存储问题

TargetSdk 26 及以上版本对外部存储的访问权限管理也进行了修改。在 TargetSdk 25 及以下版本中,应用程序在安装时便能获取外部存储的读取和写入权限。而到了 TargetSdk 26 及以上版本,应用程序在运行时需要动态请求外部存储的读取和写入权限。

1. 外部存储权限申请

要申请外部存储权限,可以使用以下方法:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_STORAGE);

2. 外部存储权限申请注意事项

与其他权限申请类似,申请外部存储权限也需要注意:

  • 申请权限必须在主线程进行。
  • 申请权限时,必须提供权限申请的 rationale。
  • 用户有权随时授予或撤销权限。

五、通知问题

TargetSdk 26 及以上版本对通知的管理机制也进行了调整。在 TargetSdk 25 及以下版本中,应用程序可以自由创建和发送通知,不受任何限制。而到了 TargetSdk 26 及以上版本,应用程序在创建和发送通知之前必须先注册通知渠道。

1. 注册通知渠道

要注册通知渠道,可以使用以下方法:

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);

2. 发送通知

注册通知渠道后,即可通过 NotificationCompat.Builder 创建和发送通知:

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "channel_id")
        .setContentTitle("通知标题")
        .setContentText("通知内容")
        .setSmallIcon(R.drawable.ic_notification);
Notification notification = notificationBuilder.build();
notificationManager.notify(NOTIFICATION_ID, notification);

六、前台服务问题

TargetSdk 26 及以上版本对前台服务的使用也进行了限制。在 TargetSdk 25 及以下版本中,应用程序可以自由创建和使用前台服务,不受任何限制。而到了 TargetSdk 26 及以上版本,应用程序在创建前台服务时必须显式地显示通知,否则前台服务将被系统终止。

1. 显示前台服务通知

要显示前台服务通知,可以使用以下方法:

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "channel_id")
        .setContentTitle("前台服务通知标题")
        .setContentText("前台服务通知内容")
        .setSmallIcon(R.drawable.ic_notification);
Notification notification = notificationBuilder.build();
startForeground(NOTIFICATION_ID, notification);

2. 前台服务注意事项

使用前台服务时,需要注意以下事项:

  • 前台服务必须始终显示通知。
  • 前台服务在后台运行时,可能会消耗更多的电量。

总结

从 Android TargetSdk 22 升级到 TargetSdk 26 的过程中,我们需要关注权限、文件共享、相机、存储、通知和前台服务等方面带来的变化,并采取相应的对策。通过了解这些变化,开发者可以顺利地将应用程序升级到最新的 TargetSdk,为用户提供更好的使用体验。

常见问题解答

1. TargetSdk 升级后,应用程序可能会出现哪些兼容性问题?

TargetSdk 升级后,应用程序可能遇到的兼容性问题包括权限申请、文件共享、相机访问、外部存储访问、通知管理和前台服务使用等方面。

2. 如何解决权限申请问题?

在 TargetSdk 23 及以上版本中,需要在运行时动态申请权限。开发者可以使用 ActivityCompat.requestPermissions() 或 Context.requestPermissions() 方法,并在申请权限时向用户提供权限申请的 rationale。

3. 如何解决文件共享问题?

在 TargetSdk 24 及以上版本中,使用 ContentProvider 共享文件取代了传统的 FileProvider 共享方式。开发者需要创建 ContentProvider 子类,在清单文件中注册 ContentProvider,并实现文件共享逻辑。

4. 如何解决相机访问问题?

在 TargetSdk 23 及以上版本中,需要在运行时动态申请相机权限。开发者可以使用 ActivityCompat.requestPermissions() 方法申请权限,并在申请权限时向用户提供权限申请的 rationale。

5. 如何解决外部存储访问问题?

在 TargetSdk 26 及以上版本中,需要在运行时动态申请外部存储访问权限。开发者可以使用 ActivityCompat.requestPermissions() 方法申请权限,并在申请权限时向用户提供权限申请的 rationale。