বাহ্যিক ডিভাইস নিয়ন্ত্রণ করুন

অ্যান্ড্রয়েড 11 এবং পরবর্তীতে, কুইক অ্যাক্সেস ডিভাইস কন্ট্রোল বৈশিষ্ট্য ব্যবহারকারীকে ডিফল্ট লঞ্চার থেকে তিনটি ইন্টারঅ্যাকশনের মধ্যে ব্যবহারকারীর সামর্থ্য থেকে লাইট, থার্মোস্ট্যাট এবং ক্যামেরার মতো বাহ্যিক ডিভাইসগুলি দ্রুত দেখতে এবং নিয়ন্ত্রণ করতে দেয়। ডিভাইস OEM বেছে নেয় তারা কোন লঞ্চার ব্যবহার করে। ডিভাইস এগ্রিগেটর—উদাহরণস্বরূপ, Google Home—এবং থার্ড-পার্টি ভেন্ডর অ্যাপ এই স্পেসে প্রদর্শনের জন্য ডিভাইস সরবরাহ করতে পারে। এই পৃষ্ঠাটি আপনাকে দেখায় যে কীভাবে এই স্পেসে ডিভাইস নিয়ন্ত্রণগুলি সরাতে হয় এবং সেগুলিকে আপনার নিয়ন্ত্রণ অ্যাপে লিঙ্ক করতে হয়।

চিত্র 1. অ্যান্ড্রয়েড UI-তে ডিভাইস নিয়ন্ত্রণ স্থান।

এই সমর্থন যোগ করতে, একটি ControlsProviderService তৈরি করুন এবং ঘোষণা করুন। পূর্বনির্ধারিত নিয়ন্ত্রণ প্রকারের উপর ভিত্তি করে আপনার অ্যাপ সমর্থন করে এমন নিয়ন্ত্রণগুলি তৈরি করুন এবং তারপর এই নিয়ন্ত্রণগুলির জন্য প্রকাশক তৈরি করুন৷

ইউজার ইন্টারফেস

ডিভাইসগুলি টেমপ্লেটেড উইজেট হিসাবে ডিভাইস নিয়ন্ত্রণের অধীনে প্রদর্শিত হয়। পাঁচটি ডিভাইস কন্ট্রোল উইজেট উপলব্ধ, যেমনটি নিম্নলিখিত চিত্রে দেখানো হয়েছে:

উইজেট টগল করুন
টগল করুন
স্লাইডার উইজেট দিয়ে টগল করুন
স্লাইডার দিয়ে টগল করুন
রেঞ্জ উইজেট
ব্যাপ্তি (চালু বা বন্ধ করা যাবে না)
স্টেটলেস টগল উইজেট
রাষ্ট্রহীন টগল
তাপমাত্রা প্যানেল উইজেট (বন্ধ)
তাপমাত্রা প্যানেল (বন্ধ)
চিত্র 2. টেমপ্লেটেড উইজেটগুলির সংগ্রহ।

একটি উইজেট স্পর্শ করা এবং ধরে রাখা আপনাকে গভীর নিয়ন্ত্রণের জন্য অ্যাপে নিয়ে যায়। আপনি প্রতিটি উইজেটে আইকন এবং রঙ কাস্টমাইজ করতে পারেন, তবে সেরা ব্যবহারকারীর অভিজ্ঞতার জন্য, ডিফল্ট আইকন এবং রঙ ব্যবহার করুন যদি ডিফল্ট সেটটি ডিভাইসের সাথে মেলে।

তাপমাত্রা প্যানেল উইজেট দেখানো একটি চিত্র (খোলা)
চিত্র 3. উন্মুক্ত তাপমাত্রা প্যানেল উইজেট খোলা।

পরিষেবা তৈরি করুন

এই বিভাগটি দেখায় কিভাবে ControlsProviderService তৈরি করতে হয়। এই পরিষেবাটি Android সিস্টেম UI কে বলে যে আপনার অ্যাপে ডিভাইস নিয়ন্ত্রণ রয়েছে যা অবশ্যই Android UI-এর ডিভাইস নিয়ন্ত্রণ অঞ্চলে প্রদর্শিত হবে৷

