অ্যান্ড্রয়েড এন এবং তার আগের সুপারিশগুলি৷

টিভির সাথে ইন্টারঅ্যাক্ট করার সময়, ব্যবহারকারীরা সাধারণত কন্টেন্ট দেখার আগে ন্যূনতম ইনপুট দিতে পছন্দ করেন। অনেক টিভি ব্যবহারকারীর জন্য একটি আদর্শ দৃশ্য হল: বসুন, চালু করুন এবং দেখুন। ব্যবহারকারীদের তাদের পছন্দের বিষয়বস্তুতে পৌঁছানোর জন্য সবচেয়ে কম পদক্ষেপ হল সাধারণত যে পথটি তারা পছন্দ করে।

দ্রষ্টব্য: শুধুমাত্র Android 7.1 (API স্তর 25) পর্যন্ত অ্যান্ড্রয়েড সংস্করণে চলমান অ্যাপগুলিতে সুপারিশ করার জন্য এখানে বর্ণিত APIগুলি ব্যবহার করুন৷ Android 8.0 (API লেভেল 26) এবং পরবর্তীতে চলমান অ্যাপগুলির জন্য সুপারিশ সরবরাহ করতে, আপনার অ্যাপকে অবশ্যই সুপারিশ চ্যানেল ব্যবহার করতে হবে।

অ্যান্ড্রয়েড ফ্রেমওয়ার্ক হোম স্ক্রিনে একটি সুপারিশ সারি প্রদান করে ন্যূনতম-ইনপুট ইন্টারঅ্যাকশনে সহায়তা করে। সামগ্রীর সুপারিশগুলি ডিভাইসের প্রথম ব্যবহারের পরে টিভি হোম স্ক্রিনের প্রথম সারি হিসাবে উপস্থিত হয়৷ আপনার অ্যাপের বিষয়বস্তু ক্যাটালগ থেকে সুপারিশগুলি অবদান রাখলে ব্যবহারকারীদের আপনার অ্যাপে ফিরিয়ে আনতে সাহায্য করতে পারে।

চিত্র 1. সুপারিশ সারি একটি উদাহরণ.

এই নির্দেশিকা আপনাকে শেখায় কিভাবে সুপারিশ তৈরি করতে হয় এবং সেগুলিকে Android ফ্রেমওয়ার্কে প্রদান করতে হয় যাতে ব্যবহারকারীরা সহজেই আপনার অ্যাপের সামগ্রী আবিষ্কার করতে এবং উপভোগ করতে পারে৷ Leanback স্যাম্পল অ্যাপে নমুনা বাস্তবায়নও দেখুন।

সুপারিশের জন্য সর্বোত্তম অনুশীলন

সুপারিশগুলি ব্যবহারকারীদের তারা যে বিষয়বস্তু এবং অ্যাপগুলি উপভোগ করে তা দ্রুত খুঁজে পেতে সহায়তা করে৷ উচ্চ-মানের এবং ব্যবহারকারীদের জন্য প্রাসঙ্গিক সুপারিশগুলি তৈরি করা আপনার 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 অবজেক্ট হিসাবে সুপারিশগুলি গ্রহণ করে৷

মান নির্ধারণ করা

সুপারিশ কার্ডের জন্য 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);