Filter
-
Content Type
-
Category
Mobile/Wearable
Visual Display
Digital Appliance
Platform
Recommendations
Filter
Learn Code Lab
codelabimplement keyevent callback by mapping air actions objective learn how to implement keyevent callback on your s pen remote by mapping the air actions to a car racing game overview s pen connects via bluetooth low energy ble to a device and the s pen framework manages the connection ble events are converted by the s pen framework into keyevents before sending to the app apps are able to handle s pen events by reusing existing keyevent callback without adding other interfaces collecting and sending s pen remote events to apps the s pen framework collects and manages keyevents to be received by the app, and are defined in xml format before making them public below is the process of the s pen remote event handling and sending s pen remote event-defined keyevents to apps ble event is sent to the s pen framework the s pen framework checks for the foreground app and looks for the keyevent that the app made public the found keyevent is sent to the app's keyevent callback the app performs the actions defined in the keyevent set up your environment you will need the following java se development kit 10 jdk or later android studio latest version recommended samsung galaxy device with s pen remote capability galaxy tab s6 series or newer galaxy s22 ultra or newer galaxy fold3 or newer sample code here is a sample code for you to start coding in this code lab download it and start your learning experience! air actions sample code 6 4 mb start your project in android studio, click open an existing android studio project locate the android project from the directory and click ok implement remote actions check for the activity to handle the keyevent in a manifest file, androidmanifest xml add <intent-filter> and <meta-data> elements to that activity androidmanifest xml resource file defining remoteactions must be specified for <meta-data> <?xml version="1 0" encoding="utf-8"?> <manifest xmlns android="http //schemas android com/apk/res/android" package="com example spenremote racingcar"> <application <activity android name=" mainactivity" <intent-filter> <action android name="com samsung android support remote_action" /> </intent-filter> <meta-data android name="com samsung android support remote_action" android resource="@xml/remote_action_sample"/> </activity> </application> </manifest> noteonly one remoteaction per app is allowed at the moment if you define remoteactions to several activities, all other except one may be ignored create an xml file under res/xml/ name the file with the same name as the resource specified previously create the desired <action> elements in the xml file created as seen below xml has a root element of <remote-actions>, and may include several <action> elements in addition, each <action> contains information about id, label, priority, trigger_key, etc if you want to map a default action to a specific gesture, you need to add a <preference> element <?xml version="1 0" encoding="utf-8"?> <remote-actions version="1 2"> <action id="pause_or_resume" label="@string/pause_or_resume" priority="1" trigger_key="space"> <preference name="gesture" value="click"/> <preference name="button_only" value="true"/> </action> <action id="move_left" label="@string/move_car_left" priority="2" trigger_key="dpad_left"> <preference name="gesture" value="swipe_left"/> <preference name="motion_only" value="true"/> </action> <action id="move_right" label="@string/move_car_right" priority="3" trigger_key="dpad_right"> <preference name="gesture" value="swipe_right"/> <preference name="motion_only" value="true"/> </action> <action id="restart" label="@string/restart" priority="4" trigger_key="ctrl+r"> <preference name="gesture" value="circle_cw|circle_ccw"/> <preference name="motion_only" value="true"/> </action> </remote-actions> implement keyevent callback apply the keyevent callback to the activity where remoteactions have been declared it is recommended to handle the sent keyevent at onkeydown tiplearn more about keyevent callback in android developers add the following keyevent callback as seen below space key pause or resume the racing game left key move the car to left direction right key move the car to right direction ctrl + r key restart the racing game @override public boolean onkeydown int keycode, keyevent event { if keycode == keyevent keycode_space { racingcar playstate state = racingcar getplaystate ; if state == racingcar playstate playing { pause ; } else { resume ; } } else if keycode == keyevent keycode_dpad_left { movecarto racingcar pos_left ; } else if keycode == keyevent keycode_dpad_right { movecarto racingcar pos_right ; } else if event getmetastate & keyevent meta_ctrl_on != 0 && keycode == keyevent keycode_r { restart ; } return super onkeydown keycode, event ; } notepay attention to cases when the child view consumes the keyevent for example, if the edittext is focused on a screen where the edittext co-exists, most keyevents will be consumed for text inputs or a cursor movement and they may not be sent to the activities or container layouts on this screen, you must specify the key code or key combination that the child view cannot consume run the app now, everything is ready when you install your app, make sure that your app icon appears properly in the settings, settings > advanced features > s pen > air actions you can now control the car in the game using air actions you're done! congratulations! you have successfully achieved the goal of this code lab now, you can map air actions events on a game or app by yourself! if you're having trouble, you may download this file air actions complete code 6 4 mb
Learn Code Lab
codelabmeasure blood oxygen level on galaxy watch objective create a health app for galaxy watch, operating on wear os powered by samsung, utilizing samsung health sensor sdk to trigger and obtain blood oxygen level spo2 measurement results overview samsung health sensor sdk provides means of accessing and tracking health information contained in the health data storage its tracking service gives raw and processed sensor data such as accelerometer and body composition data sent by the samsung bioactive sensor the latest bioactive sensor of galaxy watch runs powerful health sensors such as photoplethysmogram ppg , electrocardiogram ecg , bioelectrical impedance analysis bia , sweat loss, and spo2 see samsung health sensor sdk descriptions for detailed information set up your environment you will need the following galaxy watch4 or newer android studio latest version recommended java se development kit jdk 11 or later sample code here is a sample code for you to start coding in this code lab download it and start your learning experience! measuring blood oxygen level sample code 146 3 kb connect your galaxy watch to wi-fi go to settings > connection > wi-fi and make sure that wi-fi is enabled from the list of available wi-fi networks, choose and connect to the same one as your pc turn on developer mode and adjust its settings on your watch, go to settings > about watch > software and tap on software version 5 times upon successful activation of developer mode, a toast message will display as on the image below afterwards, developer options will be visible under settings tap developer options and enable the following options adb debugging in developer options find wireless debugging turn on wireless debugging check always allow on this network and tap allow go back to developer options and click turn off automatic wi-fi notethere may be differences in settings depending on your one ui version connect your galaxy watch to android studio go to settings > developer options > wireless debugging and choose pair new device take note of the wi-fi pairing code, ip address & port in android studio, go to terminal and type adb pair <ip address> <port> <wi-fi pairing code> when prompted, tap always allow from this computer to allow debugging after successfully pairing, type adb connect <ip address of your watch> <port> upon successful connection, you will see the following message in android studio’s terminal connected to <ip address of your watch> now, you can run the app directly on your watch turn on developer mode for health platform on your watch go to settings > apps > health platform quickly tap health platform title for 10 times this enables developer mode and displays [dev mode] below the title to stop using developer mode, quickly tap health platform title for 10 times to disable it start your project in android studio, click open to open existing project locate the downloaded android project from the directory and click ok check capabilities for the device to track data with the samsung health sensor sdk, it must support a given tracker type – blood oxygen level to check this, get the list of available tracker types and verify that the tracker is on the list in the connectionmanager java file, navigate to the isspo2available function, use a provided healthtrackingservice object to create a healthtrackercapability instance, send it to the checkavailabletrackers function, and assign its result to the availabletrackers list gettrackingcapability returns a healthtrackercapability instance in the healthtrackingservice object healthtrackingservicehealthtrackingservice initiates a connection to samsung's health tracking service and provides a healthtracker instance to track a healthtrackertype public healthtrackercapability gettrackingcapability provide a healthtrackercapability instance to get a supporting health tracker type list /****************************************************************************************** * [practice 1] check capabilities to confirm spo2 availability * * ---------------------------------------------------------------------------------------- * * hint replace todo 1 with java code * get healthtrackercapability object from healthtrackingservice * send the object to checkavailabletrackers ******************************************************************************************/ public boolean isspo2available healthtrackingservice healthtrackingservice { if healthtrackingservice == null return false; list<healthtrackertype> availabletrackers = null; //"todo 1" if availabletrackers == null return false; else return availabletrackers contains healthtrackertype spo2_on_demand ; } check connection error resolution using samsung health sensor sdk api, resolve any error when connecting to health tracking service in the connectionmanager java file, navigate to the processtrackerexception function, and check if the provided healthtrackerexception object has a resolution assign the result to hasresolution variable hasresolution function in the healthtrackerexception object checks if the api can fix the error healthtrackerexceptionhealthtrackerexception contains error codes and checks the error's resolution if there is a resolution, solving the error is available by calling resolve activity boolean hasresolution checks whether the given error has a resolution /******************************************************************************************* * [practice 2] resolve healthtrackerexception error * * ----------------------------------------------------------------------------------------- * * hint replace todo 2 with java code * call hasresolution on healthtrackerexception object ******************************************************************************************/ public void processtrackerexception healthtrackerexception e { boolean hasresolution = false; //"todo 2" if hasresolution e resolve callingactivity ; if e geterrorcode == healthtrackerexception old_platform_version || e geterrorcode == healthtrackerexception package_not_installed observerupdater getobserverupdater notifyconnectionobservers r string novalidhealthplatform ; else observerupdater getobserverupdater notifyconnectionobservers r string connectionerror ; log e tag, "could not connect to health tracking service " + e getmessage ; } initialize spo2 tracker before the measurement starts, initialize the spo2 tracker by obtaining the proper health tracker object in the spo2listener java file, navigate to the init function using the provided healthtrackingservice object, create an instance of the spo2 tracker and assign it to the spo2tracker object gethealthtracker with healthtrackertype spo2_on_demand as an argument will create a healthtracker instance healthtrackingservicehealthtrackingservice initiates a connection to samsung's health tracking service and provides a healthtracker instance to track a healthtrackertype healthtracker gethealthtracker healthtrackertype healthtrackertype provides a healthtracker instance for the given healthtrackertype /******************************************************************************************* * [practice 3] initialize spo2 tracker * * ---------------------------------------------------------------------------------------- * * hint replace todo 3 with java code * initialize spo2tracker with proper samsung health sensor sdk functionality * call gethealthtracker on healthtrackingservice object * use healthtrackertype spo2_on_demand as an argument ******************************************************************************************/ void init healthtrackingservice healthtrackingservice { //"todo 3" } perform measurement for the client app to start obtaining the data through the sdk, it has to set a listener method on the healthtracker the application setups the listener when the user taps on the measure button each time there is new data, the listener callback receives it after the measurement is completed, the listener has to be disconnected due to battery drain, on-demand measurement should not last more than 30 seconds the measurement is cancelled if the final value is not delivered in time note that the sensor needs a few seconds to warm up and provide correct values, which adds to the overall measurement time the blood oxygen level values come in the ondatareceived callback of trackereventlistener in spo2listener java file, you can see the code for reading the value private final healthtracker trackereventlistener spo2listener = new healthtracker trackereventlistener { @override public void ondatareceived @nonnull list<datapoint> list { for datapoint data list { updatespo2 data ; } } }; private void updatespo2 datapoint data { int status = data getvalue valuekey spo2set status ; int spo2value = 0; if status == measurement_completed spo2value = data getvalue valuekey spo2set spo2 ; observerupdater getobserverupdater notifytrackerobservers status, spo2value ; } run unit tests for your convenience, you can find an additional unit tests package this lets you verify your code changes even without using a physical watch see instructions below on how to run unit tests right click on com samsung health spo2tracking test and execute run 'tests in 'com samsung health spo2tracking'' command if you completed all the tasks correctly, you can see that all the unit tests passed successfully run the app after building the apk, you can run the application on a connected device to measure blood oxygen level right after the app is started, it requests for user permission allow the app to receive data from the body sensors afterwards, it shows the application's main screen to get the blood oxygen level, tap on the measure button to stop the measurement, tap on the stop button you're done! congratulations! you have successfully achieved the goal of this code lab now, you can create a health app that measures blood oxygen level by yourself! if you're having trouble, you may download this file measuring blood oxygen level complete code 146 2 kb to learn more about samsung health, visit developer samsung com/health
Learn Code Lab
codelabintegrate in-app payment into merchant apps using samsung pay sdk objective learn how to integrate in-app payment with your merchant apps using samsung pay sdk partnership request to use the samsung pay sdk, you must become an official samsung partner once done, you can fully utilize this code lab you can learn more about the partnership process by visiting samsung pay page, here in samsung developers notein accordance with the applicable samsung partner agreements, this code lab covers setup and use of the samsung pay sdk for purposes of integrating the samsung pay app with partner apps the use cases and corresponding code samples included are representative examples only and should not be construed as either recommended or required overview the samsung pay sdk is an application framework for integrating selected samsung pay features with android-based partner apps on samsung devices in-app payment, which allows customers to pay for products and services with samsung pay, is one of the operations supported alongside push provisioning and open favorite cards partner apps can leverage the samsung pay sdk to perform different operations ― push provisioning and open favorite cards for issuers; in-app payment for merchants key components include partner app app developed by merchant or issuer for making online or offline payments and provisioning payment cards through samsung pay samsung pay sdk sdk integrated into the partner app for direct communication with samsung pay samsung pay app pay app with which the samsung pay sdk communicates financial network comprises the payment gateways, acquirers, card associations, and issuers that participate in transaction processing under agreement with the merchant most common use case for in-app payment the merchant app allows the user to make payments with samsung pay upon user selection of the samsung pay option, the merchant app calls the apis included in the samsung pay sdk to initiate a transaction with the samsung pay app the samsung pay app responds with the tokenized payment information necessary to complete the transaction the merchant app forwards this payment information to the designated payment gateway pg , either directly through the merchant's web server or indirectly via the samsung-pg interface server for standard transaction processing for more detailed information, see the official samsung pay sdk programming guide set up your environment you will need the following samsung wallet or samsung pay app depending on the country a compatible mobile device with android marshmallow 6 0 or android api level 23 or later android os versions samsung pay sdk android studio latest version recommended java se development kit jdk 11 or later sample code here is a sample code for you to start coding in this code lab download it and start your learning experience! in-app payment sample code 1 90 mb integrate the samsung pay sdk with your app the following steps comprise the general process for integrating the samsung pay sdk with your app sign up for the samsung pay developers site by clicking sign up and register your samsung account or create it if you don't already have one , then sign in follow the on-screen instructions for adding your app and creating a new service to generate the service id you'll need to use in your project download the samsung pay sdk by going to resources > sdk download add the samsung pay sdk jar file samsungpay jar to your android project using android studio or file explorer develop your partner app with the required api calls and callbacks for samsung pay integration upload a release version of your app to the samsung pay developers site for approval upon samsung approval, publish your partner app to the google play store and samsung galaxy apps notethe service id is already provided in the sample code for this code lab however, this service id is for test purposes only and cannot be used for an actual application or service using the provided test service id enforces your app to use the fixed properties below service id 0915499788d6493aa3a038 package name com test beta pay app version 1 0/ 1 or higher start your project after downloading the sample code containing the project files, in android studio click open to open existing project locate the downloaded android project sampleonlinepay from the directory and click ok add the samsungpaysdk_2 18 00_release jar file from the sdk's libs folder to your android project's libs folder go to gradle scripts > build gradle module sampleonlinepay app and enter the following to the dependencies block implementation files 'libs/samsungpaysdk_2 18 00_release jar' if the target sdk version is 30 android 11 or the r-os , you must include the following <queries> element in androidmanifest xml <queries> <package android name="com samsung android spay" /> </queries> configure the api level as of sdk version 1 4, enhanced version control management has been introduced to improve backward compatibility and handle api dependency from country and service type for example, if a partner integrates the latest sdk—for instance, api level 2 18—but continues to use apis based on level 1 4, the partner app remains compatible with samsung pay apps supporting api level 1 4 without upgrading the samsung pay app implement the following in application tag of androidmanifest xml <meta-data android name="spay_sdk_api_level" android value="2 17" /> // most recent sdk version is recommended to leverage the latest apis add an xml layout and modify the activity next, replace the xml layout in res > layout > activity_main xml this layout shows the sample item information such as image, name, and price <?xml version="1 0" encoding="utf-8"?> <layout xmlns tools="http //schemas android com/tools" xmlns app="http //schemas android com/apk/res-auto" xmlns android="http //schemas android com/apk/res/android"> <androidx constraintlayout widget constraintlayout android layout_width="match_parent" android layout_height="match_parent" tools context=" mainactivity"> <imageview android id="@+id/imageview" android layout_width="350dp" android layout_height="184dp" android layout_margintop="100dp" app layout_constraintend_toendof="parent" app layout_constraintstart_tostartof="parent" app layout_constrainttop_totopof="parent" android src="@drawable/galaxy_s23_ultra_image"/> <imageview android id="@+id/samsung_pay_button" android layout_width="wrap_content" android layout_height="75dp" app layout_constraintbottom_tobottomof="parent" app layout_constraintend_toendof="parent" app layout_constraintstart_tostartof="parent" android src="@drawable/pay_rectangular_full_screen_black" android visibility="invisible"/> <textview android id="@+id/textview" android layout_width="wrap_content" android layout_height="wrap_content" android layout_margintop="10dp" android text="galaxy s23 ultra" android textsize="16sp" android textstyle="bold" app layout_constraintend_toendof="parent" app layout_constraintstart_tostartof="parent" app layout_constrainttop_tobottomof="@+id/imageview" /> <textview android id="@+id/textview2" android layout_width="wrap_content" android layout_height="wrap_content" android layout_margintop="5dp" android text="$1,199 00" android textsize="14sp" app layout_constraintend_toendof="parent" app layout_constrainthorizontal_bias="0 517" app layout_constraintstart_tostartof="parent" app layout_constrainttop_tobottomof="@+id/textview" /> </androidx constraintlayout widget constraintlayout> </layout> since you added a data binding layout, you need to inflate the xml file differently go to java > com > test > beta > pay > mainactivity kt, and declare the databinding variable in the mainactivity class private lateinit var databinding activitymainbinding replace the standard setcontentview declaration with the data binding version inside the oncreate method databinding = databindingutil setcontentview this, r layout activity_main check samsung pay status in the mainactivity, create the samsungpay instance to determine if the device supports samsung pay and if the samsung pay button can be displayed as the user's payment option, check the samsung pay status samsungpay requires a valid partnerinfo from the merchant app, which consists of service id and service type during onboarding, the samsung pay developers site assigns the service id and service type in the mainactivity, declare the partnerinfo variable private lateinit var partnerinfo partnerinfo then, set the partnerinfo in the oncreate method val bundle = bundle bundle putstring spaysdk partner_service_type, spaysdk servicetype inapp_payment tostring partnerinfo = partnerinfo service_id, bundle after setting partnerinfo, call the getsamsungpaystatus method via updatesamsungpaybutton function inside the oncreate method updatesamsungpaybutton the getsamsungpaystatus method of the samsungpay class must be called before using any other feature in the samsung pay sdk write the updatesamsungpaybutton function as follows private fun updatesamsungpaybutton { val samsungpay = samsungpay this, partnerinfo samsungpay getsamsungpaystatus object statuslistener { override fun onsuccess status int, bundle bundle { when status { spaysdk spay_ready -> { databinding samsungpaybutton visibility = view visible // perform your operation } spaysdk spay_not_ready -> { // samsung pay is supported but not fully ready // if extra_error_reason is error_spay_app_need_to_update, // call gotoupdatepage // if extra_error_reason is error_spay_setup_not_completed, // call activatesamsungpay databinding samsungpaybutton visibility = view invisible } spaysdk spay_not_allowed_temporally -> { // if extra_error_reason is error_spay_connected_with_external_display, // guide user to disconnect it databinding samsungpaybutton visibility = view invisible } spaysdk spay_not_supported -> { databinding samsungpaybutton visibility = view invisible } else -> databinding samsungpaybutton visibility = view invisible } } override fun onfail errorcode int, bundle bundle { databinding samsungpaybutton visibility = view invisible toast maketext applicationcontext, "getsamsungpaystatus fail", toast length_short show } } } tipfor the list and detailed definition of status codes such as spay_ready, refer to checking samsung pay status noteas of sdk version 1 5, if the device has android lollipop 5 1 android api level 22 or earlier versions, the getsamsungpaystatus api method returns a spay_not supported status code merchant apps using sdk 1 4 or earlier must check their app's android version activate the samsung pay app the samsungpay class provides an api method called activatesamsungpay to activate the samsung pay app on the same device where the partner app is running if the getsamsungpaystatus returns spay_not_ready and the extra_error_reason is error_spay_setup_not_complete, the partner app needs to display an appropriate message to the user then, call activatesamsungpay to launch samsung pay app and request the user to sign in in updatesamsungpaybutton function, add the code to call activatesamsungpay method via doactivatesamsungpay function when the status is spay_not_ready // if extra_error_reason is error_spay_setup_not_completed, // call activatesamsungpay val extraerror = bundle getint samsungpay extra_error_reason if extraerror == samsungpay error_spay_setup_not_completed { doactivatesamsungpay spaysdk servicetype inapp_payment tostring } create the doactivatesamsungpay function as below private fun doactivatesamsungpay servicetype string { val bundle = bundle bundle putstring samsungpay partner_service_type, servicetype val partnerinfo = partnerinfo service_id, bundle val samsungpay = samsungpay this, partnerinfo samsungpay activatesamsungpay } create a transaction request upon successfully initializing the samsungpay class, the merchant app should create a transaction request with payment information samsung pay offers two types of online payment sheet―normal and custom the normal payment sheet has fixed display items ― items, tax, and shipping the custom payment sheet offers more dynamic controls for customizing the ui, together with additional customer order and payment data for this code lab, use the custom payment sheet and populate the fields in customsheetpaymentinfo to initiate a payment transaction /* * make user's transaction details * the merchant app should send paymentinfo to samsung pay via the applicable samsung pay sdk api method for the operation * being invoked * upon successful user authentication, samsung pay returns the "payment info" structure and the result string * the result string is forwarded to the pg for transaction completion and will vary based on the requirements of the pg used * the code example below illustrates how to populate payment information in each field of the paymentinfo class */ private fun maketransactiondetailswithsheet customsheetpaymentinfo? { val brandlist = brandlist val extrapaymentinfo = bundle val customsheet = customsheet customsheet addcontrol makeamountcontrol return customsheetpaymentinfo builder setmerchantid "123456" setmerchantname "sample merchant" setordernumber "amz007mar" // if you want to enter address, please refer to the javadoc // reference/com/samsung/android/sdk/samsungpay/v2/payment/sheet/addresscontrol html setaddressinpaymentsheet customsheetpaymentinfo addressinpaymentsheet do_not_show setallowedcardbrands brandlist setcardholdernameenabled true setrecurringenabled false setcustomsheet customsheet setextrapaymentinfo extrapaymentinfo build } private fun makeamountcontrol amountboxcontrol { val amountboxcontrol = amountboxcontrol amount_control_id, "usd" amountboxcontrol additem product_item_id, "item", 1199 00, "" amountboxcontrol additem product_tax_id, "tax", 5 0, "" amountboxcontrol additem product_shipping_id, "shipping", 1 0, "" amountboxcontrol setamounttotal 1205 00, amountconstants format_total_price_only return amountboxcontrol } private val brandlist arraylist<spaysdk brand> get { val brandlist = arraylist<spaysdk brand> brandlist add spaysdk brand visa brandlist add spaysdk brand mastercard brandlist add spaysdk brand americanexpress brandlist add spaysdk brand discover return brandlist } request payment with a custom payment sheet the startinapppaywithcustomsheet method of the paymentmanager class is applied to request payment using a custom payment sheet in samsung pay when you call the startinapppaywithcustomsheet method, a custom payment sheet is displayed on the merchant app screen from there, the user can select a registered card for payment and change the billing and shipping addresses as necessary the payment sheet lasts for 5 minutes after calling the api if the time limit expires, the transaction fails in the mainactivity class, declare the paymentmanager variable private lateinit var paymentmanager paymentmanager then, in oncreate , set an onclicklistener method before calling the updatesamsungpaybutton function to trigger the startinapppaywithcustomsheet function when the samsungpaybutton is clicked databinding samsungpaybutton setonclicklistener { startinapppaywithcustomsheet } lastly, create a function to call startinapppaywithcustomsheet method of the paymentmanager class /* * paymentmanager startinapppaywithcustomsheet is a method to request online in-app payment with samsung pay * partner app can use this method to make in-app purchase using samsung pay from their * application with custom payment sheet */ private fun startinapppaywithcustomsheet { paymentmanager = paymentmanager applicationcontext, partnerinfo paymentmanager startinapppaywithcustomsheet maketransactiondetailswithsheet , transactioninfolistener } /* * customsheettransactioninfolistener is for listening callback events of online in-app custom sheet payment * this is invoked when card is changed by the user on the custom payment sheet, * and also with the success or failure of online in-app payment */ private val transactioninfolistener paymentmanager customsheettransactioninfolistener = object paymentmanager customsheettransactioninfolistener { // this callback is received when the user changes card on the custom payment sheet in samsung pay override fun oncardinfoupdated selectedcardinfo cardinfo, customsheet customsheet { /* * called when the user changes card in samsung pay * newly selected cardinfo is passed and partner app can update transaction amount based on new card if needed * call updatesheet method this is mandatory */ paymentmanager updatesheet customsheet } override fun onsuccess response customsheetpaymentinfo, paymentcredential string, extrapaymentdata bundle { /* * you will receive the payloads shown below in paymentcredential parameter * the output paymentcredential structure varies depending on the pg you're using and the integration model direct, indirect with samsung */ toast maketext applicationcontext, "onsuccess ", toast length_short show } // this callback is received when the online payment transaction has failed override fun onfailure errorcode int, errordata bundle? { toast maketext applicationcontext, "onfailure ", toast length_short show } } run the app after building the apk, you can run the sample merchant app and see how it connects to samsung pay upon clicking the button at the bottom of the screen to thoroughly test the sample app, you must add at least one card to the samsung pay app you're done! congratulations! you have successfully achieved the goal of this code lab now, you can integrate in-app payment with your app by yourself! if you face any trouble, you may download this file in-app payment complete code 2 26 mb to learn more about developing apps for samsung pay devices, visit developer samsung com/pay
Learn Code Lab
codelabtransfer heart rate data from galaxy watch to a mobile device objective create a health app for galaxy watch, operating on wear os powered by samsung, to measure heart rate and inter-beat interval ibi , send data to a paired android phone, and create an android application for receiving data sent from a paired galaxy watch overview with this code lab, you can measure various health data using samsung health sensor sdk and send it to a paired android mobile device for further processing samsung health sensor sdk tracks various health data, but it cannot save or send collected results meanwhile, wearable data layer allows you to synchronize data from your galaxy watch to an android mobile device using a paired mobile device allows the data to be more organized by taking advantage of a bigger screen and better performance see samsung health sensor sdk descriptions for detailed information set up your environment you will need the following galaxy watch4 or newer android mobile device android studio latest version recommended java se development kit jdk 17 or later sample code here is a sample code for you to start coding in this code lab download it and start your learning experience! heart rate data transfer sample code 213 7 kb connect your galaxy watch to wi-fi go to settings > connection > wi-fi and make sure that the wi-fi is enabled from the list of available wi-fi networks, choose and connect to the same one as your pc turn on developer mode and adjust its settings on your watch, go to settings > about watch > software and tap on software version 5 times upon successful activation of developer mode, a toast message will display as on the image below afterwards, developer options will be visible under settings tap developer options and enable the following options adb debugging in developer options find wireless debugging turn on wireless debugging check always allow on this network and tap allow go back to developer options and click turn off automatic wi-fi notethere may be differences in settings depending on your one ui version connect your galaxy watch to android studio go to settings > developer options > wireless debugging and choose pair new device take note of the wi-fi pairing code, ip address & port in android studio, go to terminal and type adb pair <ip address> <port> <wi-fi pairing code> when prompted, tap always allow from this computer to allow debugging after successfully pairing, type adb connect <ip address of your watch> <port> upon successful connection, you will see the following message in the terminal connected to <ip address of your watch> now, you can run the app directly on your watch turn on developer mode for health platform to use the app, you need to enable developer mode in the health platform on your watch go to settings > apps > health platform quickly tap health platform title for 10 times this enables developer mode and displays [dev mode] below the title to stop using developer mode, quickly tap health platform title for 10 times to disable it set up your android device click on the following links to setup your android device enable developer options run apps on a hardware device connect the galaxy watch with you samsung mobile phone start your project in android studio, click open to open an existing project locate the downloaded android project hrdatatransfer-code-lab from the directory and click ok you should see both devices and applications available in android studio as in the screenshots below initiate heart rate tracking noteyou may refer to this blog post for more detailed analysis of the heart rate tracking using samsung health sensor sdk first, you need to connect to the healthtrackingservice to do that create connectionlistener, create healthtrackingservice object by invoking healthtrackingservice connectionlistener, context invoke healthtrackingservice connectservice when connected to the health tracking service, check the tracking capability the available trackers may vary depending on samsung health sensor sdk, health platform versions or watch hardware version use the gettrackingcapability function of the healthtrackingservice object obtain heart rate tracker object using the function healthtrackingservice gethealthtracker healthtrackertype heart_rate_continuous define event listener healthtracker trackereventlistener, where the heart rate values will be collected start tracking the tracker starts collecting heart rate data when healthtracker seteventlistener updatelistener is invoked, using the event listener collect heart data from the watch the updatelistener collects datapoint instances from the watch, which contains a collection of valuekey objects those objects contain heart rate, ibi values, and ibi statuses there's always one value for heart rate while the number of ibi values vary from 0-4 both ibi value and ibi status lists have the same size go to wear > java > data > com samsung health hrdatatransfer > data under ibidataparsing kt, provide the implementation for the function below /******************************************************************************* * [practice 1] get list of valid inter-beat interval values from a datapoint * - return arraylist<int> of valid ibi values validibilist * - if no ibi value is valid, return an empty arraylist * * var ibivalues is a list representing ibivalues up to 4 * var ibistatuses is a list of their statuses has the same size as ibivalues ------------------------------------------------------------------------------- * - hints * use local function isibivalid status, value to check validity of ibi * ****************************************************************************/ fun getvalidibilist datapoint datapoint arraylist<int> { val ibivalues = datapoint getvalue valuekey heartrateset ibi_list val ibistatuses = datapoint getvalue valuekey heartrateset ibi_status_list val validibilist = arraylist<int> //todo 1 return validibilist } check data sending capabilities for the watch once the heart rate tracker can collect data, set up the wearable data layer so it can send data to a paired android mobile device wearable data layer api provides data synchronization between wear os and android devices noteto know more about wearable data layer api, go here to determine if a remote mobile device is available, the wearable data layer api uses concept of capabilities not to be confused with samsung health sensor sdk’s tracking capabilities, providing information about available tracker types using the wearable data layer's capabilityclient, you can get information about nodes remote devices being able to consume messages from the watch go to wear > java > com samsung health hrdatatransfer > data in capabilityrepositoryimpl kt, and fill in the function below the purpose of this part is to filter all capabilities represented by allcapabilities argument by capability argument and return the set of nodes set<node> having this capability later on, we need those nodes to send the message to them /************************************************************************************** * [practice 2] check capabilities for reachable remote nodes devices * - return a set of node objects out of all capabilities represented by 2nd function * argument, having the capability represented by 1st function argument * - return empty set if no node has the capability -------------------------------------------------------------------------------------- * - hints * you might want to use filtervalues function on the given allcapabilities map * ***********************************************************************************/ override suspend fun getnodesforcapability capability string, allcapabilities map<node, set<string>> set<node> { //todo 2 } encode message for the watch before sending the results of the heart rate and ibi to the paired mobile device, you need to encode the message into a string for sending data to the paired mobile device we are using wearable data layer api’s messageclient object and its function sendmessage string nodeid, string path, byte[] message go to wear > java > com samsung health hrdatatransfer > domain in sendmessageusecase kt, fill in the function below and use json format to encode the list of results arraylist<trackeddata> into a string /*********************************************************************** * [practice 3] - encode heart rate & inter-beat interval into string * - encode function argument trackeddata into json format * - return the encoded string ----------------------------------------------------------------------- * - hint * use json encodetostring function **********************************************************************/ fun encodemessage trackeddata arraylist<trackeddata> string { //todo 3 } notetrackeddata is an object, containing data received from heart rate tracker’s single datapoint object @serializable data class trackeddata var hr int, var ibi arraylist<int> = arraylist run unit tests for your convenience, you will find an additional unit tests package this will let you verify your code changes even without using a physical watch or mobile device see the instruction below on how to run unit tests right click on com samsung health hrdatatransfer test , and execute run 'tests in 'com samsung health hrdatatransfer" command if you have completed all the tasks correctly, you will see all the unit tests pass successfully run the app after building the apks, you can run the applications on your watch to measure heart rate and ibi values, and on your mobile device to collect the data from your watch once the app starts, allow the app to receive data from the body sensors afterwards, it shows the application's main screen to get the heart rate and ibi values, tap the start button tap the send button to send the data to your mobile device notethe watch keeps last ~40 values of heart rate and ibi you’re done! congratulations! you have successfully achieved the goal of this code lab now, you can create a health app on a watch to measure heart rate and ibi, and develop a mobile app that receives that health data! if you face any trouble, you may download this file heart rate data transfer complete code 213 9 kb to learn more about samsung health, visit developer samsung com/health
Learn Code Lab
codelabcontrol a smart bulb objective control a smart light bulb and change its color using bixby home studio overview bixby home studio bhs provides a simple and optimized way for accessing and controlling devices connected to your smartthings account you can quickly create complex diagrams and condition-based flows with bhs's user-friendly graphical user interface gui any device compatible with smartthings can be adjusted, controlled, and updated through bixby home studio for more information, visit getting started with bixby home studio set up your environment you will need the following samsung and smartthings account same email address smart rgb light bulb added to smartthings account virtual switch from smartthings labs if a smart rgb light bulb is not available a go to smartthings app b in the menu, select labs c choose virtual switch and click + to add a virtual switch d enter the name of virtual switch, location, and room notewhen you use a virtual switch, you can only create metadata and test the turning on and off functionality however, a physical smart rgb light bulb is necessary for testing other functions of this code lab activity, such as changing the light bulb color to red smartthings labs feature is available only on android app in us, canada, uk, india, and south korea start your project go to bhs bixbydevelopers com and sign in using your samsung account create a new project select your smartthings location and smart rgb light bulb or virtual switch for the device click create metadata from scratch then, click next choose powerswitch under bixby voice category select the powerswitch-turnoff and powerswitch-turnon voice intents click next input a project name and click done use a sample graph to switch on the bulb sample graphs are various example action flows that you can explore to learn more about the different voice intents, nodes, and smartthings capabilities you can use these sample graphs as starter points for your own devices each sample graph generically handles specific capabilities covered under various user utterances through the different voice intents for example, the turn on device sample graph works for any device it covers a variety of user utterances such as "turn on air conditioner ", "turn on fan ", "turn on speaker ”, and so on follow the steps below to use the turn on device sample graph to switch on the device go to voice intents > powerswitch-turnon > graph click the sample graphs icon on the left sidebar menu to show all the available sample graphs scroll down to see the turn on device sample graph or find it using the search bar drag and drop the sample graph into your powerswitch-turnon graph editor click try it to turn on your light bulb noteif you're using a virtual switch, it will turn on, but you won't be able to see the switch itself however, you can see the state of the virtual switch change from off to on in the smartthings app turn off the light bulb and add an alternative response the turn on device sample graph functions to switch on the device when the start node triggers the command node this graph can be modified to reverse its function, to do that copy the nodes from the powerswitch-turnon graph to the powerswitch-turnoff graph editor click the command node to open the node configuration pane and change the command from on to off right-click on the command node and change its comment to turn off device click try it to turn off the device after the command is performed, the response is either success or execution failed to make the light bulb more responsive, design the graph to provide different responses depending on whether the light bulb is already off or currently on a click the raw button and delete the existing code in the raw graph b copy and paste the following json into it and click add [{"nodeid" "5b648da1-a2c3-4912-baff-a559b968070e","nodever" "1 0","nodetype" "capabilityattribute","isstateful" true,"group" null,"inputports" {"device" {"nodes" [],"portinfo" null}},"triggerports" {"success" {"nodes" ["ccf1cbb8-c99b-439f-8246-bc9e7b7abfbf"],"portinfo" null},"failure" {"nodes" [],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {"attribute" {"datatype" "datatype schema afcapabilityattribute","datavalue" {"component" "main","capability" "switch","attribute" "switch","property" {"name" "value","datatype" "datatype primitive afstring"}}},"required" {"datatype" "datatype primitive afboolean","datavalue" true}},"styles" {"x" 415,"y" 360}},{"nodeid" "ccf1cbb8-c99b-439f-8246-bc9e7b7abfbf","nodever" "1 0","nodetype" "equalcomparison","isstateful" true,"group" null,"inputports" {"leftvalue" {"nodes" ["5b648da1-a2c3-4912-baff-a559b968070e"],"portinfo" null},"rightvalue" {"nodes" ["8d9bf8ec-7cb1-4ffe-b4c0-b0424d394027"],"portinfo" null}},"triggerports" {"true" {"nodes" ["593250c4-9c19-4155-8f90-1318f9484aab"],"portinfo" null},"false" {"nodes" ["a9c4d152-eb0d-45d2-a2bd-20217de6fee6"],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {"operator" {"datatype" "datatype operator equalcomparisonoperator","datavalue" "equalto"}},"styles" {"x" 585,"y" 332}},{"nodeid" "8d9bf8ec-7cb1-4ffe-b4c0-b0424d394027","nodever" "1 0","nodetype" "constant","isstateful" true,"group" null,"inputports" {},"triggerports" {},"valueports" {},"triggerinports" {},"configurations" {"value" {"datatype" "datatype primitive afstring","datavalue" "on"}},"styles" {"x" 415,"y" 500}},{"nodeid" "a9c4d152-eb0d-45d2-a2bd-20217de6fee6","nodever" "1 0","nodetype" "responsefeaturealreadyset","isstateful" true,"group" null,"inputports" {},"triggerports" {},"valueports" {},"triggerinports" {},"configurations" {},"styles" {"x" 635,"y" 480}}] c four nodes were added to the graph an attribute node that receives and passes an on or off value; a constant node with on as its value; an equal comparison node that compares if the attribute value is equal to the constant value; and a response already set node d rewire the graph to make it work properly by clicking the line coming from the start node and pressing the delete key e create a new line from the start node and connect it to the attribute node's trigger port f connect the equal comparison node's true port to the command node's trigger port g click the align button a couple of times to automatically organize the graph h then, click try it while the device is already off or already on, to observe the different responses change the light bulb's color based on time the command node has two capabilities that can adjust the color of light bulb, such as colorcontrol and colortemperature in this step, use these command node capabilities together with the get current datetime node and get datetime attributes node to set the light bulb's color to red or warm, if the current date time is 8 00 pm or later otherwise, the light bulb's color remains blue add the following json into the powerswitch-turnon graph [{"nodeid" "a31659e2-68fc-42b6-8076-01c2cb9fec23","nodever" "1 0","nodetype" "getcurrentdatetime","isstateful" true,"group" null,"inputports" {"__zoneid" {"nodes" [],"portinfo" null}},"triggerports" {"main" {"nodes" ["ea58c225-7d40-45b9-85d6-d8d941de9b2e"],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {},"styles" {"x" 715,"y" 280}},{"nodeid" "ea58c225-7d40-45b9-85d6-d8d941de9b2e","nodever" "1 0","nodetype" "getdatetimeattributes","isstateful" true,"group" null,"inputports" {"input" {"nodes" ["a31659e2-68fc-42b6-8076-01c2cb9fec23"],"portinfo" null}},"triggerports" {"main" {"nodes" ["880416f6-d288-4b97-b763-2abd46bf2737"],"portinfo" null}},"valueports" {"seconds" {"name" "seconds"},"month" {"name" "month"},"hour" {"name" "hour"},"year" {"name" "year"},"minutes" {"name" "minutes"},"timestampinseconds" {"name" "timestampinseconds"},"day" {"name" "day"}},"triggerinports" {},"configurations" {},"styles" {"x" 815,"y" 280}},{"nodeid" "880416f6-d288-4b97-b763-2abd46bf2737","nodever" "1 0","nodetype" "comparablecomparison","isstateful" true,"group" null,"inputports" {"leftvalue" {"nodes" ["gr //node/ea58c225-7d40-45b9-85d6-d8d941de9b2e/value/hour"],"portinfo" null},"rightvalue" {"nodes" ["606796bc-d8ea-4421-942d-91544271615d"],"portinfo" null}},"triggerports" {"true" {"nodes" ["b2ba65ab-5e3e-4615-8d3a-79015a03d7bc"],"portinfo" null},"false" {"nodes" [],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {"operator" {"datatype" "datatype operator comparablecomparisonoperator","datavalue" "greaterthanorequalto"}},"styles" {"x" 975,"y" 320}},{"nodeid" "606796bc-d8ea-4421-942d-91544271615d","nodever" "1 0","nodetype" "constant","isstateful" true,"group" null,"inputports" {},"triggerports" {},"valueports" {},"triggerinports" {},"configurations" {"value" {"datatype" "datatype primitive afinteger","datavalue" 20}},"styles" {"x" 815,"y" 420}},{"nodeid" "2b22b1a1-b9cb-4881-a861-3bf74ccd7847","nodever" "1 0","nodetype" "capabilitycommand","isstateful" true,"group" null,"inputports" {"device" {"nodes" [],"portinfo" null},"1 color" {"nodes" ["2389baa9-db45-4eb3-a40c-1166bf1e620f"],"portinfo" {"datatypes" ["undefined"],"minitems" 1,"maxitems" 1,"iscustomport" true}}},"triggerports" {"success" {"nodes" ["a31659e2-68fc-42b6-8076-01c2cb9fec23"],"portinfo" null},"failure" {"nodes" [],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {"commands" {"datatype" "datatype util aflist","datavalue" [{"datatype" "datatype schema afcapabilitycommand","datavalue" {"component" "main","capability" "colorcontrol","command" "setcolor","arguments" [{"datatype" "datatype schema afcommandargument","datavalue" {"name" "color","optional" false,"datatype" "datatype primitive afjsonobject"}}]}}]}},"styles" {"x" 590,"y" 274}},{"nodeid" "2389baa9-db45-4eb3-a40c-1166bf1e620f","nodever" "1 0","nodetype" "constant","isstateful" true,"group" null,"inputports" {},"triggerports" {},"valueports" {},"triggerinports" {},"configurations" {"value" {"datatype" "datatype primitive afjsonobject","datavalue" {"hue" 55,"saturation" 55}}},"styles" {"x" 675,"y" 440}},{"nodeid" "b2ba65ab-5e3e-4615-8d3a-79015a03d7bc","nodever" "1 0","nodetype" "capabilitycommand","isstateful" true,"group" null,"inputports" {"device" {"nodes" [],"portinfo" null},"1 temperature" {"nodes" ["4d02fcda-df99-4c75-8b0a-73bb67933acd"],"portinfo" {"datatypes" ["undefined"],"minitems" 1,"maxitems" 1,"iscustomport" true}}},"triggerports" {"success" {"nodes" [],"portinfo" null},"failure" {"nodes" [],"portinfo" null}},"valueports" {},"triggerinports" {},"configurations" {"commands" {"datatype" "datatype util aflist","datavalue" [{"datatype" "datatype schema afcapabilitycommand","datavalue" {"component" "main","capability" "colortemperature","command" "setcolortemperature","arguments" [{"datatype" "datatype schema afcommandargument","datavalue" {"name" "temperature","optional" false,"datatype" "datatype primitive afinteger"}}]}}]}},"styles" {"x" 1115,"y" 380}},{"nodeid" "4d02fcda-df99-4c75-8b0a-73bb67933acd","nodever" "1 0","nodetype" "constant","isstateful" true,"group" null,"inputports" {},"triggerports" {},"valueports" {},"triggerinports" {},"configurations" {"value" {"datatype" "datatype primitive afinteger","datavalue" 500}},"styles" {"x" 975,"y" 478}}] rewire the graph as follows a delete the wire that connects command switch node's success port and response success node's trigger port b connect the command switch node's success port to the command colorcontrol node's trigger port c connect the command colortemperature node's success port to the response success node's trigger port d connect the numerical comparison node's false port to the response success node's trigger port noteadd a constant node with time zone, for example america/new_york, as string value if you want to test this section based on your local time click align then, click try it to see how the light bulb color change based on time you're done! congratulations! you have successfully achieved the goal of this code lab now, you can control a smart light bulb using bixby home studio if you face any trouble, you may download this file control bulb complete code 25 72 kb notewatch this short clip to quickly know how to navigate your way in this code lab and to see how easy it is to use bixby home studio to learn more about bixby, visit developer samsung com/bixby
Learn Code Lab
codelabbuild a health app with steps from samsung health and its connected wearables objective create a step counter application for android devices, utilizing the samsung health data sdk to read steps data collected by the samsung health app overview samsung health offers various features to monitor user health data such as their daily step activity with the samsung health data sdk, android applications can easily access collected data, including steps recorded over a specific period or from a certain device you can retrieve steps data collected by samsung health, obtain the total number of steps taken within the day, and the total number of steps per hour, and apply local time filters to refine your queries effectively set up your environment you will need the following android studio latest version recommended java se development kit jdk 17 or later android mobile device compatible with the latest samsung health version sample code here is a sample code for you to start coding in this code lab download it and start your learning experience! health data steps sample code 573 9 kb set up your android device click on the following links to set up your android device enable developer options run apps on a hardware device activate samsung health's developer mode to enable the developer mode in the samsung health app, follow these steps go to settings > about samsung health then, tap the version number quickly 10 times or more if you are successful, the developer mode new button is shown tap developer mode new and choose on now, you can test your app with samsung health notethe samsung health developer mode is only intended for testing or debugging your application it is not for application users start your project in android studio click open to open existing project locate the downloaded android project mysteps from the directory and click ok check gradle settings before using the samsung health data sdk library, certain configurations are necessary these steps are already applied in the sample code provided the samsung-health-data-api-1 0 0b1 aar library is added to the app\libs folder, and included as a dependency in the module-level build gradle file in the same file, the gson library is also added as a dependency dependencies { implementation filetree mapof "dir" to "libs", "include" to listof "* aar" implementation libs gson } next, the kotlin-parcelize plugin is applied plugins { id "kotlin-parcelize" } lastly, the following entries are also added in the gradle > libs version toml file [versions] gson = "2 10 1" parcelize = “1 9 0” [libraries] gson = { module = "com google code gson gson", version ref = "gson" } [plugins] parcelize = { id = “org jetbrains kotlin plugin parcelize”, version ref = ”parcelize” } request steps data permissions noteyou can access data from samsung health by obtaining a healthdatastore object using the healthdataservice getstore appcontext method to read data from samsung health, you need to acquire proper permissions from the app user each health data type has its own permission additionally, separate permissions are required for reading and writing operations the user must grant the following permissions in the app steps for read operation steps_goal for read operation when launching the application, it is important to verify if the necessary permissions have already been granted this can be achieved through the library function healthdatastore getgrantedpermissions permissions set<permission> set<permission> go to app > kotlin+java > com samsung health mysteps domain in the arepermissionsgrantedusecase kt file, navigate to the permissions object and create the permissions needed to read the steps and steps goal data from samsung health /**************************************************************************** * [practice 1] create permission set to receive step data * * make permissions set down below contain two permission * com samsung android sdk health data permission permission objects of types * - 'datatypes steps' of 'accesstype read' * - 'datatypes steps_goal of 'accesstype read' ****************************************************************************/ object permissions { //todo 1 val permissions = emptyset<permission> } if the permissions are not granted, invoke an ask-for-permissions view the special function provided by the library is called from mainactivity, where the context is an activity's context val result = healthdatastore requestpermissions permissions, context after invoking the function, the app user sees the following pop-up upon starting the application if the user does not consent to read their steps data, the application displays a message explaining why this authorization is vital for the app to function properly notepermissions can be granted or revoked at any time by tapping the more button on the toolbar and selecting the connect to samsung health tab once the user grants the necessary permissions, you can proceed with retrieving the step data from the healthdatastore retrieve steps data from samsung health understand how to retrieve step goal a step goal is a target number of steps set by an individual to achieve within a day this can be set in the samsung health app by navigating to steps > settings > set target check the readlaststepgoal function in readstepgoalfromtodayusecase kt to know how to retrieve the most recent step goal from samsung health @throws healthdataexception class private suspend fun readlaststepgoal int { val startdate = localdate now val enddate = localdate now plusdays 1 log i tag, "startdate $startdate; enddate $enddate" val readrequest = datatype stepsgoaltype last requestbuilder setlocaldatefilter localdatefilter of startdate, enddate build val result = healthdatastore aggregatedata readrequest var stepgoal = 0 result datalist foreach { data -> log i tag, "step goal ${data value}" log i tag, "data starttime ${data starttime}" log i tag, "data endtime ${data endtime}" data value? let { stepgoal = it } } return stepgoal } the function readlaststepgoal retrieves the most recent step goal from samsung health first, it filters the data by setting the startdate and enddate to the current date and the next day respectively using a localdatefilter next, the function builds a request using the datatype stepsgoaltype last constant to retrieve the most recent value and specifies the date range using the setlocaldatefilter method the request is then executed by calling the aggregatedata function of the healthdatastore once the data is fetched, the function loops through each entry and extracts the step goal value finally, it returns the step goal value as the result collect today's total number of steps to verify if the user reached their daily step goal, get the number of steps taken from midnight until the current time perform this calculation by creating a generic function that calculates the total number of steps within a specified time frame then, set the start time as the beginning of today and the end time as the current timestamp total is an aggregate operation that obtains the sum of steps to achieve this task, use the following healthdatastore getgrantedpermissions permissions set<permission> set containsall elements collection<@unsafevariance e> aggregaterequest it represents a request for an aggregation query over time it is used to run aggregate operations like total and last for healthdatapoint localtimefilter filter with a localdatetime type time interval as a condition the time interval is represented as local date time companion function of starttime localdatetime?, endtime localdatetime? creates a localtimefilter with starttime and endtime aggregaterequest localtimebuilder<t> provides a convenient and safe way to set the fields and create an aggregaterequest setlocaltimefilter localtimefilter localtimefilter sets the local time filter of the request in readstepsfromatimerangeusecase kt, navigate to the function getaggregaterequestbuilder and filter today's steps /*************************************************************************** * [practice 2] - create a read request builder to obtain steps from given * time range * collecting steps from a period of time is an aggregate operation which * sums up all the steps from that period * in this exercise you need to * - create a localtimefilter with starttime and endtime for the * aggregaterequest * - apply the filter to the aggregaterequest * ------------------------------------------------------------------------- * - hint * use localtimefilter of to create a time filter for the request **************************************************************************/ fun getaggregaterequestbuilder starttime localdatetime, endtime localdatetime aggregaterequest<long> { val aggregaterequest = datatype stepstype total requestbuilder build // todo 2 return aggregaterequest } a list of aggregated data is received as a result of the request in this example, it's a single-item list containing the total number of steps taken from the beginning of the day to the present moment with the given code, you can iterate over the list and check if the value of the analyzed aggregateddata element is not null if so, assign it to the stepcount variable however, if the value is empty, the code returns a value of 0, indicating that no steps were recorded val result = healthdatastore aggregatedata aggregaterequest var stepcount = 0l result datalist foreach { aggregateddata -> aggregateddata value? let { stepcount = it } } obtain the number of steps for each hour after setting up the functions to fetch steps data from samsung health and aggregating the data to calculate the total step count, you need to obtain the total number of steps for each hour and visualize the steps the user took during every hour of the day to achieve this, utilize the aggregate operation sum of steps , but this time incorporate additional filtering grouping by hour aggregaterequest it represents a request for an aggregation query over time it is used to run aggregate operations like total and last on healthdatapoint localtimefilter filter with a localdatetime type time interval as a condition the time interval is represented as local date time companion function of starttime localdatetime?, endtime localdatetime? creates a localtimefilter with starttime and endtime localtimegroup grouped time interval with a pair of localtimegroupunit and multiplier this means that the grouping is applied to intervals as much as multiplier in local date and time companion function of timegroupunit localtimegroupunit, multiplier int creates a localtimegroup with the given timegroupunit and multiplier localtimebuilder<t> provides a convenient and safe way to set the fields and create an aggregaterequest setlocaltimefilterwithgroup localtimefilter localtimefilter?, localtimegroup localtimegroup? sets the local time filter with the local time group of the request in readgroupedstepsbytimerangeusecase kt, navigate to the getaggregaterequestbuilder function obtain the total number of steps from every hour by creating two variables one to specify the time range using localtimefilter of and another to define the grouping using localtimegroup of by combining these variables, you can set an aggregate request that retrieves the desired data /************************************************************************ * [practice 3] - create an aggregate request for steps from given period * of time * for this, datatype steps grouped by hour is needed * in this exercise you need to * - create an aggregate request, with grouping and time filters, * for filters' parameters use the method's arguments * - return the request * ---------------------------------------------------------------------- * - hint * use setlocaltimefilterwithgroup function to apply time and grouping * filters to the request builder ***********************************************************************/ fun getaggregaterequestbuilder startdatetime localdatetime, enddatetime localdatetime, localtimegroupunit localtimegroupunit, multiplier int aggregaterequest<long> { val aggregaterequest = datatype stepstype total requestbuilder build // todo 3 return aggregaterequest } to apply local time filtering with the given group, use the localtimefilter and localtimegroup classes the localtimegroup consists of a localtimegroupunit, which in this case is hourly, and a multiplier you can also group by other time periods such as daily, weekly, monthly, minutely, and yearly since you want data from every hour period, use a multiplier value of 1 the returned data from the request is a list, where each item represents a grouped value healthdatastore only returns values for periods when the step count is greater than zero the code below shows that by iterating over the returned datalist and adding non-null groupeddata to the output steplist, you can obtain the aggregated value of steps for each hour of the day val result = healthdatastore aggregatedata aggregaterequest val steplist arraylist<groupeddata> = arraylist result datalist foreach { aggregateddata -> var stepcount = 0l aggregateddata value? let { stepcount = it } val starttime = aggregateddata starttime atzone zoneid systemdefault val groupeddata = groupeddata stepcount, starttime tolocaldatetime steplist add groupeddata } noteevery usage of samsung health data sdk might throw a healthdataexception such exceptions are thrown from every backend function up the call stack and handled in viewmodel the healthdataexception has four possible subclasses an example is resolvableplatformexception, which means it can be automatically resolved by invoking resolvableplatformexception resolve activitycontext the reason for such an exception is, for instance, when samsung health app is not installed on the device resolving it results in opening samsung health page in the app store run unit tests for your convenience, an additional unit tests package is provided this package lets you verify your code changes even without using a physical device right-click on com samsung health mysteps test and select run 'tests in 'com samsung health mysteps' if you completed all the tasks correctly, you can see that all the unit tests passed successfully run the app after building the apk, you can run the app on a connected device to read your steps data once the app starts, allow all permissions to read steps data from samsung health and tap done afterwards, the app's main screen appears, displaying the daily summary of steps taken, target, and steps by hour swipe down to sync the latest data from samsung health you can scroll down to steps by hour to see the hourly breakdown you're done! congratulations! you have successfully achieved the goal of this code lab now, you can create a mobile health app that reads samsung health steps count data by yourself! if you are having trouble, you may download this file health data steps complete code 573 4 kb to learn more about samsung health, visit developer samsung com/health
Learn Code Lab
codelabimplement flex mode on an unreal engine game objective learn how to implement flex mode on an unreal engine game using android jetpack windowmanager and raw java native interface jni overview the flexible hinge and glass display on galaxy foldable devices, such as the galaxy z fold4 and galaxy z flip4, let the phone remains propped open while you use apps when the phone is partially folded, it will go into flex mode apps will reorient to fit the screen, letting you watch videos or play games without holding the phone for example, you can set the device on a flat surface, like on a table, and use the bottom half of the screen to navigate unfold the phone to use the apps in full screen mode, and partially fold it again to return to flex mode to provide users with a convenient and versatile foldable experience, developers need to optimize their apps to meet the flex mode standard set up your environment you will need the following epic games launcher with unreal engine 4 or later visual studio or any source code editor samsung galaxy foldable device galaxy z fold2, z fold3, or newer galaxy z flip, z flip3, or newer remote test lab if physical device is not available requirements samsung account java runtime environment jre 7 or later with java web start internet environment where port 2600 is available create and set up your project after launching unreal engine from the epic games launcher, follow the steps below to start your project in the select or create new project window, choose games as a new project category and click next select third person as template, then click next to proceed noteyou can implement flex mode on any template or existing projects and use this code lab activity as a reference in the project settings window, set the following type of project c++ target platform mobile / tablet performance characteristics scalable 3d or 2d real-time raytracing raytracing disabled include an additional content pack no starter content project name tutorial_project click create project wait for the engine to finish loading and open the unreal editor once the project is loaded, go to edit > project settings > platforms > android click the configure now button if the project is not yet configured for the android platform then, proceed with the following apk packaging and build settings a apk packaging set target sdk version to 30 set orientation to full sensor change the maximum supported aspect ratio to 2 8 aspect ratio of galaxy z fold3 in decimal to prevent black bars from appearing on the cover display leave it if your game does not need to use the cover display enable use display cutout region?, to prevents black bars at the edge of the main screen otherwise, leave it unchecked b build disable support opengl es3 1 and enable support vulkan notecurrently, there is a problem with opengl es and the split-screen system being investigated the only option right now is to turn off opengl es and use vulkan instead enable native resize event the resize event of a game when switching between displays is disabled in the engine by default however, this behavior can be easily enabled by setting android enablenativeresizeevent=1 in the deviceprofile currently, the only way to create a profile for foldable devices is by creating a specific rule for each device to save time in this code lab, enable the native resize event for all android devices instead locate and open the tutorial_project > config folder in file explorer inside the config folder, create a new folder named android create a new file called androiddeviceprofiles ini and open this file in a text editor, such as visual studio copy below deviceprofile code to the newly created androiddeviceprofiles ini file [deviceprofiles] +deviceprofilenameandtypes=android,android [android deviceprofile] devicetype=android baseprofilename= +cvars=r mobilecontentscalefactor=1 0 +cvars=slate absoluteindices=1 +cvars=r vulkan delayacquirebackbuffer=2 +cvars=r vulkan robustbufferaccess=1 +cvars=r vulkan descriptorsetlayoutmode=2 ; don't enable vulkan by default specific device profiles can set this cvar to 0 to enable vulkan +cvars=r android disablevulkansupport=1 +cvars=r android disablevulkansm5support=1 ; pf_b8g8r8a8 +cvars=r defaultbackbufferpixelformat=0 +cvars=android enablenativeresizeevent=1 ; previewallowlistcvars and previewdenylistcvars are arrays of cvars that are included or excluded from being applied in mobile preview ; if any previewallowlistcvars is set, cvars are denied by default previewallowlistcvars=none this is a copy of the default android deviceprofile from the existing basedeviceprofiles ini file but with the enabled nativeresizeevent console variable cvars notethis step is not required when you only want to implement flex mode yet, it's recommended, to allow applications to run seamlessly from main to cover display without stretching and squashing the game, by enabling the nativeresizeevent create a new plugin and import the foldablehelper foldablehelper is a java file that you can use in different projects it provides an interface to the android jetpack windowmanager library, enabling application developers to support new device form factors and multi-window environments before proceeding, read how to use jetpack windowmanager in android game dev and learn the details of how foldablehelper uses windowmanager library to retrieve information about the folded state of the device flat for normal mode and half-opened for flex mode , window size, and orientation of the fold on the screen download the foldablehelper java file here foldablehelper java 5 64 kb to import the foldablehelper java file to the project, follow the steps below go to edit > plugins in the unreal editor click the new plugin button and select blank to create a blank plugin in the name field, type foldables_tutorial and click the create plugin button in file explorer, locate and open tutorial_project > plugins folder go to plugins > foldables_tutorial > source> foldables_tutorial > private and create a new folder called java copy the foldablehelper java file into java folder open the tutorial_project sln file in visual studio in the same private folder path, add a new filter called java right-click on the java filter and click add > existing item locate the foldablehelper java file, then click add to include this java file in the build modify java activity to use foldablehelper unreal plugin language upl is a simple xml-based language created by epic games for manipulating xml and returning strings using upl, you can utilize the foldablehelper java file by modifying the java activity and related gradle files as follows in visual studio, right-click on source > foldables_tutorial folder, then click add > new item > web > xml file xml create an xml file called foldables_tutorial_upl xml ensure that the file location is correct before clicking add in the newly created xml file, include the foldablehelper java file in the build by copying the java folder to the build directory <root xmlns android="http //schemas android com/apk/res/android"> <prebuildcopies> <copydir src="$s plugindir /private/java" dst="$s builddir /src/com/samsung/android/gamedev/foldable" /> </prebuildcopies> set up the gradle dependencies in the build gradle file by adding the following in the xml file <buildgradleadditions> <insert> dependencies { implementation filetree dir 'libs', include ['* jar'] implementation "org jetbrains kotlin kotlin-stdlib-jdk8 1 6 0" implementation "androidx core core 1 7 0" implementation "androidx core core-ktx 1 7 0" implementation "androidx appcompat appcompat 1 4 0" implementation "androidx window window 1 0 0" implementation "androidx window window-java 1 0 0" } android{ compileoptions{ sourcecompatibility javaversion version_1_8 targetcompatibility javaversion version_1_8 } } </insert> </buildgradleadditions> next, modify the gameactivity <gameactivityimportadditions> <insert> <!-- package name of foldablehelper --> import com samsung android gamedev foldable foldablehelper; </insert> </gameactivityimportadditions> <gameactivityoncreateadditions> <insert> foldablehelper init this ; </insert> </gameactivityoncreateadditions> <gameactivityonstartadditions> <insert> foldablehelper start this ; </insert> </gameactivityonstartadditions> <gameactivityonstopadditions> <insert> foldablehelper stop ; </insert> </gameactivityonstopadditions> </root> gameactivityimportadditions adds the com samsung android gamedev foldable foldablehelper into the gameactivity with the existing imports gameactivityoncreateadditions adds the code to the oncreate method inside the gameactivity gameactivityonstartadditions adds the code to the onstart method inside the gameactivity gameactivityonstopadditions adds the code to the onstop method inside the gameactivity save the xml file then, ensure that the engine uses the upl file by modifying the foldables_tutorial build cs script, located in the same folder as the foldables_tutorial_upl xml file after the dynamicallyloadedmodulenames addrange call, add the following if target platform == unrealtargetplatform android { additionalpropertiesforreceipt add "androidplugin", moduledirectory + "\\foldables_tutorial_upl xml" ; } this means that the game engine will use the upl file if the platform is android otherwise, the foldablehelper won’t work implement a storage struct the next thing to implement is a struct, the native version of java’s foldablelayoutinfo class to store the data retrieved from the java code using a struct, do the following in content browser of unreal editor, right-click on c++ classes > add/import content then, click new c++ class select none for the parent class and click next name the new class as foldablelayoutinfo assign it to the foldables_tutorial plugin then, click create class delete the created foldablelayoutinfo cpp file and only keep its header file in the header file called foldablelayoutinfo h, set up a struct to store all needed data from the windowmanager #pragma once #include "core h" enum efoldstate { undefined_state, flat, half_opened }; enum efoldorientation { undefined_orientation, horizontal, vertical }; enum efoldocclusiontype { undefined_occlusion, none, full }; struct ffoldablelayoutinfo { efoldstate state; efoldorientation orientation; efoldocclusiontype occlusiontype; fvector4 foldbounds; fvector4 currentmetrics; fvector4 maxmetrics; bool isseparating; ffoldablelayoutinfo state efoldstate undefined_state , orientation efoldorientation undefined_orientation , occlusiontype efoldocclusiontype undefined_occlusion , foldbounds -1, -1, -1, -1 , currentmetrics -1, -1, -1, -1 , maxmetrics -1, -1, -1, -1 , isseparating false { } }; implement jni code to implement jni, create a new c++ class with no parent and name it foldables_helper assign the class to the same plugin, then modify the c++ header and source files as follows in the created header file foldables_helper h , include foldablelayoutinfo h #include "foldablelayoutinfo h" then, declare a multicast_delegate to serve as a listener for passing the data from the java implementation to the rest of the engine declare_multicast_delegate_oneparam fonlayoutchangeddelegate, ffoldablelayoutinfo ; lastly, set up the methods and member variables class foldables_tutorial_api ffoldables_helper { public static void init ; static bool haslistener; static fonlayoutchangeddelegate onlayoutchanged; }; moving to the source file foldables_helper cpp , set up the definitions for the methods and member variables created in the header file bool ffoldables_helper haslistener = false; fonlayoutchangeddelegate ffoldables_helper onlayoutchanged; void ffoldables_helper init { haslistener = true; } now, in the same source file, create the native version of the onlayoutchanged function created in the foldablehelper java file since the java onlayoutchanged function only works on android, surround the function with an #if directive to ensure that it compiles only on android #if platform_android #endif within this directive, copy the code below to use the jni definition of the java onlayoutchanged function extern "c" jniexport void jnicall java_com_samsung_android_gamedev_foldable_foldablehelper_onlayoutchanged jnienv * env, jclass clazz, jobject jfoldablelayoutinfo { create the ffoldablelayoutinfo to store the data retrieved from java ffoldablelayoutinfo result; retrieve the field ids of the foldablelayoutinfo and rect objects created in the java file //java foldablelayoutinfo field ids jclass jfoldablelayoutinfocls = env->getobjectclass jfoldablelayoutinfo ; jfieldid currentmetricsid = env->getfieldid jfoldablelayoutinfocls, "currentmetrics", "landroid/graphics/rect;" ; jfieldid maxmetricsid = env->getfieldid jfoldablelayoutinfocls, "maxmetrics", "landroid/graphics/rect;" ; jfieldid hingeorientationid = env->getfieldid jfoldablelayoutinfocls, "hingeorientation", "i" ; jfieldid stateid = env->getfieldid jfoldablelayoutinfocls, "state", "i" ; jfieldid occlusiontypeid = env->getfieldid jfoldablelayoutinfocls, "occlusiontype", "i" ; jfieldid isseparatingid = env->getfieldid jfoldablelayoutinfocls, "isseparating", "z" ; jfieldid boundsid = env->getfieldid jfoldablelayoutinfocls, "bounds", "landroid/graphics/rect;" ; jobject currentmetricsrect = env->getobjectfield jfoldablelayoutinfo, currentmetricsid ; //java rect object field ids jclass rectcls = env->getobjectclass currentmetricsrect ; jfieldid leftid = env->getfieldid rectcls, "left", "i" ; jfieldid topid = env->getfieldid rectcls, "top", "i" ; jfieldid rightid = env->getfieldid rectcls, "right", "i" ; jfieldid bottomid = env->getfieldid rectcls, "bottom", "i" ; retrieve the current windowmetrics and store it in the ffoldablelayoutinfo as an fintvector4 // currentmetrics int left = env->getintfield currentmetricsrect, leftid ; int top = env->getintfield currentmetricsrect, topid ; int right = env->getintfield currentmetricsrect, rightid ; int bottom = env->getintfield currentmetricsrect, bottomid ; // store currentmetrics rect to fvector4 result currentmetrics = fintvector4{ left, top, right, bottom }; do the same for the other variables in the java foldablelayoutinfo // maxmetrics jobject maxmetricsrect = env->getobjectfield jfoldablelayoutinfo, maxmetricsid ; left = env->getintfield maxmetricsrect, leftid ; top = env->getintfield maxmetricsrect, topid ; right = env->getintfield maxmetricsrect, rightid ; bottom = env->getintfield maxmetricsrect, bottomid ; //store maxmetrics rect to fvector4 result maxmetrics = fintvector4{ left, top, right, bottom }; int hingeorientation = env->getintfield jfoldablelayoutinfo, hingeorientationid ; int state = env->getintfield jfoldablelayoutinfo, stateid ; int occlusiontype = env->getintfield jfoldablelayoutinfo, occlusiontypeid ; bool isseparating = env->getbooleanfield jfoldablelayoutinfo, isseparatingid ; // store the values to an object for unreal result orientation = tenumasbyte<efoldorientation> hingeorientation + 1 ; result state = tenumasbyte<efoldstate> state + 1 ; result occlusiontype = tenumasbyte<efoldocclusiontype> occlusiontype + 1 ; result isseparating = isseparating; // boundsrect jobject boundsrect = env->getobjectfield jfoldablelayoutinfo, boundsid ; left = env->getintfield boundsrect, leftid ; top = env->getintfield boundsrect, topid ; right = env->getintfield boundsrect, rightid ; bottom = env->getintfield boundsrect, bottomid ; // store maxmetrics rect to fvector4 result foldbounds = fintvector4{ left, top, right, bottom }; broadcast the result via the onlayoutchanged delegate for use in the engine if ffoldables_helper haslistener { ue_log logtemp, warning, text "broadcast" ; ffoldables_helper onlayoutchanged broadcast result ; } } create a player controller and two ui states this section focuses on adding a player controller and creating two user interface ui states for flat and flex modes these objects are needed for the flex mode logic implementation following are the steps to add a player controller and create two ui states add a new player controller blueprint in content browser, go to content > thirdpersoncpp and right-click on blueprints > add/import content > blueprint class pick player controller as its parent class rename it as flexplayercontroller notethe flexplayercontroller added is generic and can be replaced by your custom player controller in an actual project add a new c++ class with actor component as its parent class name it as foldables_manager and assign it to the foldables_tutorial plugin click the create class button open the flexplayercontroller blueprint by double-clicking it click open full blueprint editor attach the actor component to the flexplayercontroller in the left pane, click add component, then find and select the foldables_manager next, create a pair of userwidget classes for the ui layouts needed flat mode ui for the full screen or normal mode; and flex mode ui for split-screen in add c++ class window, select the show all classes checkbox find and pick userwidget as the parent class then, click next name the new user widget as flatui and attach it to the plugin click next repeat the process but name the new user widget as flexui you might get an error when trying to compile stating that the userwidget is an undeclared symbol to fix this, open the foldables_tutorial build cs file, and in the publicdependencymodulenames addrange call, add "inputcore" and "umg" to the list create a pair of blueprints made from subclasses of these two user widgets right-click on content and create a new folder called foldui inside the newly created folder, right-click to add a new blueprint class in all classes, choose flatui and click the select button rename the blueprint as bp_flatui in the same folder, repeat the process but choose the flexui class and rename the blueprint as bp_flexui double-click on bp_flatui and bp_flexui, then design your two uis like below to visualize switching between flat and flex mode flat ui flex ui notethis code lab activity does not cover the steps on how to create or design ui if you want to learn about how to create your own game design in unreal engine 4, refer to unreal motion graphics ui designer guide implement the flex mode logic after creating the flexplayercontroller and the two ui states bp_flatui and bp_flexui , you can now implement flex mode logic in the foldables_manager open the foldables_manager h and include the necessary c++ header files #pragma once #include "coreminimal h" #include "components/actorcomponent h" #include "engine h" #include "flatui h" #include "flexui h" #include "foldables_helper h" #include "foldables_manager generated h" remove the line below to save a little bit of performance as this component doesn't need to tick public // called every frame virtual void tickcomponent float deltatime, eleveltick ticktype, factorcomponenttickfunction* thistickfunction override; set up the functions needed in foldables_manager the constructor, a function to create the ui widgets the implementation of onlayoutchanged delegate public // sets default values for this component's properties ufoldables_manager ; void createwidgets ; protected // called when the game starts virtual void beginplay override; protected void onlayoutchanged ffoldablelayoutinfo foldablelayoutinfo ; then, set up the variables needed references to the flat and flex ui classes references to the flat and flex ui objects mark the pointers as uproperty to ensure that garbage collection does not delete the objects they point to tsubclassof<uuserwidget> flatuiclass; tsubclassof<uuserwidget> flexuiclass; uproperty class uflatui* flatui; uproperty class uflexui* flexui; finally, define a new private function restoreflatmode , to disable flex mode and return to normal mode private void restoreflatmode ; moving over to foldables_manager cpp, implement the constructor using the constructorhelpers, find the ui classes and set the variables to store these classes also, set the bcanevertick to false to prevent the component from ticking and remove the code block of tickcomponent function // sets default values for this component's properties ufoldables_manager ufoldables_manager { primarycomponenttick bcanevertick = false; static constructorhelpers fclassfinder<uflatui> flatuibpclass text "/game/foldui/bp_flatui" ; static constructorhelpers fclassfinder<uflexui> flexuibpclass text "/game/foldui/bp_flexui" ; if flatuibpclass succeeded { flatuiclass = flatuibpclass class; } if flexuibpclass succeeded { flexuiclass = flexuibpclass class; } } next, set up the beginplay function to link the delegate to the onlayoutchanged function, to initialize the foldables_helper, and to create the widgets ready for use in the first frame // called when the game starts void ufoldables_manager beginplay { super beginplay ; ffoldables_helper onlayoutchanged adduobject this, &ufoldables_manager onlayoutchanged ; ffoldables_helper init ; createwidgets ; } set up the createwidgets function to create the widgets using the ui classes acquired in the constructor add the flatui widget to the viewport, assuming the app opens in normal mode until it receives the foldablelayoutinfo void ufoldables_manager createwidgets { flatui = createwidget<uflatui> aplayercontroller* getowner , flatuiclass, fname text "flatui" ; flexui = createwidget<uflexui> aplayercontroller* getowner , flexuiclass, fname text "flexui" ; flatui->addtoviewport ; } afterward, create the onlayoutchanged function, which will be called via a delegate inside this function, check whether the device’s folded state is half_opened if so, check whether the orientation of the fold is horizontal void ufoldables_manager onlayoutchanged ffoldablelayoutinfo foldablelayoutinfo { //if state is now flex if foldablelayoutinfo state == efoldstate half_opened { if foldablelayoutinfo orientation == efoldorientation horizontal { notefor this third person template, splitting the screen vertically isn’t ideal from a user experience ux point of view for this code lab activity, split the screen only on the horizontal fold top and bottom screen if you want it vertically, you need to use the same principle in the next step but for the x-axis instead of the y-axis you must also ensure that you have a flex ui object for the vertical layout if the device is both on flex mode and horizontal fold, change the viewport to only render on the top screen using the normalized position of the folding feature then in an asynctask on the game thread, disable the flatui and enable the flexui however, if the device is on normal mode, then return to flat ui using restoreflatmode function //horizontal split float foldratio = float foldablelayoutinfo foldbounds y / foldablelayoutinfo currentmetrics w - foldablelayoutinfo currentmetrics y ; gengine->gameviewport->splitscreeninfo[0] playerdata[0] sizex = 1 0f; gengine->gameviewport->splitscreeninfo[0] playerdata[0] sizey = foldratio; asynctask enamedthreads gamethread, [=] { if flatui->isinviewport { flatui->removefromparent ; } if !flexui->isinviewport { flexui->addtoviewport 0 ; } } ; } else { restoreflatmode ; } } else { restoreflatmode ; } } reverse the flex mode implementation logic to create the restoreflatmode function by setting the viewport to fill the screen, then disable the flexui and enable the flatui void ufoldables_manager restoreflatmode { gengine->gameviewport->splitscreeninfo[0] playerdata[0] sizex = 1 0f; gengine->gameviewport->splitscreeninfo[0] playerdata[0] sizey = 1 0f; asynctask enamedthreads gamethread, [=] { if !flatui->isinviewport { flatui->addtoviewport 0 ; } if flexui->isinviewport { flexui->removefromparent ; } } ; } set up a game mode and attach the flexplayercontroller the game mode defines the game rules, scoring, and any game-specific behavior set up the game mode in unreal editor by creating a blueprint class in the content > thirdpersoncpp > blueprints folder pick game mode base as the parent class and rename it as flexgamemode double-click on flexgamemode in the drop-down menu next to player controller class, choose the flexplayercontroller lastly, go to edit > project settings > project > maps & modes and select flexgamemode as the default gamemode build and run the app go to edit > package project > android to build the apk ensure that the android development environment for unreal is already set up to your computer noteif the build failed due to corrupted build tools, consider downgrading the version to 30 or lower using the sdk manager or, simply rename d8 bat to the name of the missing file dx bat in sdk path > build-tools > version number directory and, in lib folder of the same directory, rename d8 jar to dx jar after packaging your android project, run the game app on a foldable galaxy device and see how the ui switches from normal to flex mode if you don’t have any physical device, you can also test it on a remote test lab device tipwatch this tutorial video and know how to easily test your app via remote test lab you're done! congratulations! you have successfully achieved the goal of this code lab now, you can implement flex mode in your unreal engine game app by yourself! if you're having trouble, you may download this file flex mode on unreal complete code 20 16 mb to learn more, visit www developer samsung com/galaxy-z www developer samsung com/galaxy-gamedev
Learn Code Lab
codelabmatter build a matter iot app with smartthings home api objective learn how to create an iot app to onboard, control, remove, and share matter devices using smartthings home apis notesmartthings home apis are distributed only to authorized users if you want permission to use the apis, contact st matter@samsung com overview matter is an open-source connectivity standard for smart home and internet of things iot devices it is a secure, reliable, and seamless cross-platform protocol for connecting compatible devices and systems with one another smartthings provides the matter virtual device app and smartthings home apis to help you quickly develop matter devices and use the smartthings ecosystem without needing to build your own iot ecosystem you can use smartthings home apis to onboard, control, remove, and share all matter devices when building your application other iot ecosystems can use the matter devices onboarded on your iot app through the multi-admin function for detailed information, go to partners smartthings com/matter set up your environment you will need the following host pc running on windows 10 or higher or ubuntu 20 04 x64 android studio latest version recommended java se development kit jdk 11 or later devices connected on the same network mobile device with matter virtual device app installed mobile device with developer mode and usb debugging enabled matter-enabled smartthings station onboarded with samsung account used for smartthings app tipyou can create a virtual device as a third-party iot device sample code noteyou can request permission to access the sample project file for this code lab by sending an email to st matter@samsung com start your project after downloading the sample code containing the project files, open your android studio and click open to open an existing project locate the downloaded android project from the directory and click ok commission the device you can onboard a matter-compatible device to the iot app by calling the commissiondevice api, which can lay the groundwork to control, remove, and share the device go to app > java > com samsung android matter home sample > feature > main in the mainviewmodel kt file, call the commissiondevice api to launch the onboarding activity and join the device to the smarththings fabric // ================================================================================= // codelab // step 1 create an instance of matter commissioning client // step 2 call the commissiondevice api to launch the onboarding activity in home service // step 3 set _intentsender value from return value of commissiondevice api // todo 1 device commission and join a device to smartthings fabric // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //val commissioningclient = matter getcommissioningclient //val intentsender = commissioningclient commissiondevice context //_intentsender value = intentsender // ================================================================================= control the device capabilities are core to the smartthings architecture they abstract specific devices into their underlying functions, which allows the retrieval of the state of a device component or control of the device function each device has its own appropriate capabilities therefore, each device has a different control api, and the more functions it supports, the more apis it has to use in this step, select a device type that you want to onboard and control using necessary home apis the level of modification complexity is assigned per each device contact sensorlevel 1 3 mins file path app > java > com samsung android matter home sample > feature > device file name contactsensorviewmodel kt // ================================================================================= // codelab level 1 // step 1 get contactsensor capability from device instance // step 2 get stream openclose value from contactsensor capability // step 3 set _openclose value for ui updating // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability contactsensor ? openclose? collect { openclose -> // _openclose value = openclose //} // ================================================================================= // ================================================================================= // codelab level 1 // step 1 get battery capability from device instance // step 2 get stream battery value from battery capability // step 3 set _batterystatus value for ui updating // todo 2 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability battery ? battery? collect { battery -> // _batterystatus value = battery //} // ================================================================================= motion sensorlevel 1 3 mins file path app > java > com samsung android matter home sample > feature > device file name motionsensorviewmodel kt // ================================================================================= // codelab level 1 // step 1 get motionsensor capability from device instance // step 2 get stream occupied value from motionsensor capability // step 3 set _motionoccupied value for ui updating // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability motionsensor ? occupied? collect { motionoccupied -> // _motionoccupied value = motionoccupied // timber d "occupied= $motionoccupied" //} // ================================================================================= // ================================================================================= // codelab level 1 // step 1 get battery capability from device instance // step 2 get stream battery value from battery capability // step 3 set _batterystatus value for ui updating // todo 2 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability battery ? battery? collect { battery -> // _batterystatus value = battery // timber d "battery= $battery" //} // ================================================================================= on-off switchlevel 2 4 mins file path app > java > com samsung android matter home sample > feature > device file name switchviewmodel kt // ================================================================================= // codelab level 2 // step 1 get switch capability from device instance // step 2 get stream onoff value from switch capability // step 3 set _onoff value for ui updating // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability switch ? onoff? collect { onoff -> // _onoff value = onoff //} // ================================================================================= // ================================================================================= // codelab level 2 // step 1 get switch capability from device instance // step 2 control the device using the apis that supported by switch capability // toggle switch state based on onoff value // onoff == true call switch off // onoff == false call switch on // todo 2 uncomment the following code blocks // --------------------------------------------------------------------------------- //device readcapability switch ? let { switch -> // if onoff == true { // switch off // } else { // switch on // } //} // ================================================================================= smart locklevel 3 8 mins file path app > java > com samsung android matter home sample > feature > device file name smartlockviewmodel kt // ================================================================================= // codelab level 3 // step 1 get lock capability from device instance // step 2 get stream lockunlock value from lock capability // step 3 set _lockstatus value for ui updating // --------------------------------------------------------------------------------- // todo 1 copy code below device readcapability lock ? lockunlock? collect { lockunlock -> _lockstatus value = lockunlock } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get tamperalert capability from device instance // step 2 get stream tamperalert value from tamperalert capability // step 3 set _tamperstatus value for ui updating // --------------------------------------------------------------------------------- // todo 2 copy code below device readcapability tamperalert ? tamperalert? collect { tamperalert -> _tamperstatus value = tamperalert } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get battery capability from device instance // step 2 get stream battery value from battery capability // step 3 set _batterystatus value for ui updating // --------------------------------------------------------------------------------- // todo 3 copy code below device readcapability battery ? battery? collect { battery -> _batterystatus value = battery } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get lock capability from device instance // step 2 control the device using the apis that supported by lock capability // toggle lock state based on lockunlock value // lockunlock == true call lock // lockunlock == false call unlock // --------------------------------------------------------------------------------- // todo 4 copy code below device readcapability lock ? let { lock -> if lockunlock == true { lock lock } else { lock unlock } } // ================================================================================= blindslevel 3 8 mins file path app > java > com samsung android matter home sample > feature > device file name blindviewmodel kt // ================================================================================= // codelab level 3 // step 1 get windowshade capability from device instance // step 2 get stream windowshademode value from windowshade capability // step 3 set _windowshademode value for ui updating // --------------------------------------------------------------------------------- // todo 1 copy code below device readcapability windowshade ? windowshademode? collect { windowshademode -> timber d "windowshademode $windowshademode" _windowshademode value = windowshademode } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get windowshadelevel capability from device instance // step 2 get stream shadelevel value from windowshadelevel capability // step 3 set _shadelevel value for ui updating // --------------------------------------------------------------------------------- // todo 2 copy code below device readcapability windowshadelevel ? shadelevel? collect { shadelevel -> timber d "shadelevel $shadelevel" _shadelevel value = shadelevel } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get battery capability from device instance // step 2 get stream battery value from battery capability // step 3 set _batterystatus value for ui updating // --------------------------------------------------------------------------------- // todo 3 copy code below device readcapability battery ? battery? collect { battery -> _batterystatus value = battery } // ================================================================================= // ================================================================================= // codelab level 3 // step 1 get windowshade capability from device instance // step 2 control the device using the apis that supported by windowshade capability // send windowshade open/close/pause command based on controlcommand value // "open" call windowshade open // "close" call windowshade close // "pause" call windowshade pause // --------------------------------------------------------------------------------- // todo 4 copy code below device readcapability windowshade ? let { windowshade -> when controlcommand { "open" -> windowshade open "close" -> windowshade close "pause" -> windowshade pause } } // ================================================================================= extended color lightlevel 4 10 mins file path app > java > com samsung android matter home sample > feature > device file name lightviewmodel kt // ================================================================================= // codelab level 4 // step 1 get switch capability from device instance // step 2 get stream onoff value from switch capability // step 3 set _onoff value for ui updating // --------------------------------------------------------------------------------- // todo 1 copy code below device readcapability switch ? onoff? collect { onoff -> _onoff value = onoff } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get switchlevel capability from device instance // step 2 get stream level value from switchlevel capability // step 3 set _level value for ui updating // --------------------------------------------------------------------------------- // todo 2 copy code below device readcapability switchlevel ? level? collect { level -> _level value = level } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get switch capability from device instance // step 2 control the device using the apis that supported by switch capability // toggle switch state based on onoff value // onoff == true call switch off // onoff == false call switch on // --------------------------------------------------------------------------------- // todo 3 copy code below device readcapability switch ? let { switch -> if onoff == true { switch off } else { switch on } } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get switchlevel capability from device instance // step 2 control the device using the apis that supported by switchlevel capability // call switchlevel setlevel with percentage value // --------------------------------------------------------------------------------- // todo 4 copy code below timber d "target position = $percentage" device readcapability switchlevel ? setlevel percentage // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get colorcontrol capability from device instance // step 2 control the device using the apis that supported by colorcontrol capability // call colorcontrol setcolor with hue,saturation value // --------------------------------------------------------------------------------- // todo 5 copy code below timber d "hue $hue,saturation $saturation" device readcapability colorcontrol ? setcolor hue todouble , saturation todouble // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get colortemperature capability from device instance // step 2 control the device using the apis that supported by colortemperature capability // call colortemperature setcolortemperature with temperature // --------------------------------------------------------------------------------- // todo 6 copy code below device readcapability colortemperature ? setcolortemperature temperature // ================================================================================= video playerlevel 4 10 mins file path app > java > com samsung android matter home sample > feature > device file name televisionviewmodel kt // ================================================================================= // codelab level 4 // step 1 get switch capability from device instance // step 2 get stream onoff value from switch capability // step 3 set _onoff value for ui updating // --------------------------------------------------------------------------------- // todo 1 copy code below device readcapability switch ? onoff? collect { onoff -> _onoff value = onoff } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get mediaplayback capability from device instance // step 2 get stream mediaplaybackstate value from mediaplayback capability // step 3 set _mediaplaybackstate value for ui updating // --------------------------------------------------------------------------------- // todo 2 copy code below device readcapability mediaplayback ? mediaplaybackstate? collect { mediaplaybackstate -> _mediaplaybackstate value = mediaplaybackstate } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get switch capability from device instance // step 2 control the device using the apis that supported by switch capability // toggle switch state based on onoff value // onoff == true call switch off // onoff == false call switch on // --------------------------------------------------------------------------------- // todo 3 copy code below device readcapability switch ? let { switch -> if onoff == true { switch off } else { switch on } } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get mediaplayback capability from device instance // step 2 control the device using the apis that supported by mediaplayback capability // send mediaplayback play/pause/stop/rewind/fastforward command based on controlcommand value // "play" call mediaplayback play and setplaybackstatus with playbackstatus playing // "pause" call mediaplayback pause and setplaybackstatus with playbackstatus paused // "stop" call mediaplayback stop and setplaybackstatus with playbackstatus stopped // "rewind" call mediaplayback rewind and setplaybackstatus with playbackstatus rewinding // "fastforward" call mediaplayback fastforward and setplaybackstatus with playbackstatus fastforwarding // --------------------------------------------------------------------------------- // todo 4 copy code below device readcapability mediaplayback ? let { mediaplayback -> when controlcommand { "play" -> { mediaplayback play mediaplayback setplaybackstatus playbackstatus playing } "pause" -> { mediaplayback pause mediaplayback setplaybackstatus playbackstatus paused } "stop" -> { mediaplayback stop mediaplayback setplaybackstatus playbackstatus stopped } "rewind" -> { mediaplayback rewind mediaplayback setplaybackstatus playbackstatus rewinding } "fastforward" -> { mediaplayback fastforward mediaplayback setplaybackstatus playbackstatus fastforwarding } } } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get mediatrackcontrol capability from device instance // step 2 control the device using the apis that supported by mediatrackcontrol capability // send mediatrack nexttrack/previoustrack command based on controlcommand value // "nexttrack" call mediatrack nexttrack // "previoustrack" call mediatrack previoustrack // --------------------------------------------------------------------------------- // todo 5 copy code below device readcapability mediatrackcontrol ? let { mediatrack -> when controlcommand { "nexttrack" -> mediatrack nexttrack "previoustrack" -> mediatrack previoustrack } } // ================================================================================= // ================================================================================= // codelab level 4 // step 1 get keypadinput capability from device instance // step 2 control the device using the apis that supported by keypadinput capability // call keypadinput sendkey with key value // --------------------------------------------------------------------------------- // todo 6 copy code below device readcapability keypadinput ? sendkey key // ================================================================================= thermostatlevel 5 13 mins file path app > java > com samsung android matter home sample > feature > device file name thermostatviewmodel kt // ================================================================================= // codelab level 5 // step 1 get thermostatmode capability from device instance // step 2 get stream thermostatmode value from thermostatmode capability // step 3 set _systemmode value for ui updating // --------------------------------------------------------------------------------- // todo 1 copy code below device readcapability thermostatmode ? thermostatmode? collect { thermostatmode -> timber d "viewmodel thermostatmode $thermostatmode" _systemmode value = thermostatmode } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatfanmode capability from device instance // step 2 get stream thermostatfanmode value from thermostatfanmode capability // step 3 set _fanmode value for ui updating // --------------------------------------------------------------------------------- // todo 2 copy code below device readcapability thermostatfanmode ? thermostatfanmode? collect { fanmode -> _fanmode value = fanmode } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get temperaturemeasurement capability from device instance // step 2 get stream temperature value from temperaturemeasurement capability // step 3 set _temperature value for ui updating // --------------------------------------------------------------------------------- // todo 3 copy code below device readcapability temperaturemeasurement ? temperature? collect { temperature -> _temperature value = temperature } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatcoolingsetpointbattery capability from device instance // step 2 get stream coolingsetpoint value from thermostatcoolingsetpoint capability // step 3 set _occupiedcoolingsetpoint value for ui updating // --------------------------------------------------------------------------------- // todo 4 copy code below device readcapability thermostatcoolingsetpoint ? coolingsetpoint? collect { coolingsetpoint -> _occupiedcoolingsetpoint value = coolingsetpoint } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatheatingsetpoint capability from device instance // step 2 get stream heatingsetpoint value from thermostatheatingsetpoint capability // step 3 set _occupiedheatingsetpoint value for ui updating // --------------------------------------------------------------------------------- // todo 5 copy code below device readcapability thermostatheatingsetpoint ? heatingsetpoint? collect { heatingsetpoint -> _occupiedheatingsetpoint value = heatingsetpoint } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get relativehumiditymeasurement capability from device instance // step 2 get stream humidity value from relativehumiditymeasurement capability // step 3 set _humidity value for ui updating // --------------------------------------------------------------------------------- // todo 6 copy code below device readcapability relativehumiditymeasurement ? humidity? collect { humidity -> _humidity value = humidity } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get battery capability from device instance // step 2 get stream battery value from battery capability // step 3 set _batterystatus value for ui updating // --------------------------------------------------------------------------------- // todo 7 copy code below device readcapability battery ? battery? collect { battery -> _batterystatus value = battery } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatmode capability from device instance // step 2 control the device using the apis that supported by thermostatmode capability // change thermostatmode state based on systemmode value // thermostatsystemmode off call thermostatmode off // thermostatsystemmode cool call thermostatmode cool // thermostatsystemmode heat call thermostatmode heat // thermostatsystemmode auto call thermostatmode auto // --------------------------------------------------------------------------------- // todo 8 copy code below device readcapability thermostatmode ? let { thermostatmode -> when systemmode { thermostatsystemmode off -> thermostatmode off thermostatsystemmode cool -> thermostatmode cool thermostatsystemmode heat -> thermostatmode heat thermostatsystemmode auto -> thermostatmode auto } } // ================================================================================= // ================================================================================= // step 1 get thermostatfanmode capability from device instance // step 2 control the device using the apis that supported by thermostatfanmode capability // change thermostatfanmode state based on fanmode value // thermostatfanmodeenum auto call thermostatfanmode fanauto // thermostatfanmodeenum circulate call thermostatfanmode fancirculate // thermostatfanmodeenum followschedule call thermostatfanmode setthermostatfanmode with followschedule // thermostatfanmodeenum on call thermostatfanmode fanon // --------------------------------------------------------------------------------- // todo 9 copy code below device readcapability thermostatfanmode ? let { thermostatfanmode -> when fanmode { thermostatfanmodeenum auto -> thermostatfanmode fanauto thermostatfanmodeenum circulate -> thermostatfanmode fancirculate thermostatfanmodeenum followschedule -> thermostatfanmode setthermostatfanmode "followschedule" thermostatfanmodeenum on -> thermostatfanmode fanon } } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatheatingsetpoint capability value from device instance // step 2 increase _occupiedheatingsetpoint value that have current heating value // step 3 if new increased value is under value_max 104 , // call setheatingsetpoint of thermostatheatingsetpoint capability with new increased value // --------------------------------------------------------------------------------- // todo 10 copy code below device readcapability thermostatheatingsetpoint ? let { heatingsetpoint -> val nextvalue = _occupiedheatingsetpoint value!! + 1 if nextvalue < value_max { heatingsetpoint setheatingsetpoint nextvalue } } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatheatingsetpoint capability value from device instance // step 2 decrease _occupiedheatingsetpoint value that have current heating value // step 3 if new decreased value is over value_min 32 , // call setheatingsetpoint of thermostatheatingsetpoint capability with new decreased value // --------------------------------------------------------------------------------- // todo 11 copy code below device readcapability thermostatheatingsetpoint ? let { heatingsetpoint -> val nextvalue = _occupiedheatingsetpoint value!! - 1 if nextvalue > value_min { heatingsetpoint setheatingsetpoint nextvalue } } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatcoolingsetpoint capability value from device instance // step 2 increase _occupiedcoolingsetpoint value that have current cooling value // step 3 if new increased value is under value_max 104 , // call setcoolingsetpoint of thermostatcoolingsetpoint capability with new increased value // --------------------------------------------------------------------------------- // todo 12 copy code below device readcapability thermostatcoolingsetpoint ? let { coolingsetpoint -> val nextvalue = _occupiedcoolingsetpoint value!! + 1 if nextvalue < value_max { coolingsetpoint setcoolingsetpoint nextvalue } } // ================================================================================= // ================================================================================= // codelab level 5 // step 1 get thermostatcoolingsetpoint capability value from device instance // step 2 decrease _occupiedcoolingsetpoint value that have current cooling value // step 3 if new decreased value is over value_min 32 , // call setcoolingsetpoint of thermostatcoolingsetpoint capability with new decreased value // --------------------------------------------------------------------------------- // todo 13 copy code below device readcapability thermostatcoolingsetpoint ? let { coolingsetpoint -> val nextvalue = _occupiedcoolingsetpoint value!! - 1 if nextvalue > value_min { coolingsetpoint setcoolingsetpoint nextvalue } } // ================================================================================= noteyou can find related files in android studio by going to edit menu> find > find in files and entering the keyword "codelab" remove the device using removedevice api, you can remove the device from your iot app and the smartthings fabric go to app > java > com samsung android matter home sample > feature > device > base in the baseviewmodel kt file, call the removedevice api to launch the removedevice activity // ================================================================================= // [codelab] device remove from smartthings fabric // step 1 create an instance of matter commissioning client // step 2 call the removedevice api to launch the removedevice activity in home service // step 3 set _intentsender value from return value of removedevice api // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //val commissioningclient = matter getcommissioningclient //val intentsender = commissioningclient removedevice // context, // commissioningclient removedevicerequest deviceid // //_intentsenderforremovedevice value = intentsender // ================================================================================= share the device matter devices can be shared with other matter-compatible iot platforms, such as google home, using home apis without resetting the device while connected to smartthings to perform this operation, it is necessary to enter the commissioning mode without resetting the device in the baseviewmodel kt file, call the sharedevice api to launch the sharedevice activity // ================================================================================= // [codelab] device share to other platforms // step 1 create an instance of matter commissioning client // step 2 call the sharedevice api to launch the sharedevice activity in home service // step 3 set _intentsender value from return value of sharedevice api // todo 1 uncomment the following code blocks // --------------------------------------------------------------------------------- //val commissioningclient = matter getcommissioningclient //val intentsender = commissioningclient sharedevice // context, // commissioningclient sharedevicerequest deviceid // //_intentsenderforsharedevice value = intentsender // ================================================================================= build and run the iot app run the sample app to build and run your iot app, follow these steps using a usb cable, connect your mobile device select the sample iot app from the run configurations menu in the android studio then, select the connected device in the target device menu click run onboard to onboard the virtual device go to the matter virtual device app then, select and set up the virtual device type you want to control click save click start to show the qr code for onboarding go to the sample iot app and click the + button then, onboard the virtual device by scanning its qr code control by sample iot app in the sample iot app, control the virtual device by using its various functions such as on and off for switch you're done! congratulations! you have successfully achieved the goal of this code lab topic now, you can create a matter-compatible iot application with smartthings home apis by yourself! learn more by going to smartthings matter libraries
We use cookies to improve your experience on our website and to show you relevant advertising. Manage you settings for our cookies below.
These cookies are essential as they enable you to move around the website. This category cannot be disabled.
These cookies collect information about how you use our website. for example which pages you visit most often. All information these cookies collect is used to improve how the website works.
These cookies allow our website to remember choices you make (such as your user name, language or the region your are in) and tailor the website to provide enhanced features and content for you.
These cookies gather information about your browser habits. They remember that you've visited our website and share this information with other organizations such as advertisers.
You have successfully updated your cookie preferences.