ControlsProviderService API প্রতিক্রিয়াশীল স্ট্রীমগুলির সাথে পরিচিতি অনুমান করে, যেমনটি প্রতিক্রিয়াশীল স্ট্রীমস গিটহাব প্রকল্পে সংজ্ঞায়িত করা হয়েছে এবং জাভা 9 ফ্লো ইন্টারফেসে প্রয়োগ করা হয়েছে। API নিম্নলিখিত ধারণাগুলিকে ঘিরে তৈরি করা হয়েছে:

  • প্রকাশক: আপনার আবেদন প্রকাশক।
  • গ্রাহক: সিস্টেম UI হল গ্রাহক এবং এটি প্রকাশকের কাছ থেকে বেশ কয়েকটি নিয়ন্ত্রণের জন্য অনুরোধ করতে পারে।
  • সদস্যতা: যে সময়সীমার মধ্যে প্রকাশক সিস্টেম UI-তে আপডেট পাঠাতে পারে। হয় প্রকাশক বা গ্রাহক এই উইন্ডোটি বন্ধ করতে পারেন৷

পরিষেবা ঘোষণা করুন

আপনার অ্যাপটিকে অবশ্যই একটি পরিষেবা ঘোষণা করতে হবে—যেমন MyCustomControlService —এর অ্যাপ ম্যানিফেস্টে৷

পরিষেবাটিতে ControlsProviderService এর জন্য একটি অভিপ্রায় ফিল্টার অন্তর্ভুক্ত থাকতে হবে। এই ফিল্টারটি অ্যাপ্লিকেশনগুলিকে সিস্টেম UI-তে নিয়ন্ত্রণে অবদান রাখতে দেয়৷

আপনার একটি label প্রয়োজন যা সিস্টেম UI-এর নিয়ন্ত্রণগুলিতে প্রদর্শিত হয়৷

নিম্নলিখিত উদাহরণ দেখায় কিভাবে একটি পরিষেবা ঘোষণা করতে হয়:

<service
    android:name="MyCustomControlService"
    android:label="My Custom Controls"
    android:permission="android.permission.BIND_CONTROLS"
    android:exported="true"
    >
    <intent-filter>
      <action android:name="android.service.controls.ControlsProviderService" />
    </intent-filter>
</service>

এরপরে, MyCustomControlService.kt নামে একটি নতুন কোটলিন ফাইল তৈরি করুন এবং এটিকে ControlsProviderService() প্রসারিত করুন :

কোটলিন

    class MyCustomControlService : ControlsProviderService() {
        ...
    }
    

জাভা

    public class MyCustomJavaControlService extends ControlsProviderService {
        ...
    }
    

সঠিক নিয়ন্ত্রণের ধরন নির্বাচন করুন

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

  1. নিয়ন্ত্রণ প্রতিনিধিত্ব করে ডিভাইসের ধরন চয়ন করুন। DeviceTypes ক্লাস হল সমস্ত সমর্থিত ডিভাইসের একটি গণনা। UI-তে ডিভাইসের জন্য আইকন এবং রং নির্ধারণ করতে টাইপ ব্যবহার করা হয়।
  2. ব্যবহারকারী-মুখী নাম, ডিভাইসের অবস্থান-উদাহরণস্বরূপ, রান্নাঘর-এবং নিয়ন্ত্রণের সাথে যুক্ত অন্যান্য UI পাঠ্য উপাদান নির্ধারণ করুন।
  3. ব্যবহারকারীর মিথস্ক্রিয়া সমর্থন করার জন্য সেরা টেমপ্লেটটি বেছে নিন। কন্ট্রোলগুলিকে অ্যাপ্লিকেশন থেকে একটি ControlTemplate বরাদ্দ করা হয়। এই টেমপ্লেটটি সরাসরি ব্যবহারকারীকে নিয়ন্ত্রণের অবস্থার পাশাপাশি উপলব্ধ ইনপুট পদ্ধতিগুলি দেখায়—অর্থাৎ, ControlAction । নিম্নলিখিত সারণীটি উপলব্ধ কিছু টেমপ্লেট এবং তারা যে কাজগুলি সমর্থন করে তার রূপরেখা দেয়:
