开发者控制台

开发运行Fire OS 7的Amazon Fire TV设备

开发运行Fire OS 7的Amazon Fire TV设备

Fire OS 7基于Android 9 Pie。遵从以下指南,确保应用与Fire OS 7兼容。

运行Fire OS 7和之前Fire OS版本的设备

Fire OS 7基于Android 9 Pie(API级别28)。Fire OS 7最初在2019年针对一些Fire TV设备发布。

大部分2018年的Amazon Fire TV设备运行的是Fire OS 6,Fire OS 6基于Android Nougat(Android 7.1.2,级别25)。即使是较旧的Fire TV设备,运行的也是Fire OS 5(Android 5.1级别22)。通常,较旧设备的Fire OS版本不会升级。

有关Fire TV设备和版本的详细列表,请参阅Fire OS版本

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设备上使用谷歌服务。相反,针对所需的服务(例如:应用内购买),必须使用应用和游戏服务开发工具包。更多详细信息,请参阅Amazon Fire TV开发与Android TV开发

让应用以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设备。

更多详细信息,请参阅识别Fire TV设备。另请参阅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 OS 7中的通知

从Android Level 8.0(API级别26)开始,必须为应用发送的通知分配一个通道。(推荐是一种通知。) 若应用发送通知或推荐,必须创建一个通道并将通道与通知关联。没有通道ID的通知将被删除。

从更高层次上说,如需向通知添加通道,需进行以下操作:

  1. 步骤1: 创建通知通道,并在通知管理器中注册
  2. 步骤2: 设置通知的通道ID,使用以下方法之一:

以下章节提供更多详细信息和代码示例。

步骤1: 创建通知通道,并在通知管理器中注册

以下内容来自Android文档中的创建通知通道

创建通知通道

如需创建通知通道,请进行以下步骤:

  1. 构建具有唯一通道ID、用户可见名称和重要性级别的NotificationChannel对象。
  2. 或使用setDescription指定用户在系统设置中看到的描述。
  3. 通过将通知通道传递给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更新您的应用清单,这两项也作为版本的一部分进行了更新。

可以在此处下载更新后的ADM SDK

唤醒锁更改

如果客户未在4小时内与聚焦且唤醒的应用进行互动,他们将收到“Are you still watching?”(您是否还在查看?)的提示,如果不予以确认,他们将被转到主页。有关更多信息,请参阅唤醒锁要求

可以在“设置”中关闭此功能。如果该应用是标牌应用,请联系亚马逊申请豁免。

支持

如果应用在Fire OS 7上存在问题,请在亚马逊Fire TV和Fire TV Stick论坛中报告该问题。


Last updated: 2021年2月5日