Fire平板电脑上的Fire OS 7
Fire OS 7基于Android 9 Pie。遵从以下指南,确保应用与Fire OS 7兼容。
- 运行Fire OS 7和之前Fire OS版本的设备
- Fire OS 7中的Android更改
- Fire OS 7与Android 9对等
- 让应用以Fire OS 7设备为目标
- 在Fire OS 7设备上测试应用的兼容性
- minSdkVersion和targetSdkVersion的设置
- 了解minSdkVersion如何影响支持的设备
- Fire平板电脑自动备份
- Fire OS 7中的通知
- Amazon Device Messaging (ADM)兼容性
- 支持
运行Fire OS 7和之前Fire OS版本的设备
Fire OS 7基于Android 9 Pie(API级别28)。Fire OS 7最初于2019年面向部分Fire平板电脑设备发布。
大多数Fire平板电脑设备运行Fire OS 5(Android 5.1,级别22)。Fire 7 (2019)平板电脑设备运行Fire OS 6,该版本基于Android Nougat(Android 7.1.2,级别25)。部分较早版本的Fire平板电脑设备仍然搭载Fire OS 4或更早版本。
有关Fire平板电脑设备和版本的详细列表,请参阅平板电脑设备规格。
Fire OS 7中的Android更改
从Fire OS 6升级到Fire OS 7须通过Oreo(Android 8.0)从Nougat (Android 7.1.2)过渡到Pie (Android 9)。
Android 8.0和Android 9中进行的更改,须相应更改应用中的代码,应用才能在Fire OS 7设备上正常运行。
Android 8.0更改
Android 8.0中的主要更改如下:
-
通知通道: 所有通知(包括推荐和合作伙伴管理的推荐)必须与通道关联。有关通道的信息,请参阅有关通知通道的Android培训。有关示例代码和其他详细信息,请参阅下文的“Fire OS 7中的通知”部分。
-
后台服务: Android 8.0限制后台服务的使用。因此,使用后台服务刷新其推荐的应用均无法刷新FOS 7上的推荐。Android建议使用JobScheduler来解决后台服务的限制。请参阅“后台服务”。
-
本机库: 若本机库包含既可写入又可执行的加载段,则不再加载本机库。
-
权限: 应用需明示请求每个权限,即使在同一个权限组中也是如此。
-
MediaSession事件: 应用须正确使用MediaSession处理音频。请参阅有关查找媒体会话的Android 8.0文档。当Android处理事件时,若前台活动缺乏有效的媒体会话来处理事件,则Android将查找其他媒体会话。另请参阅”Fire TV上多媒体应用的要求“。
可在Android 8.0行为变化中了解大部分更改情况。
Android 9更改
Android 9中的主要更改仅包括下列各项:
- 隐私变更: 应用对Wifi的访问将受到限制。在后台运行时,应用对用户输入和传感器数据的访问权限将受到限制。
可在行为变化:所有应用(Pie)中了解更改情况。
Fire OS 7与Android 9对等
FOS 7中实现的所有功能在Android 9中均能找到。这并不一定意味着Android 9中的所有内容均可在FOS 7中使用,但对于已在FOS 7中实现的功能,与在Android 9中是相同的。FOS 7不支持某些Android 9功能,如分屏、通知点和自适应图标。
另请记住,虽然Fire OS 7与Android 9具有相同功能,但无法在Amazon Fire设备上使用谷歌服务。相反,针对所需的服务(例如:应用内购买),必须使用应用和游戏服务开发工具包。
让应用以Fire OS 7设备为目标
用户可能在Fire OS 5、Fire OS 6或Fire OS 7设备上运行应用。如需最大限度地提高应用与设备上的Fire OS版本的兼容性,建议根据SDK级别确定设备。
在代码中,可检查Build.VERSION.SDK_INT
是否大于等于28
(Android 9 API级别),以将Fire OS 7设备确定为目标设备。
另请参阅Android文档中的支持不同平台版本。
在Fire OS 7设备上测试应用的兼容性
目前,可通过连接到实际设备,测试应用与Fire OS 7的兼容性。
minSdkVersion和targetSdkVersion的设置
将minSdkVersion
设置为适用Fire OS版本所需的最低API级别。
Fire OS版本 | minSdkVersion |
---|---|
Fire OS 5 | 22 |
Fire OS 6 | 25 |
Fire OS 7 | 28 |
将targetSdkVersion
设置为测试应用时所用的最高API级别。
请参阅设备筛选和兼容性,以了解有关最低API级别要求的更多信息。
了解minSdkVersion如何影响支持的设备
在应用清单(或build.gradle
文件)中,minSdkVersion
属性设置了应用正常运行所需的最低SDK级别。(不支持该API级别的设备将不允许在该设备上安装应用 — 这是应用商店设备筛选和兼容性的工作方式。)
Fire OS 5设备基于API级别22 (Lollipop 5.1)。Fire OS 7设备基于API级别28 (Android 9)。将minSdkVersion
设置为22,即表示应用要求设备至少具有API级别22才能正常运行。
将minSdkVersion
设置为22时,还可在具有更高API级别(例如28)的设备中安装您的应用,因为Android级别向后兼容。API级别28通常包含级别1到级别28的所有API(每个版本均添加到上一个版本中)。
但假设你想利用Android 9中的API(API级别28)。若将minSdkVersion
设置为22,则可以在没有API级别28的Fire OS 5设备中安装您的应用。因此,必须以防御性方式进行编程,检查设备级别,若设备不支持该API级别,则回退到替代方案。代码可能如下所示:
targetSdkVersion
if (Build.VERSION.SDK_INT >= 28) {
Log.v(TAG, "Yes, this is an API level 28 or higher device(是,这台设备具备API级别28或更高版本)");
} else {
Log.v(TAG, "No, this is not an API level 28 or higher device(否,这台设备不具备API级别28或更高版本)");
}
该代码检查设备的API级别是否大于或等于28,若是,则运行代码。如果不是,则回退到else
逻辑。
默认情况下,若未指定targetSdkVersion
,将使用与minSdkVersion
相同的值。targetSdkVersion
允许您设置应用测试所依据的最新API级别。基于该值,Android将确保此级别设备的性能正常。
例如,若将targetSdkVersion
设置为23或更高版本(Marshmallow的版本),Android将应用Marshmallow中包含的运行时权限检查功能。但是,如果targetSdkVersion
低于23(在Marshmallow中推出运行时权限检查之前),Android将不在您的应用中应用此行为。
尽管不建议采取这一做法,但如果需要防止较早版本的应用出现在Fire OS 7设备上,可以将maxSdkVersion
设置为Fire OS 5 (22)。
有关更多信息,请参阅以下内容:
Fire平板电脑自动备份
从2023年5月31日开始,亚马逊Fire平板电脑将为选择在平板电脑上进行备份和恢复的用户启用自动备份。如果您的应用以API 23或更高级别为目标平台,并且未在清单中明确禁用自动备份,则您的应用将自动参与。尽管自动备份的默认值为true
,但我们建议在清单中显式设置该属性。
自动备份详情
- 不再需要为键/值备份方法编写自定义备份和恢复逻辑,但该方法仍然受支持。
- 此功能在Fire OS 7及更高版本上可用,适用于以(
targetSdkVersion
) API 23或更高版本为目标的应用。 - 应用数据将免费自动备份到AWS S3。
- 除应用缓存外,会自动备份所有数据文件,包括数据库、共享首选项和应用专用目录中的其他内容,除非另有指定。
- 对于客户而言,每个设备的每个应用限制为25 MB。如果超过限制,将不会备份应用数据,但在限制范围内的旧备份仍将可用于恢复。
- 确保备份的数据不包括任何最终用户的敏感数据,例如,1996年《健康保险携带和责任法案》(HIPAA)定义的“受保护的健康信息”,或联邦贸易委员会《健康泄露通知规则》定义的“PHR可识别健康信息”。出于安全原因,您还应该在备份中排除密码令牌或凭证。
有关更多信息,请参阅Android自动备份功能文档。
备份您的应用
对于自动备份,您的应用若以API 23或更高版本为目标,并在Fire OS 7或更高版本上运行,将自动进行备份。您不需要实现BackupAgent
。自动备份(android:allowBackup
)的默认值为true
,但我们建议您在清单中显式设置布尔值,如下所示:
<manifest ... >
...
<application android:allowBackup="true" ... >
...
</application>
</manifest>
默认情况下,将备份应用数据目录中的所有文件(缓存文件除外)。
备份数据子集
Android允许应用开发者通过修改XML文件架构来自定义他们想要备份的文件。您可以使用此文件中的模式来选择要包含或排除的文件。确保备份的数据不包括任何最终用户的敏感数据,例如,1996年《健康保险携带和责任法案》(HIPAA)定义的“受保护的健康信息”,或联邦贸易委员会《健康泄露通知规则》定义的“PHR可识别健康信息”。出于安全原因,您还应该在备份中排除密码令牌或凭证。如果存在任何加密的数据文件,例如共享的首选项,则在将这些文件传输到新设备后它们可能无法工作。最好也将这类文件排除。
如果您的应用需要对备份的数据进行更精细的控制,或者您需要侦听onRestoreFinished()
或onQuotaExceeded()
等备份事件,请考虑实现备份代理。
禁用自动备份
如果您选择禁用自动备份,您可以在应用的清单文件中将android:allowBackup
设置为false
。有关更多信息,请参阅启用和禁用备份。
从键/值备份过渡到自动备份
如果您以前通过子类化BackupAgent
,并在您的清单(android:backupAgent
)中设置它,从而实现了键/值备份,可在<application/>
上添加android:fullBackupOnly="true"
属性。
在切换到自动备份时,您可能需要重新处理现有BackupAgent
或将其完全删除。请记住,切换备份选项可能会损害应用的向后兼容性,因此请进行计划,主动处理此类情况。
测试自动备份
这是关于如何在Fire平板电脑上测试自动备份功能的一组概括性步骤。有关AOSP的自动备份测试文档的更多信息,请参阅Android的备份测试指南。
选项1: 使用亚马逊的传输
-
确保正确设置传输。
adb shell bmgr list transports
您日志中的结果应当和以下所示类似:
* com.amazon.device.backup/.transport.BackupTransportService com.android.localtransport/.LocalTransport
如果未设置为亚马逊的备份传输,则可以通过命令行进行设置。
adb shell bmgr transport com.amazon.device.backup/.transport.BackupTransportService
-
设置全局设置
force_auto_backup
。要在您的设备上支持自动备份,可设置
force_auto_backup
标记。adb shell settings put global force_auto_backup 1
-
作为运行自动备份的前提条件,需要运行键值备份。必须先完成此操作。
adb shell bmgr backup @pm@ && adb shell bmgr run
-
备份程序包。
adb shell bmgr backupnow <程序包>
示例:
adb shell bmgr backupnow com.example.app
完整备份运行时,您应当会看到类似于如下的日志。
I PFTBT : 完整数据备份完成执行。
注意: 完整备份和自动备份是一回事,这两个术语可以互换使用。 -
查询恢复令牌。
恢复令牌是标识运行的备份的唯一ID。
例如:
adb shell dumpsys backup | grep "Current:"
输出:
Current: 3
在本例中,3是“恢复令牌”。
-
测试恢复令牌。
adb shell bmgr restore <令牌> <程序包>
示例:
adb shell bmgr restore 3 com.example.app
如果成功完成恢复,则应打印以下日志。
I BackupManagerService: 恢复完成。
您还可以测试数据删除,以检查恢复是否有效。卸载应用并重新安装。然后检查是否已恢复备份的数据。
如果您正确执行了所有步骤,应当能够对你的应用进行任何更改,并看到用您之前备份的数据恢复的更改。如果您遇到任何问题,请参阅下面的故障排除步骤。
选项2: 使用本地传输
您可使用AOSP的本地传输,在本地测试数据。这不会将任何数据备份到服务器,但您可以使用它来测试将备份哪些数据并将其恢复到应用。Android的备份测试指南包括使用本地传输的信息。相应步骤与以上所述大致相同。唯一的区别在于,您没有将您的传输设置为亚马逊的传输,而是AOSP的本地传输。
adb shell bmgr transport com.android.localtransport/.LocalTransport
关于备份传输
备份传输处理在服务器中上传和下载设备备份数据的逻辑。对于亚马逊而言,传输处理将数据备份到AWS S3的逻辑。
如何获取所有传输的列表
您可以通过以下命令获得所有传输的列表:
adb shell bmgr list transports
故障排除
未启用备份
如果您在日志中看到以下内容:
备份完成并且结果为: 不允许备份
无法运行备份
这意味着您的设备上没有启用备份。要解决这个问题,可以转到Settings(设置)> Device Options(设备选项)> Backup & Restore(备份和恢复)。然后将Backup & Restore切换为ON
(开)。接下来尝试重新运行备份。
传输已拒绝
首先,确保您的Fire平板电脑为最新版本。然后,如果您在日志中看到以下内容:
程序包<程序包名称>的结果: 传输已拒绝程序包,因为它目前无法处理该程序包
这种情况可能有几种原因,最常见的原因是节流。每天仅允许将程序包备份一次。要设置较低的节流限制,请运行以下命令
adb shell settings put secure overridden_backup_throttle_delay_ms <按毫秒计延迟>
示例:
adb shell settings put secure overridden_backup_throttle_delay_ms 1000
如果您已经将平板电脑设置为较低的节流限制,则此错误可能意味着您没有要备份的数据。进行检查以确认您的应用是否设置了任何要备份的数据。要获取一些任意的备份数据,请运行以下命令:
adb shell
cd /storage/emulated/0/Android/data/<您的程序包名称>/files
接下来创建测试文件:
touch test.txt
echo "some test data" >> test.txt
未找到程序包
如果您在日志中看到以下内容:
程序包<程序包名称>的结果: 未找到程序包
进行检查以确认设备上是否已安装您的程序包。
Fire OS 7中的通知
从Android Level 8.0(API级别26)开始,必须为应用发送的通知分配一个通道。(推荐是一种通知。) 若应用发送通知或推荐,必须创建一个通道并将通道与通知关联。没有通道ID的通知将被删除。
从更高层次上说,如需向通知添加通道,需进行以下操作:
- 步骤1: 创建通知通道,并在通知管理器中注册。
- 步骤2: 设置通知的通道ID,使用以下方法之一:
以下章节提供更多详细信息和代码示例。
步骤1: 创建通知通道,并在通知管理器中注册
以下内容来自Android文档中的创建通知通道:
创建通知通道
如需创建通知通道,请进行以下步骤:
- 构建具有唯一通道ID、用户可见名称和重要性级别的
NotificationChannel
对象。- 或使用
setDescription
指定用户在系统设置中看到的描述。通过将通知通道传递给
createNotificationChannel
,注册通知通道。private void createNotificationChannel() { //创建通知通道,但仅限于API 26+,因为 // NotificationChannel类是新的,不在支持库中 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = getString(R.string.channel_name); String description = getString(R.string.channel_description); int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); //在系统中注册通道;无法更改重要性 //或之后其他通知行为 NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } }
步骤2: 设置通知的通道ID
有两个方法可用于设置通知的通道ID。可使用ContentRecommendation
和反射,设置通道ID,也可以使用Notification.Builder
。
方法1: 通过使用createContentRecommendation
和反射,设置通道ID
Notification notification = createContentRecommendation(largeIcon, notificationId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d(TAG, "SDK version is >= Android O");
try {
Field channel = notification.getClass().getDeclaredField("mChannelId");
channel.setAccessible(true);
channel.set(notification, StringTerms.CHANNEL_ID);
}
catch (Exception e) {
Log.d(TAG, "Can't set ChannelId", e);
}
}
方法2: 将Notification.Builder
与通道ID结合使用
以下代码是由Google Git上的Android开源项目改编而成。
public Notification getNotificationObject(Context context) {
Notification.Builder builder = new Notification.Builder(context, "channelId");
RecommendationExtender recExtender = new RecommendationExtender();
// 对通知对象中的所有内容推荐数据进行编码
builder.setCategory(Notification.CATEGORY_RECOMMENDATION);
builder.setContentTitle(mTitle);
builder.setContentText(mText);
builder.setContentInfo(mSourceName);
builder.setLargeIcon(mContentImage);
builder.setSmallIcon(mBadgeIconId);
if (mBackgroundImageUri != null) {
builder.getExtras().putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, mBackgroundImageUri);
}
builder.setColor(mColor);
builder.setGroup(mGroup);
builder.setSortKey(mSortKey);
builder.setProgress(mProgressMax, mProgressAmount, false);
builder.setAutoCancel(mAutoDismiss);
if (mContentIntentData != null) {
PendingIntent contentPending;
if (mContentIntentData.mType == INTENT_TYPE_ACTIVITY) {
contentPending = PendingIntent.getActivity(context, mContentIntentData.mRequestCode,
mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT,
mContentIntentData.mOptions);
}
else if (mContentIntentData.mType == INTENT_TYPE_SERVICE) {
contentPending = PendingIntent.getService(context, mContentIntentData.mRequestCode,
mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
else { // Default:INTENT_TYPE_BROADCAST{
contentPending = PendingIntent.getBroadcast(context,
mContentIntentData.mRequestCode,
mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
builder.setContentIntent(contentPending);
}
if (mDismissIntentData != null) {
PendingIntent dismissPending;
if (mDismissIntentData.mType == INTENT_TYPE_ACTIVITY) {
dismissPending = PendingIntent.getActivity(context, mDismissIntentData.mRequestCode,
mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT,
mDismissIntentData.mOptions);
}
else if (mDismissIntentData.mType == INTENT_TYPE_SERVICE) {
dismissPending = PendingIntent.getService(context, mDismissIntentData.mRequestCode,
mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
else { // Default:INTENT_TYPE_BROADCAST{
dismissPending = PendingIntent.getBroadcast(context,
mDismissIntentData.mRequestCode,
mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
builder.setDeleteIntent(dismissPending);
}
recExtender.setContentTypes(mContentTypes);
recExtender.setGenres(mContentGenres);
recExtender.setPricingInformation(mPriceType, mPriceValue);
recExtender.setStatus(mStatus);
recExtender.setMaturityRating(mMaturityRating);
recExtender.setRunningTime(mRunningTime);
builder.extend(recExtender);
Notification notif = builder.build();
return notif;
}
有关更多详细信息,请参阅关于创建和管理通知通道的Android文档。
Amazon Device Messaging (ADM)兼容性
如果您的应用使用Amazon Device Messaging,则需要更新SDK以避免在Fire OS 7上出现崩溃。在之前的版本中,ADM使用IntentService
向在后台运行的客户端应用发送消息。在Fire OS 7中,Android 8.0(API级别26)的所有后台执行限制适用于IntentService
。例如,根据Android文档中的后台服务限制:
IntentService
是一项服务,因此受后台服务新限制的约束。因此,对于Android 8.0或更高版本而言,许多依赖IntentService
的应用无法正常运行。出于这个原因,Android支持库26.0.0引入了一个新的JobIntentService
类,该类与IntentService
具有相同功能,但在Android 8.0或更高版本上运行时,使用作业而不是服务。
应用必须使用JobIntentService
才能在后台运行时接收ADM消息。在Android 8.0或更高版本上运行时,这个较新的类使用作业而不是服务。
ADMMessageHandlerJobBase
是一个新的类,它将使用JobIntentService
在后台传递消息。您应该使用此类代替旧的ADMMessageHandlerBase
。创建与ADM交互的应用时,您应该在处理程序中扩展ADMMessageHandlerJobBase
。关于示例,请参阅处理注册和消息。此外,另请参阅设置Amazon Device Messaging和更新您的应用清单,这两项也作为版本的一部分进行了更新。
支持
如果应用在Fire OS 7上存在问题,请在Fire平板电脑论坛中报告该问题。
Last updated: 2023年3月1日