টেমপ্লেট অ্যাকশন বর্ণনা
ControlTemplate.getNoTemplateObject() None অ্যাপ্লিকেশনটি নিয়ন্ত্রণ সম্পর্কে তথ্য জানাতে এটি ব্যবহার করতে পারে, কিন্তু ব্যবহারকারী এটির সাথে যোগাযোগ করতে পারে না।
ToggleTemplate BooleanAction একটি নিয়ন্ত্রণের প্রতিনিধিত্ব করে যা সক্ষম এবং অক্ষম রাজ্যের মধ্যে পরিবর্তন করা যেতে পারে। BooleanAction অবজেক্টে এমন একটি ক্ষেত্র রয়েছে যা ব্যবহারকারী নিয়ন্ত্রণে ট্যাপ করলে অনুরোধ করা নতুন অবস্থার প্রতিনিধিত্ব করতে পরিবর্তিত হয়।
RangeTemplate FloatAction নির্দিষ্ট ন্যূনতম, সর্বোচ্চ এবং ধাপের মান সহ একটি স্লাইডার উইজেট প্রতিনিধিত্ব করে। যখন ব্যবহারকারী স্লাইডারের সাথে ইন্টারঅ্যাক্ট করে, তখন আপডেট করা মান সহ অ্যাপ্লিকেশনটিতে একটি নতুন FloatAction অবজেক্ট পাঠান।
ToggleRangeTemplate BooleanAction , FloatAction এই টেমপ্লেটটি ToggleTemplate এবং RangeTemplate এর সংমিশ্রণ। এটি স্পর্শ ইভেন্টগুলির পাশাপাশি একটি স্লাইডারকে সমর্থন করে, যেমন অস্পষ্ট আলো নিয়ন্ত্রণ করা।
TemperatureControlTemplate ModeAction , BooleanAction , FloatAction পূর্ববর্তী ক্রিয়াগুলিকে এনক্যাপসুলেট করার পাশাপাশি, এই টেমপ্লেটটি ব্যবহারকারীকে একটি মোড সেট করতে দেয়, যেমন তাপ, শীতল, তাপ/ঠান্ডা, ইকো বা বন্ধ৷
StatelessTemplate CommandAction একটি নিয়ন্ত্রণ নির্দেশ করতে ব্যবহৃত হয় যা স্পর্শ ক্ষমতা প্রদান করে কিন্তু যার অবস্থা নির্ধারণ করা যায় না, যেমন একটি IR টেলিভিশন রিমোট। আপনি একটি রুটিন বা ম্যাক্রো সংজ্ঞায়িত করতে এই টেমপ্লেটটি ব্যবহার করতে পারেন, যা নিয়ন্ত্রণ এবং রাষ্ট্রের পরিবর্তনের সমষ্টি।

এই তথ্য দিয়ে, আপনি নিয়ন্ত্রণ তৈরি করতে পারেন:

  • যখন নিয়ন্ত্রণের অবস্থা অজানা থাকে তখন Control.StatelessBuilder বিল্ডার ক্লাস ব্যবহার করুন।
  • নিয়ন্ত্রণের অবস্থা জানা থাকলে Control.StatefulBuilder বিল্ডার ক্লাস ব্যবহার করুন।

উদাহরণস্বরূপ, একটি স্মার্ট লাইট বাল্ব এবং একটি থার্মোস্ট্যাট নিয়ন্ত্রণ করতে, আপনার MyCustomControlService এ নিম্নলিখিত ধ্রুবক যোগ করুন:

