توصیه‌ها در Android N و نسخه‌های قدیمی‌تر

هنگام تعامل با تلویزیون، کاربران معمولاً ترجیح می‌دهند قبل‌از تماشای محتوا، حداقل ورودی را ارائه دهند. سناریوی ایده‌آل برای بسیاری از کاربران تلویزیون این است: بنشینند، تلویزیون را روشن کنند، و تماشا کنند. کمترین مراحل برای رساندن کاربران به محتوایی که از آن لذت می‌برند معمولاً مسیری است که ترجیح می‌دهند.

توجه: از میاناهای برنامه‌سازی کاربردی شرح‌داده‌شده در اینجا برای ارائه توصیه‌ها فقط در برنامه‌هایی که در نسخه‌های Android تا Android 7.1 (سطح میانای برنامه‌سازی کاربردی ۲۵) اجرا می‌شوند استفاده کنید. برای ارائه توصیه برای برنامه‌هایی که در Android نسخه ۸.۰ (سطح میانای برنامه‌سازی کاربردی ۲۶) و بالاتر اجرا می‌شوند، برنامه‌تان باید از کانال‌های توصیه‌ها استفاده کند.

چارچوب Android با ارائه ردیف توصیه‌ها در صفحه اصلی، به تعامل با حداقل ورودی کمک می‌کند. توصیه‌های محتوا پس‌از اولین استفاده از دستگاه، در ردیف اول صفحه اصلی تلویزیون نشان داده می‌شود. ارائه توصیه‌هایی از کاتالوگ محتوای برنامه‌تان می‌تواند به بازگرداندن کاربران به برنامه‌تان کمک کند.

نمونه‌ای از ردیف توصیه‌ها در صفحه اصلی Android TV
شکل ۱. نمونه‌ای از ردیف توصیه‌ها.

این راهنما به شما آموزش می‌دهد که چگونه توصیه‌ها را ایجاد کنید و آن‌ها را به چارچوب Android ارائه دهید تا کاربران بتوانند محتوای برنامه شما را کشف کنند و از آن لذت ببرند. همچنین نمونه پیاده‌سازی را در برنامه نمونه Leanback ببینید.

روال‌های مطلوب برای توصیه‌ها

توصیه‌ها به کاربران کمک می‌کنند محتوا و برنامه‌های موردعلاقه‌شان را به‌سرعت پیدا کنند. ایجاد توصیه‌های باکیفیت و مرتبط با کاربران عامل مهمی در ایجاد تجربه کاربری عالی با برنامه تلویزیون شما است. به همین دلیل، باید به‌دقت بررسی کنید که چه توصیه‌هایی را به کاربر ارائه می‌دهید و آن‌ها را به‌دقت مدیریت کنید.

انواع توصیه‌ها

وقتی توصیه‌هایی ایجاد می‌کنید، باید کاربران را به فعالیت‌های مشاهده ناتمام پیوند دهید یا فعالیت‌هایی را پیشنهاد دهید که آن را به محتوای مرتبط گسترش دهد. در اینجا چند نوع خاص از توصیه‌هایی که باید درنظر بگیرید آورده شده است:

  • توصیه‌های محتوای ادامه برای قسمت بعدی تا کاربران بتوانند تماشای مجموعه را ازسر بگیرند. یا از توصیه‌های ادامه دادن برای فیلم‌ها، نمایش‌های تلویزیونی، یا پادکست‌های موقتاً متوقف‌شده استفاده کنید تا کاربران بتوانند فقط با چند کلیک به تماشای محتوای موقتاً متوقف‌شده برگردند.
  • توصیه‌های محتوای جدید، مثلاً برای قسمت جدیدی که برای اولین‌بار پخش می‌شود، اگر کاربر تماشای مجموعه دیگری را تمام کرده باشد. همچنین، اگر برنامه‌تان به کاربران اجازه می‌دهد محتوا را مشترک شوند، دنبال کنند، یا ردگیری کنند، از توصیه‌های محتوای جدید برای موارد تماشانشده در فهرست محتوای ردگیری‌شده آن‌ها استفاده کنید.
  • توصیه‌های محتوای مرتبط براساس سابقه رفتار تماشای کاربران.

برای اطلاعات بیشتر درباره نحوه طراحی کارت‌های توصیه برای بهترین تجربه کاربری، ردیف توصیه را در «مشخصات طراحی Android TV» ببینید.

بازآوری توصیه‌ها

