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

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

চিত্র ১. অ্যান্ড্রয়েড ইউআইতে ডিভাইস নিয়ন্ত্রণ স্থান।

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

ব্যবহারকারী ইন্টারফেস

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

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

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

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

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

এই বিভাগটি দেখায় কিভাবে ControlsProviderService তৈরি করতে হয়। এই পরিষেবাটি অ্যান্ড্রয়েড সিস্টেম UI কে বলে যে আপনার অ্যাপে এমন ডিভাইস নিয়ন্ত্রণ রয়েছে যা অ্যান্ড্রয়েড 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 নামে একটি নতুন Kotlin ফাইল তৈরি করুন এবং এটিকে Extend ControlsProviderService() করুন:

কোটলিন

    class MyCustomControlService : ControlsProviderService() {
        ...
    }
    

জাভা

    public class MyCustomJavaControlService extends ControlsProviderService {
        ...
    }
    

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

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

  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 বিল্ডার ক্লাস ব্যবহার করে, কারণ প্রতিটি নিয়ন্ত্রণের অবস্থা অজানা।

একবার অ্যান্ড্রয়েড ইউআইতে নিয়ন্ত্রণগুলি উপস্থিত হয়ে গেলে, ব্যবহারকারী পছন্দসই নিয়ন্ত্রণগুলি নির্বাচন করতে পারবেন।

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

খাঁজকাটা

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

কোটলিন

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

আপনার Gradle ফাইলগুলি সিঙ্ক করার পরে, 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 দেখানো একটি ছবি
চিত্র ৪. সিস্টেম মেনুতে ডিভাইস নিয়ন্ত্রণ।

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

আলো এবং থার্মোস্ট্যাট নিয়ন্ত্রণ সম্বলিত সিস্টেম মেনু দেখানো একটি ছবি
চিত্র ৫। আলো এবং তাপস্থাপক নিয়ন্ত্রণ যোগ করতে হবে।

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

কোটলিন

    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 এবং flows ব্যবহার করে প্রয়োজনীয় Reactive Streams API পূরণ করে নিম্নলিখিত কাজগুলি করে:

  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());
        }
    }
    

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

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