কোটলিন

    private const val LIGHT_ID = 1234
    private const val LIGHT_TITLE = "My fancy light"
    private const val LIGHT_TYPE = DeviceTypes.TYPE_LIGHT
    private const val THERMOSTAT_ID = 5678
    private const val THERMOSTAT_TITLE = "My fancy thermostat"
    private const val THERMOSTAT_TYPE = DeviceTypes.TYPE_THERMOSTAT
 
    class MyCustomControlService : ControlsProviderService() {
      ...
    }
    

জাভা

    public class MyCustomJavaControlService extends ControlsProviderService {
 
    private final int LIGHT_ID = 1337;
    private final String LIGHT_TITLE = "My fancy light";
    private final int LIGHT_TYPE = DeviceTypes.TYPE_LIGHT;
    private final int THERMOSTAT_ID = 1338;
    private final String THERMOSTAT_TITLE = "My fancy thermostat";
    private final int THERMOSTAT_TYPE = DeviceTypes.TYPE_THERMOSTAT;
 
    ...
    }
    

নিয়ন্ত্রণের জন্য প্রকাশক তৈরি করুন

আপনি নিয়ন্ত্রণ তৈরি করার পরে, এটির একজন প্রকাশকের প্রয়োজন৷ প্রকাশক নিয়ন্ত্রণের অস্তিত্ব সম্পর্কে সিস্টেম UI-কে জানান। ControlsProviderService ক্লাসে দুটি প্রকাশক পদ্ধতি রয়েছে যা আপনাকে অবশ্যই আপনার অ্যাপ্লিকেশন কোডে ওভাররাইড করতে হবে:

  • createPublisherForAllAvailable() : আপনার অ্যাপে উপলব্ধ সমস্ত নিয়ন্ত্রণের জন্য একটি Publisher তৈরি করে। এই প্রকাশকের জন্য Control অবজেক্ট তৈরি করতে Control.StatelessBuilder() ব্যবহার করুন।
  • createPublisherFor() : প্রদত্ত নিয়ন্ত্রণগুলির একটি তালিকার জন্য একটি Publisher তৈরি করে, যেমন তাদের স্ট্রিং শনাক্তকারী দ্বারা চিহ্নিত করা হয়। এই Control অবজেক্টগুলি তৈরি করতে Control.StatefulBuilder ব্যবহার করুন, যেহেতু প্রকাশককে অবশ্যই প্রতিটি নিয়ন্ত্রণের জন্য একটি রাজ্য বরাদ্দ করতে হবে৷

প্রকাশক তৈরি করুন

যখন আপনার অ্যাপটি সিস্টেম UI-তে প্রথম নিয়ন্ত্রণ প্রকাশ করে, অ্যাপটি প্রতিটি নিয়ন্ত্রণের অবস্থা জানে না। স্থিতি পাওয়া একটি সময়সাপেক্ষ অপারেশন হতে পারে যা ডিভাইস প্রদানকারীর নেটওয়ার্কে অনেক হপ জড়িত। সিস্টেমে উপলব্ধ নিয়ন্ত্রণের বিজ্ঞাপন দিতে createPublisherForAllAvailable() পদ্ধতি ব্যবহার করুন। এই পদ্ধতিটি Control.StatelessBuilder বিল্ডার ক্লাস ব্যবহার করে, যেহেতু প্রতিটি নিয়ন্ত্রণের অবস্থা অজানা।

একবার নিয়ন্ত্রণগুলি Android UI-তে প্রদর্শিত হলে, ব্যবহারকারী পছন্দসই নিয়ন্ত্রণগুলি নির্বাচন করতে পারেন৷

একটি ControlsProviderService তৈরি করতে Kotlin coroutines ব্যবহার করতে, আপনার build.gradle এ একটি নতুন নির্ভরতা যোগ করুন:

গ্রোভি

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk9:1.6.4"
}

কোটলিন

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk9:1.6.4")
}

একবার আপনি আপনার গ্রেডল ফাইলগুলি সিঙ্ক করলে, createPublisherForAllAvailable() বাস্তবায়ন করতে আপনার Service নিম্নলিখিত স্নিপেট যোগ করুন :