هنگام بازآوری توصیه‌ها، آن‌ها را فقط حذف و دوباره پست نکنید، زیرا این کار باعث می‌شود توصیه‌ها در انتهای ردیف توصیه‌ها ظاهر شوند. وقتی یک مورد محتوا، مانند یک فیلم، پخش شد، آن را از توصیه‌ها حذف کنید.

سفارشی کردن توصیه‌ها

می‌توانید کارت‌های توصیه را با تنظیم عناصر میانای کاربر مثل تصویر پیش‌زمینه و پس‌زمینه کارت، رنگ، نماد برنامه، عنوان، و زیرعنوان سفارشی کنید تا اطلاعات نمانام‌سازی را منتقل کنید. برای اطلاعات بیشتر، ردیف توصیه را در «مشخصات طراحی Android TV» ببینید.

توصیه‌های گروهی

می‌توانید توصیه‌ها را براساس منبع توصیه گروه‌بندی کنید. برای مثال، برنامه‌تان ممکن است دو گروه توصیه ارائه دهد: توصیه‌هایی برای محتوایی که کاربر در آن مشترک است، و توصیه‌هایی برای محتوای پرطرفدار جدیدی که ممکن است کاربر از آن مطلع نباشد.

هنگام ایجاد یا به‌روزرسانی ردیف توصیه، سیستم توصیه‌ها را برای هر گروه به‌طور جداگانه رتبه‌بندی و مرتب می‌کند. با ارائه اطلاعات گروه برای توصیه‌هایتان، می‌توانید مطمئن شوید که توصیه‌هایتان تحت توصیه‌های نامربوط سفارش داده نمی‌شوند.

از NotificationCompat.Builder.setGroup() برای تنظیم رشته کلید گروه توصیه استفاده کنید. برای مثال، برای علامت‌گذاری توصیه‌ای به‌عنوان متعلق به گروهی که حاوی محتوای پرطرفدار جدید است، می‌توانید setGroup("trending") را فراخوانی کنید.

ایجاد سرویس توصیه‌ها

توصیه‌های محتوا با پردازش پس‌زمینه ایجاد می‌شود. برای اینکه برنامه‌تان بتواند در توصیه‌ها مشارکت کند، سرویسی ایجاد کنید که به‌طور دوره‌ای فهرستگان را از کاتالوگ برنامه‌تان به فهرست توصیه‌های سیستم اضافه کند.

نمونه کد زیر نحوه گسترش IntentService را برای ایجاد سرویس توصیه برای برنامه‌تان نشان می‌دهد:

کاتلین

class UpdateRecommendationsService : IntentService("RecommendationService") {
    override protected fun onHandleIntent(intent: Intent) {
        Log.d(TAG, "Updating recommendation cards")
        val recommendations = VideoProvider.getMovieList()
        if (recommendations == null) return

        var count = 0

        try {
            val builder = RecommendationBuilder()
                    .setContext(applicationContext)
                    .setSmallIcon(R.drawable.videos_by_google_icon)

            for (entry in recommendations.entrySet()) {
                for (movie in entry.getValue()) {
                    Log.d(TAG, "Recommendation - " + movie.getTitle())

                    builder.setBackground(movie.getCardImageUrl())
                            .setId(count + 1)
                            .setPriority(MAX_RECOMMENDATIONS - count)
                            .setTitle(movie.getTitle())
                            .setDescription(getString(R.string.popular_header))
                            .setImage(movie.getCardImageUrl())
                            .setIntent(buildPendingIntent(movie))
                            .build()
                    if (++count >= MAX_RECOMMENDATIONS) {
                        break
                    }
                }
                if (++count >= MAX_RECOMMENDATIONS) {
                    break
                }
            }
        } catch (e: IOException) {
            Log.e(TAG, "Unable to update recommendation", e)
        }
    }

    private fun buildPendingIntent(movie: Movie): PendingIntent {
        val detailsIntent = Intent(this, DetailsActivity::class.java)
        detailsIntent.putExtra("Movie", movie)

        val stackBuilder = TaskStackBuilder.create(this)
        stackBuilder.addParentStack(DetailsActivity::class.java)
        stackBuilder.addNextIntent(detailsIntent)

        // Ensure a unique PendingIntents, otherwise all
        // recommendations end up with the same PendingIntent
        detailsIntent.setAction(movie.getId().toString())

        val intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
        return intent
    }

    companion object {
        private val TAG = "UpdateRecommendationsService"
        private val MAX_RECOMMENDATIONS = 3
    }
}

جاوا

