অ্যান্ড্রয়েড 11 এবং পরবর্তীতে, কুইক অ্যাক্সেস ডিভাইস কন্ট্রোল বৈশিষ্ট্য ব্যবহারকারীকে ডিফল্ট লঞ্চার থেকে তিনটি ইন্টারঅ্যাকশনের মধ্যে ব্যবহারকারীর সামর্থ্য থেকে লাইট, থার্মোস্ট্যাট এবং ক্যামেরার মতো বাহ্যিক ডিভাইসগুলি দ্রুত দেখতে এবং নিয়ন্ত্রণ করতে দেয়। ডিভাইস OEM বেছে নেয় তারা কোন লঞ্চার ব্যবহার করে। ডিভাইস এগ্রিগেটর—উদাহরণস্বরূপ, Google Home—এবং থার্ড-পার্টি ভেন্ডর অ্যাপ এই স্পেসে প্রদর্শনের জন্য ডিভাইস সরবরাহ করতে পারে। এই পৃষ্ঠাটি আপনাকে দেখায় যে কীভাবে এই স্পেসে ডিভাইস নিয়ন্ত্রণগুলি সরাতে হয় এবং সেগুলিকে আপনার নিয়ন্ত্রণ অ্যাপে লিঙ্ক করতে হয়।
এই সমর্থন যোগ করতে, একটি ControlsProviderService
তৈরি করুন এবং ঘোষণা করুন। পূর্বনির্ধারিত নিয়ন্ত্রণ প্রকারের উপর ভিত্তি করে আপনার অ্যাপ সমর্থন করে এমন নিয়ন্ত্রণগুলি তৈরি করুন এবং তারপর এই নিয়ন্ত্রণগুলির জন্য প্রকাশক তৈরি করুন৷
ইউজার ইন্টারফেস
ডিভাইসগুলি টেমপ্লেটেড উইজেট হিসাবে ডিভাইস নিয়ন্ত্রণের অধীনে প্রদর্শিত হয়। পাঁচটি ডিভাইস কন্ট্রোল উইজেট উপলব্ধ, যেমনটি নিম্নলিখিত চিত্রে দেখানো হয়েছে:
একটি উইজেট স্পর্শ করা এবং ধরে রাখা আপনাকে গভীর নিয়ন্ত্রণের জন্য অ্যাপে নিয়ে যায়। আপনি প্রতিটি উইজেটে আইকন এবং রঙ কাস্টমাইজ করতে পারেন, তবে সেরা ব্যবহারকারীর অভিজ্ঞতার জন্য, ডিফল্ট আইকন এবং রঙ ব্যবহার করুন যদি ডিফল্ট সেটটি ডিভাইসের সাথে মেলে।
পরিষেবা তৈরি করুন
এই বিভাগটি দেখায় কিভাবে 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 { ... }
সঠিক নিয়ন্ত্রণের ধরন নির্বাচন করুন
এপিআই কন্ট্রোল তৈরি করতে নির্মাতা পদ্ধতি প্রদান করে। নির্মাতাকে পপুলেট করতে, আপনি যে ডিভাইসটি নিয়ন্ত্রণ করতে চান এবং ব্যবহারকারী কীভাবে এটির সাথে ইন্টারঅ্যাক্ট করবেন তা নির্ধারণ করুন। নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
- নিয়ন্ত্রণ প্রতিনিধিত্ব করে ডিভাইসের ধরন চয়ন করুন।
DeviceTypes
ক্লাস হল সমস্ত সমর্থিত ডিভাইসের একটি গণনা। UI-তে ডিভাইসের জন্য আইকন এবং রং নির্ধারণ করতে টাইপ ব্যবহার করা হয়। - ব্যবহারকারী-মুখী নাম, ডিভাইসের অবস্থান-উদাহরণস্বরূপ, রান্নাঘর-এবং নিয়ন্ত্রণের সাথে যুক্ত অন্যান্য UI পাঠ্য উপাদান নির্ধারণ করুন।
- ব্যবহারকারীর মিথস্ক্রিয়া সমর্থন করার জন্য সেরা টেমপ্লেটটি বেছে নিন। কন্ট্রোলগুলিকে অ্যাপ্লিকেশন থেকে একটি
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> 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 এ দেখানো হয়েছে:
ডিভাইস নিয়ন্ত্রণে ট্যাপ করলে একটি দ্বিতীয় স্ক্রিনে নেভিগেট হয় যেখানে আপনি আপনার অ্যাপ নির্বাচন করতে পারেন। একবার আপনি আপনার অ্যাপটি নির্বাচন করলে, আপনি দেখতে পাবেন কিভাবে আগের স্নিপেটটি আপনার নতুন নিয়ন্ত্রণগুলি দেখানো একটি কাস্টম সিস্টেম মেনু তৈরি করে, যেমন চিত্র 5 এ দেখানো হয়েছে:
এখন, আপনার Service
নিম্নলিখিত যোগ করে createPublisherFor()
পদ্ধতি প্রয়োগ করুন:
কোটলিন
private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.IO + job) private val controlFlows = mutableMapOf>() 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.PublishercreatePublisherFor(@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 এবং ফ্লো ব্যবহার করে:
- একটি
Flow
তৈরি করে। - এক সেকেন্ড অপেক্ষা করে।
- স্মার্ট আলোর অবস্থা তৈরি করে এবং নির্গত করে।
- আরেকটি সেকেন্ডের জন্য অপেক্ষা করে।
- থার্মোস্ট্যাটের অবস্থা তৈরি করে এবং নির্গত করে।
কর্ম হ্যান্ডেল
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 Consumerconsumer) { 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()); } }
অ্যাপটি চালান, ডিভাইস কন্ট্রোল মেনু অ্যাক্সেস করুন এবং আপনার লাইট এবং থার্মোস্ট্যাট কন্ট্রোল দেখুন।
,অ্যান্ড্রয়েড 11 এবং পরবর্তীতে, কুইক অ্যাক্সেস ডিভাইস কন্ট্রোল বৈশিষ্ট্য ব্যবহারকারীকে ডিফল্ট লঞ্চার থেকে তিনটি ইন্টারঅ্যাকশনের মধ্যে ব্যবহারকারীর সামর্থ্য থেকে লাইট, থার্মোস্ট্যাট এবং ক্যামেরার মতো বাহ্যিক ডিভাইসগুলি দ্রুত দেখতে এবং নিয়ন্ত্রণ করতে দেয়। ডিভাইস OEM বেছে নেয় তারা কোন লঞ্চার ব্যবহার করে। ডিভাইস এগ্রিগেটর—উদাহরণস্বরূপ, Google Home—এবং থার্ড-পার্টি ভেন্ডর অ্যাপ এই স্পেসে প্রদর্শনের জন্য ডিভাইস সরবরাহ করতে পারে। এই পৃষ্ঠাটি আপনাকে দেখায় যে কীভাবে এই স্পেসে ডিভাইস নিয়ন্ত্রণগুলি সরাতে হয় এবং সেগুলিকে আপনার নিয়ন্ত্রণ অ্যাপে লিঙ্ক করতে হয়।
এই সমর্থন যোগ করতে, একটি ControlsProviderService
তৈরি করুন এবং ঘোষণা করুন। পূর্বনির্ধারিত নিয়ন্ত্রণ প্রকারের উপর ভিত্তি করে আপনার অ্যাপ সমর্থন করে এমন নিয়ন্ত্রণগুলি তৈরি করুন এবং তারপর এই নিয়ন্ত্রণগুলির জন্য প্রকাশক তৈরি করুন৷
ইউজার ইন্টারফেস
ডিভাইসগুলি টেমপ্লেটেড উইজেট হিসাবে ডিভাইস নিয়ন্ত্রণের অধীনে প্রদর্শিত হয়। পাঁচটি ডিভাইস কন্ট্রোল উইজেট উপলব্ধ, যেমনটি নিম্নলিখিত চিত্রে দেখানো হয়েছে:
একটি উইজেট স্পর্শ করা এবং ধরে রাখা আপনাকে গভীর নিয়ন্ত্রণের জন্য অ্যাপে নিয়ে যায়। আপনি প্রতিটি উইজেটে আইকন এবং রঙ কাস্টমাইজ করতে পারেন, তবে সেরা ব্যবহারকারীর অভিজ্ঞতার জন্য, ডিফল্ট আইকন এবং রঙ ব্যবহার করুন যদি ডিফল্ট সেটটি ডিভাইসের সাথে মেলে।
পরিষেবা তৈরি করুন
এই বিভাগটি দেখায় কিভাবে 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 { ... }
সঠিক নিয়ন্ত্রণের ধরন নির্বাচন করুন
এপিআই কন্ট্রোল তৈরি করতে নির্মাতা পদ্ধতি প্রদান করে। নির্মাতাকে পপুলেট করতে, আপনি যে ডিভাইসটি নিয়ন্ত্রণ করতে চান এবং ব্যবহারকারী কীভাবে এটির সাথে ইন্টারঅ্যাক্ট করবেন তা নির্ধারণ করুন। নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
- নিয়ন্ত্রণ প্রতিনিধিত্ব করে ডিভাইসের ধরন চয়ন করুন।
DeviceTypes
ক্লাস হল সমস্ত সমর্থিত ডিভাইসের একটি গণনা। UI-তে ডিভাইসের জন্য আইকন এবং রং নির্ধারণ করতে টাইপ ব্যবহার করা হয়। - ব্যবহারকারী-মুখী নাম, ডিভাইসের অবস্থান-উদাহরণস্বরূপ, রান্নাঘর-এবং নিয়ন্ত্রণের সাথে যুক্ত অন্যান্য UI পাঠ্য উপাদান নির্ধারণ করুন।
- ব্যবহারকারীর মিথস্ক্রিয়া সমর্থন করার জন্য সেরা টেমপ্লেটটি বেছে নিন। কন্ট্রোলগুলিকে অ্যাপ্লিকেশন থেকে একটি
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> 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 এ দেখানো হয়েছে:
ডিভাইস নিয়ন্ত্রণে ট্যাপ করলে একটি দ্বিতীয় স্ক্রিনে নেভিগেট হয় যেখানে আপনি আপনার অ্যাপ নির্বাচন করতে পারেন। একবার আপনি আপনার অ্যাপটি নির্বাচন করলে, আপনি দেখতে পাবেন কিভাবে আগের স্নিপেটটি আপনার নতুন নিয়ন্ত্রণগুলি দেখানো একটি কাস্টম সিস্টেম মেনু তৈরি করে, যেমন চিত্র 5 এ দেখানো হয়েছে:
এখন, আপনার Service
নিম্নলিখিত যোগ করে createPublisherFor()
পদ্ধতি প্রয়োগ করুন:
কোটলিন
private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.IO + job) private val controlFlows = mutableMapOf>() 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.PublishercreatePublisherFor(@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 এবং ফ্লো ব্যবহার করে:
- একটি
Flow
তৈরি করে। - এক সেকেন্ড অপেক্ষা করে।
- স্মার্ট আলোর অবস্থা তৈরি করে এবং নির্গত করে।
- আরেকটি সেকেন্ডের জন্য অপেক্ষা করে।
- থার্মোস্ট্যাটের অবস্থা তৈরি করে এবং নির্গত করে।
কর্ম হ্যান্ডেল
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 Consumerconsumer) { 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()); } }
অ্যাপটি চালান, ডিভাইস কন্ট্রোল মেনু অ্যাক্সেস করুন এবং আপনার লাইট এবং থার্মোস্ট্যাট কন্ট্রোল দেখুন।