কোটলিন

    class MyCustomControlService : ControlsProviderService() {
 
      override fun createPublisherForAllAvailable(): Flow.Publisher =
          flowPublish {
              send(createStatelessControl(LIGHT_ID, LIGHT_TITLE, LIGHT_TYPE))
              send(createStatelessControl(THERMOSTAT_ID, THERMOSTAT_TITLE, THERMOSTAT_TYPE))
          }
 
      private fun createStatelessControl(id: Int, title: String, type: Int): Control {
          val intent = Intent(this, MainActivity::class.java)
              .putExtra(EXTRA_MESSAGE, title)
              .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
          val action = PendingIntent.getActivity(
              this,
              id,
              intent,
              PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
          )
 
          return Control.StatelessBuilder(id.toString(), action)
              .setTitle(title)
              .setDeviceType(type)
              .build()
      }
 
          override fun createPublisherFor(controlIds: List): Flow.Publisher {
           TODO()
        }
 
        override fun performControlAction(
            controlId: String,
            action: ControlAction,
            consumer: Consumer
        ) {
            TODO()
        }
    }
    

জাভা

    public class MyCustomJavaControlService extends ControlsProviderService {
 
        private final int LIGHT_ID = 1337;
        private final String LIGHT_TITLE = "My fancy light";
        private final int LIGHT_TYPE = DeviceTypes.TYPE_LIGHT;
        private final int THERMOSTAT_ID = 1338;
        private final String THERMOSTAT_TITLE = "My fancy thermostat";
        private final int THERMOSTAT_TYPE = DeviceTypes.TYPE_THERMOSTAT;
 
        private boolean toggleState = false;
        private float rangeState = 18f;
        private final Map<String, ReplayProcessor> controlFlows = new HashMap<>();
 
        @NonNull
        @Override
        public Flow.Publisher createPublisherForAllAvailable() {
            List controls = new ArrayList<>();
            controls.add(createStatelessControl(LIGHT_ID, LIGHT_TITLE, LIGHT_TYPE));
            controls.add(createStatelessControl(THERMOSTAT_ID, THERMOSTAT_TITLE, THERMOSTAT_TYPE));
            return FlowAdapters.toFlowPublisher(Flowable.fromIterable(controls));
        }
 
        @NonNull
        @Override
        public Flow.Publisher createPublisherFor(@NonNull List controlIds) {
            ReplayProcessor updatePublisher = ReplayProcessor.create();
 
            controlIds.forEach(control -> {
                controlFlows.put(control, updatePublisher);
                updatePublisher.onNext(createLight());
                updatePublisher.onNext(createThermostat());
            });
 
            return FlowAdapters.toFlowPublisher(updatePublisher);
        }
    }
    

সিস্টেম মেনুতে সোয়াইপ করুন এবং ডিভাইস নিয়ন্ত্রণ বোতামটি সনাক্ত করুন, চিত্র 4 এ দেখানো হয়েছে:

ডিভাইস নিয়ন্ত্রণের জন্য সিস্টেম UI দেখানো একটি চিত্র
চিত্র 4. সিস্টেম মেনুতে ডিভাইস নিয়ন্ত্রণ।

ডিভাইস নিয়ন্ত্রণে ট্যাপ করলে একটি দ্বিতীয় স্ক্রিনে নেভিগেট হয় যেখানে আপনি আপনার অ্যাপ নির্বাচন করতে পারেন। একবার আপনি আপনার অ্যাপটি নির্বাচন করলে, আপনি দেখতে পাবেন কিভাবে আগের স্নিপেটটি আপনার নতুন নিয়ন্ত্রণগুলি দেখানো একটি কাস্টম সিস্টেম মেনু তৈরি করে, যেমন চিত্র 5 এ দেখানো হয়েছে:

একটি আলো এবং থার্মোস্ট্যাট নিয়ন্ত্রণ ধারণকারী সিস্টেম মেনু দেখানো একটি চিত্র৷
চিত্র 5. যোগ করার জন্য হালকা এবং তাপস্থাপক নিয়ন্ত্রণ।

