توصیه هایی در Android N و نسخه های قبلی

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

توجه: فقط از APIهای توضیح داده شده در اینجا برای ارائه توصیه در برنامه‌های در حال اجرا در نسخه‌های Android تا و شامل Android 7.1 (سطح API 25) استفاده کنید. برای ارائه توصیه‌هایی برای برنامه‌هایی که در Android نسخه 8.0 (سطح API 26) و جدیدتر اجرا می‌شوند، برنامه شما باید از کانال‌های توصیه‌ها استفاده کند.

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

شکل 1. نمونه ای از ردیف توصیه ها.

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

بهترین روش ها برای توصیه ها

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

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

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

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

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

بازخوانی توصیه ها

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

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

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

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

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

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

از 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>

توصیه هایی بسازید

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

تنظیم مقادیر

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

کاتلین

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;
        }
...

اعلان را ایجاد کنید

هنگامی که مقادیر را تنظیم کردید، سپس اعلان را ایجاد می‌کنید، مقادیر را از کلاس سازنده به اعلان اختصاص می‌دهید و 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);