public class UpdateRecommendationsService extends IntentService {
    private static final String TAG = "UpdateRecommendationsService";
    private static final int MAX_RECOMMENDATIONS = 3;

    public UpdateRecommendationsService() {
        super("RecommendationService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "Updating recommendation cards");
        HashMap<String, List<Movie>> recommendations = VideoProvider.getMovieList();
        if (recommendations == null) return;

        int count = 0;

        try {
            RecommendationBuilder builder = new RecommendationBuilder()
                    .setContext(getApplicationContext())
                    .setSmallIcon(R.drawable.videos_by_google_icon);

            for (Map.Entry<String, List<Movie>> entry : recommendations.entrySet()) {
                for (Movie movie : entry.getValue()) {
                    Log.d(TAG, "Recommendation - " + movie.getTitle());

                    builder.setBackground(movie.getCardImageUrl())
                            .setId(count + 1)
                            .setPriority(MAX_RECOMMENDATIONS - count)
                            .setTitle(movie.getTitle())
                            .setDescription(getString(R.string.popular_header))
                            .setImage(movie.getCardImageUrl())
                            .setIntent(buildPendingIntent(movie))
                            .build();

                    if (++count >= MAX_RECOMMENDATIONS) {
                        break;
                    }
                }
                if (++count >= MAX_RECOMMENDATIONS) {
                    break;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Unable to update recommendation", e);
        }
    }

    private PendingIntent buildPendingIntent(Movie movie) {
        Intent detailsIntent = new Intent(this, DetailsActivity.class);
        detailsIntent.putExtra("Movie", movie);

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(DetailsActivity.class);
        stackBuilder.addNextIntent(detailsIntent);
        // Ensure a unique PendingIntents, otherwise all
        // recommendations end up with the same PendingIntent
        detailsIntent.setAction(Long.toString(movie.getId()));

        PendingIntent intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        return intent;
    }
}

برای اینکه این سرویس توسط سیستم شناسایی و اجرا شود، آن را بااستفاده از مانیفست برنامه‌تان ثبت کنید. تکه‌کد زیر نحوه اعلام این کلاس را به‌عنوان سرویس نشان می‌دهد:

<manifest ... >
  <application ... >
    ...

    <service
            android:name="com.example.android.tvleanback.UpdateRecommendationsService"
            android:enabled="true" />
  </application>
</manifest>

ایجاد توصیه‌ها

وقتی سرویس توصیه‌تان شروع به کار کرد، باید توصیه‌هایی ایجاد کند و آن‌ها را به چارچوب Android ارسال کند. چارچوب توصیه‌ها را به‌عنوان اشیاء Notification دریافت می‌کند که از الگوی خاصی استفاده می‌کنند و با دسته خاصی علامت‌گذاری شده‌اند.

درحال تنظیم مقادیر

برای تنظیم مقادیر عنصر میانای کاربر برای کارت توصیه، کلاس سازنده‌ای ایجاد می‌کنید که از الگوی سازنده شرح‌داده‌شده در زیر پیروی می‌کند. ابتدا، مقادیر عناصر کارت توصیه را تنظیم می‌کنید.

کاتلین

class RecommendationBuilder {
    ...

    fun setTitle(title: String): RecommendationBuilder {
        this.title = title
        return this
    }

    fun setDescription(description: String): RecommendationBuilder {
        this.description = description
        return this
    }

    fun setImage(uri: String): RecommendationBuilder {
        imageUri = uri
        return this
    }

    fun setBackground(uri: String): RecommendationBuilder {
        backgroundUri = uri
        return this
    }

...

جاوا

public class RecommendationBuilder {
    ...

    public RecommendationBuilder setTitle(String title) {
            this.title = title;
            return this;
        }

        public RecommendationBuilder setDescription(String description) {
            this.description = description;
            return this;
        }

        public RecommendationBuilder setImage(String uri) {
            imageUri = uri;
            return this;
        }

        public RecommendationBuilder setBackground(String uri) {
            backgroundUri = uri;
            return this;
        }
...

ایجاد اعلان

Once you've set the values, you then build the notification, assigning the values from the builder class to the notification, and calling NotificationCompat.Builder.build().

همچنین، حتماً با setLocalOnly() تماس بگیرید تا اعلان NotificationCompat.BigPictureStyle در دستگاه‌های دیگر نشان داده نشود.

نمونه کد زیر نحوه ساختن توصیه را نشان می‌دهد.

کاتلین

class RecommendationBuilder {
    ...

    @Throws(IOException::class)
    fun build(): Notification {
        ...

        val notification = NotificationCompat.BigPictureStyle(
        NotificationCompat.Builder(context)
                .setContentTitle(title)
                .setContentText(description)
                .setPriority(priority)
                .setLocalOnly(true)
                .setOngoing(true)
                .setColor(context.resources.getColor(R.color.fastlane_background))
                .setCategory(Notification.CATEGORY_RECOMMENDATION)
                .setLargeIcon(image)
                .setSmallIcon(smallIcon)
                .setContentIntent(intent)
                .setExtras(extras))
                .build()

        return notification
    }
}

جاوا

public class RecommendationBuilder {
    ...

    public Notification build() throws IOException {
        ...

        Notification notification = new NotificationCompat.BigPictureStyle(
                new NotificationCompat.Builder(context)
                        .setContentTitle(title)
                        .setContentText(description)
                        .setPriority(priority)
                        .setLocalOnly(true)
                        .setOngoing(true)
                        .setColor(context.getResources().getColor(R.color.fastlane_background))
                        .setCategory(Notification.CATEGORY_RECOMMENDATION)
                        .setLargeIcon(image)
                        .setSmallIcon(smallIcon)
                        .setContentIntent(intent)
                        .setExtras(extras))
                .build();

        return notification;
    }
}

اجرای سرویس توصیه‌ها

سرویس توصیه برنامه شما باید به‌طور دوره‌ای اجرا شود تا توصیه‌های فعلی را ایجاد کند. برای اجرای سرویس، کلاسی ایجاد کنید که زمان‌سنجی را اجرا کند و آن را در فواصل زمانی منظم فراخوانی کند. نمونه کد زیر کلاس BroadcastReceiver را گسترش می‌دهد تا اجرای دوره‌ای سرویس توصیه را هر نیم ساعت یک‌بار شروع کند:

کاتلین

class BootupActivity : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d(TAG, "BootupActivity initiated")
        if (intent.action.endsWith(Intent.ACTION_BOOT_COMPLETED)) {
            scheduleRecommendationUpdate(context)
        }
    }

    private fun scheduleRecommendationUpdate(context: Context) {
        Log.d(TAG, "Scheduling recommendations update")
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val recommendationIntent = Intent(context, UpdateRecommendationsService::class.java)
        val alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0)
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                INITIAL_DELAY,
                AlarmManager.INTERVAL_HALF_HOUR,
                alarmIntent
        )
    }

    companion object {
        private val TAG = "BootupActivity"
        private val INITIAL_DELAY:Long = 5000
    }
}

جاوا

public class BootupActivity extends BroadcastReceiver {
    private static final String TAG = "BootupActivity";