এখন, আপনার Service নিম্নলিখিত যোগ করে createPublisherFor() পদ্ধতি প্রয়োগ করুন:

কোটলিন

    private val job = SupervisorJob()
    private val scope = CoroutineScope(Dispatchers.IO + job)
    private val controlFlows = mutableMapOf<String, MutableSharedFlow>()
 
    private var toggleState = false
    private var rangeState = 18f
 
    override fun createPublisherFor(controlIds: List): Flow.Publisher {
        val flow = MutableSharedFlow(replay = 2, extraBufferCapacity = 2)
 
        controlIds.forEach { controlFlows[it] = flow }
 
        scope.launch {
            delay(1000) // Retrieving the toggle state.
            flow.tryEmit(createLight())
 
            delay(1000) // Retrieving the range state.
            flow.tryEmit(createThermostat())
 
        }
        return flow.asPublisher()
    }
 
    private fun createLight() = createStatefulControl(
        LIGHT_ID,
        LIGHT_TITLE,
        LIGHT_TYPE,
        toggleState,
        ToggleTemplate(
            LIGHT_ID.toString(),
            ControlButton(
                toggleState,
                toggleState.toString().uppercase(Locale.getDefault())
            )
        )
    )
 
    private fun createThermostat() = createStatefulControl(
        THERMOSTAT_ID,
        THERMOSTAT_TITLE,
        THERMOSTAT_TYPE,
        rangeState,
        RangeTemplate(
            THERMOSTAT_ID.toString(),
            15f,
            25f,
            rangeState,
            0.1f,
            "%1.1f"
        )
    )
 
    private fun  createStatefulControl(id: Int, title: String, type: Int, state: T, template: ControlTemplate): Control {
        val intent = Intent(this, MainActivity::class.java)
            .putExtra(EXTRA_MESSAGE, "$title $state")
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        val action = PendingIntent.getActivity(
            this,
            id,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
 
        return Control.StatefulBuilder(id.toString(), action)
            .setTitle(title)
            .setDeviceType(type)
            .setStatus(Control.STATUS_OK)
            .setControlTemplate(template)
            .build()
    }
 
    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }
 
    

জাভা

    @NonNull
    @Override
    public Flow.Publisher createPublisherFor(@NonNull List controlIds) {
        ReplayProcessor updatePublisher = ReplayProcessor.create();
 
        controlIds.forEach(control -> {
            controlFlows.put(control, updatePublisher);
            updatePublisher.onNext(createLight());
            updatePublisher.onNext(createThermostat());
        });
 
        return FlowAdapters.toFlowPublisher(updatePublisher);
    }
 
    private Control createStatelessControl(int id, String title, int type) {
        Intent intent = new Intent(this, MainActivity.class)
                .putExtra(EXTRA_MESSAGE, title)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent action = PendingIntent.getActivity(
                this,
                id,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
 
        return new Control.StatelessBuilder(id + "", action)
                .setTitle(title)
                .setDeviceType(type)
                .build();
    }
 
    private Control createLight() {
        return createStatefulControl(
                LIGHT_ID,
                LIGHT_TITLE,
                LIGHT_TYPE,
                toggleState,
                new ToggleTemplate(
                        LIGHT_ID + "",
                        new ControlButton(
                                toggleState,
                                String.valueOf(toggleState).toUpperCase(Locale.getDefault())
                        )
                )
        );
    }
 
    private Control createThermostat() {
        return createStatefulControl(
                THERMOSTAT_ID,
                THERMOSTAT_TITLE,
                THERMOSTAT_TYPE,
                rangeState,
                new RangeTemplate(
                        THERMOSTAT_ID + "",
                        15f,
                        25f,
                        rangeState,
                        0.1f,
                        "%1.1f"
                )
        );
    }
 
    private  Control createStatefulControl(int id, String title, int type, T state, ControlTemplate template) {
        Intent intent = new Intent(this, MainActivity.class)
                .putExtra(EXTRA_MESSAGE, "$title $state")
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent action = PendingIntent.getActivity(
                this,
                id,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
 
        return new Control.StatefulBuilder(id + "", action)
                .setTitle(title)
                .setDeviceType(type)
                .setStatus(Control.STATUS_OK)
                .setControlTemplate(template)
                .build();
    }
    

এই উদাহরণে, createPublisherFor() পদ্ধতিতে আপনার অ্যাপটি যা করতে হবে তার একটি জাল বাস্তবায়ন রয়েছে: আপনার ডিভাইসের স্থিতি পুনরুদ্ধার করতে তার সাথে যোগাযোগ করুন এবং সিস্টেমে সেই স্থিতি প্রকাশ করুন।

createPublisherFor() পদ্ধতিটি নিম্নলিখিতগুলি করে প্রয়োজনীয় প্রতিক্রিয়াশীল স্ট্রীমস এপিআইকে সন্তুষ্ট করতে Kotlin coroutines এবং ফ্লো ব্যবহার করে:

  1. একটি Flow তৈরি করে।
  2. এক সেকেন্ড অপেক্ষা করে।
  3. স্মার্ট আলোর অবস্থা তৈরি করে এবং নির্গত করে।
  4. আরেকটি সেকেন্ডের জন্য অপেক্ষা করে।
  5. থার্মোস্ট্যাটের অবস্থা তৈরি করে এবং নির্গত করে।

কর্ম হ্যান্ডেল

performControlAction() পদ্ধতি সংকেত দেয় যখন ব্যবহারকারী একটি প্রকাশিত নিয়ন্ত্রণের সাথে ইন্টারঅ্যাক্ট করে। প্রেরিত ControlAction ধরন ক্রিয়া নির্ধারণ করে। প্রদত্ত নিয়ন্ত্রণের জন্য উপযুক্ত পদক্ষেপ করুন এবং তারপর Android UI-তে ডিভাইসের অবস্থা আপডেট করুন।

উদাহরণটি সম্পূর্ণ করতে, আপনার Service নিম্নলিখিত যোগ করুন:

কোটলিন

    override fun performControlAction(
        controlId: String,
        action: ControlAction,
        consumer: Consumer
    ) {
        controlFlows[controlId]?.let { flow ->
            when (controlId) {
                LIGHT_ID.toString() -> {
                    consumer.accept(ControlAction.RESPONSE_OK)
                    if (action is BooleanAction) toggleState = action.newState
                    flow.tryEmit(createLight())
                }
                THERMOSTAT_ID.toString() -> {
                    consumer.accept(ControlAction.RESPONSE_OK)
                    if (action is FloatAction) rangeState = action.newValue
                    flow.tryEmit(createThermostat())
                }
                else -> consumer.accept(ControlAction.RESPONSE_FAIL)
            }
        } ?: consumer.accept(ControlAction.RESPONSE_FAIL)
    }
    

জাভা

    @Override
    public void performControlAction(@NonNull String controlId, @NonNull ControlAction action, @NonNull Consumer consumer) {
        ReplayProcessor processor = controlFlows.get(controlId);
        if (processor == null) return;
 
        if (controlId.equals(LIGHT_ID + "")) {
            consumer.accept(ControlAction.RESPONSE_OK);
            if (action instanceof BooleanAction) toggleState = ((BooleanAction) action).getNewState();
            processor.onNext(createLight());
        }
        if (controlId.equals(THERMOSTAT_ID + "")) {
            consumer.accept(ControlAction.RESPONSE_OK);
            if (action instanceof FloatAction) rangeState = ((FloatAction) action).getNewValue()
            processor.onNext(createThermostat());
        }
    }
    

অ্যাপটি চালান, ডিভাইস কন্ট্রোল মেনু অ্যাক্সেস করুন এবং আপনার লাইট এবং থার্মোস্ট্যাট কন্ট্রোল দেখুন।

আলো এবং থার্মোস্ট্যাট নিয়ন্ত্রণ দেখানো একটি চিত্র
চিত্র 6. আলো এবং তাপস্থাপক নিয়ন্ত্রণ।