    private static final long INITIAL_DELAY = 5000;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "BootupActivity initiated");
        if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
            scheduleRecommendationUpdate(context);
        }
    }

    private void scheduleRecommendationUpdate(Context context) {
        Log.d(TAG, "Scheduling recommendations update");

        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent recommendationIntent = new Intent(context, UpdateRecommendationsService.class);
        PendingIntent alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0);

        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                INITIAL_DELAY,
                AlarmManager.INTERVAL_HALF_HOUR,
                alarmIntent);
    }
}

این پیاده‌سازی کلاس BroadcastReceiver باید پس‌از راه‌اندازی دستگاه تلویزیونی که در آن نصب شده است اجرا شود. برای انجام این کار، این کلاس را در مانیفست برنامه‌تان با فیلتر قصدی ثبت کنید که تکمیل فرایند راه‌اندازی دستگاه را گوش می‌دهد. نمونه کد زیر نحوه افزودن این پیکربندی به مانیفست را نشان می‌دهد:

<manifest ... >
  <application ... >
    <receiver android:name="com.example.android.tvleanback.BootupActivity"
              android:enabled="true"
              android:exported="false">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
      </intent-filter>
    </receiver>
  </application>
</manifest>

مهم: برای دریافت اعلان تکمیل راه‌اندازی، برنامه‌تان باید اجازه RECEIVE_BOOT_COMPLETED را درخواست کند. برای اطلاعات بیشتر، به ACTION_BOOT_COMPLETED مراجعه کنید.

در روش onHandleIntent() کلاس سرویس توصیه‌تان، توصیه را به‌صورت زیر برای مدیر پست کنید:

کاتلین

val notification = notificationBuilder.build()
notificationManager.notify(id, notification)

جاوا

Notification notification = notificationBuilder.build();
notificationManager.notify(id, notification);