Quantcast
Jump to content


Recommended Posts

Posted

Watch faces are a special type of application that runs on the home screen of a Tizen wearable watch. Different watch faces have different purposes and can be interacted with in diverse ways. A watch face creates the first impression of the watch and holds value as a fashion accessory.

Anyone can make a watch face using Galaxy Watch Designer (GWD).[1] However, GWD limits how many different features you can add in a watch face. On watch faces, data is displayed to the user in the form of “complications,” which show individual data points such as steps or heart rate. While GWD gives you a set of complications you can add to designs, it does not allow you to add custom complications, as the numbers of complications are fixed inside the GWD tool. With Tizen Studio, you can create complications that pull in data from your own custom sources or perform custom actions, such as launching a separate application or opening a settings menu. With Tizen Studio, you have more options than the ones GWD gives you.

Using Tizen Web/Native/.NET APIs, developers can add a large number of functionalities on watch faces programmatically. In this article, we’ll start by developing a basic watch face using Tizen Web API.

Prerequisites

You need to define your app as a watch face application through an application category in the config.xml file. To achieve that, add wearable_clock under category.

<widget xmlns:tizen="http://tizen.org/ns/widgets" xmlns="http://www.w3.org/ns/widgets" id="http://yourdomain/WatchFace" version="1.0.0" viewmodes="maximized">
    <tizen:application id="msWLHN3Mpw.WatchFace" package="msWLHN3Mpw" required_version="2.3.1"/>
    <tizen:category name="http://tizen.org/category/wearable_clock"/>
    <content src="index.html"/>
    <feature name="http://tizen.org/feature/screen.shape.circle"/>
    <feature name="http://tizen.org/feature/screen.size.all"/>
    <icon src="icon.png"/>
    <name>WatchFace</name>
    <tizen:profile name="wearable"/>
</widget>

Resources

For an analog watch, we need three hands for second, minute, and hour. We also need a background image with a marked time index.

The following table shows resolutions for images in our example:

Image Width (pixels) Height (pixels)
Background 360 360
Hour hand 15 360
Minute hand 16 360
Second hand 16 360

Implementation

  1. We need to create a <div> element for each component, such as background, hour hand, minute hand, and second hand.
    <div id="container">
            <div id="background">
                <div id="components-main">
                    <div id="hand-main-hour"></div>
                    <div id="hand-main-minute"></div>
                    <div id="hand-main-second"></div>
                </div>
            </div>
        </div>
    
  2. We are using an image as the watch face background, so we need to set the background image by setting styles in the CSS file.

    Background Image: The clock time index is set on top of the background image. It could be a separate <div> element, but we assembled the clock index with the green background into one image (see Figure 1).

    2019-11-11-01-01.png

    Figure 1: Watch face background image

    CSS

    #background {
        width: 100%;
        height: 100%;
        background-image: url("../image/watch_bg.png");
    }
    
  3. We also need to set styles for watch face hands separately. The app image folder holds three images, one each for the hour hand, minute hand, and second hand. Then we’ll add some info to the CSS to adjust the position, size, and so on.
    The style set for the minute hand is shown below:
    #hand-main-minute {
        position: absolute;
        left: 172px;
        top: 0px;
        width: 16px;
        height: 360px;
        background-image: url("../image/watch_hand_minute.png");
        background-position: center top;
        background-size: contain;
    }
    
  4. We need to define a function that will rotate hands by a specific angle with its element ID.
     function rotateElement(elementID, angle) {
            var element = document.querySelector("#" + elementID);
            element.style.transform = "rotate(" + angle + "deg)";
        }
    
  5. We also need to have the hand update every second. To do that, we’ll set an interval to call the updateTime() function every second.
    // Update the watch hands every second
            setInterval(function() {
                updateTime();
            }, 1000);
    
  6. We are using the getCurrentDateTime() function of Tizen Time API[2] to get the current time object. From this time object, we can get the hour, minute, and second.
    var datetime = tizen.time.getCurrentDateTime(),
                hour = datetime.getHours(),
                minute = datetime.getMinutes(),
                second = datetime.getSeconds();
    
  7. Now we are going to call our defined function rotateElement() for the hour, minute, and second hands.
      // Rotate the hour/minute/second hands
        rotateElement("hand-main-hour", (hour + (minute / 60) + (second / 3600)) * 30);
        rotateElement("hand-main-minute", (minute + second / 60) * 6);
        rotateElement("hand-main-second", second * 6);
    
  8. We need to set an event listener for visibilitychange to update the screen when the display turns on from the off state.
    // Add an event listener to update the screen immediately when the device wakes up
         document.addEventListener("visibilitychange", function() {
             if (!document.hidden) {
                  updateTime();
             }
         });
    

    We also need to set an event and update the screen when the device’s time zone changes.

    // Add eventListener to update the screen when the time zone is changed
            tizen.time.setTimezoneChangeListener(function() {
                updateTime();
            });
    
  9. Additionally, we can set an event listener for ambient mode change. In this article, we added the listener and printed a console message when the ambient mode changed. It will not change anything on the watch during ambient mode, because we haven’t updated the sample watch face for ambient mode.
    window.addEventListener("ambientmodechanged", function(e) {
            if (e.detail.ambientMode === true) {
                 // Rendering ambient mode case
                 console.log("Ambient mode");
            } else {
                 // Rendering normal case
                 console.log("Normal mode");
            }
         });
    

Demo

A sample watch face app can be downloaded here, and the final watch face is shown in Figure 2.

2019-11-11-01-02.png

Figure 2: Demo watch face developed using Tizen Web

Conclusion

This article demonstrates how to start developing watch face apps with Tizen web API using Tizen Studio. We can now add more functionalities and change the watch into more than just a device that shows time.

References

  1. https://developer.samsung.com/galaxy-watch/design/watch-face/complications
  2. https://developer.tizen.org/development/guides/web-application/device-settings-and-systems/time-and-date-management

View the full blog at its source



  • Replies 0
  • Created
  • Last Reply

Top Posters In This Topic

Popular Days

Top Posters In This Topic

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Similar Topics

    • By Samsung Newsroom
      Watch Face Studio (WFS) allows designers to create custom watch faces for Galaxy Watches running Wear OS powered by Samsung with powerful visual and interactive features. One of the newest additions to the software is the Photo slot feature, which lets users personalize watch faces by adding images from their phones through the companion app (Galaxy wearable), making designs more dynamic and customizable.
      This blog demonstrates how designers can implement the Photo slot feature in a watch face project and allow users to customize backgrounds directly from their phones. The blog covers:
      • Adding a background image using a Photo slot
      • Setting the Photo slot properties
      • Customizing the Photo slot using the companion app
      The sample project includes some images that requires the use of the Photo slot feature.
      Adding a background image using Photo slot
      To begin, create a new watch face project in WFS. Instead of adding a Preset image, use the Photo slot component.
      The Photo slot component allows adding only one image to the project. However, after deploying the watch face on a real device, the Photo slot enables the inclusion of multiple images within it.
      NoteThe Photo slot feature allows only one slot per project, and adding another turns off the feature in the components. In the sample project, different times of the day are used to display the background image. This ensures that the watch face has a ready-to-use appearance when it first loads.
      Additional background images are provided with the sample project file, such as:
      ● Noon
      ● Evening
      ● Night
      In this project, the Morning theme is already added within the watch face design. The other themes are demonstrated later through customization using the companion app.
      Setting Photo slot properties
      The Photo slot component has two options in the "WHEN TO CHANGE PHOTO" section of the properties:
      • When watch face is tapped (the default value)
      • When watch wakes
      In this project, the When watch face is tapped option is selected. This option allows the user to quickly and interactively change the watch face background by tapping the watch screen to cycle through the available images in the slot.
      The Photo slot also includes another property called When watch wakes. When enabled, the background automatically changes whenever the watch screen turns on.
      Deploying the watch face
      After configuring the Photo slot and watch face elements, the project can be deployed to a real Galaxy Watch.
      For guidance on deploying the watch face to a real device, refer to Connecting Galaxy Watch to Watch Face Studio over Wi-Fi.
      Customizing the Photo slot
      One of the main advantages of the Photo slot feature is that it allows end users to customize the watch face with their own photos.
      Once the watch face has been deployed, the user can then customize it with their own background images by following the steps below:
      Open the companion app on the connected phone. Tap the Customize button. Click on the ‘+’ sign to add images. NoteThree sample images are included with the sample project. To use these images, download and store them with your phone's photos. The process opens the phone's photos and provides options to select images. After images have been added, they are displayed on this screen, along with an option to delete them. The first added image is automatically set as the background image.
      Testing on a real device ensures that the Photo slot interaction behaves correctly and the tap-based background switching works smoothly.
      Conclusion
      The Photo slot feature in Watch Face Studio introduces a powerful way to create customizable watch faces. By combining the built-in background image with user-selected images through the companion app, designers can deliver watch faces that are both visually appealing and highly customizable.
      If you have questions or need help with the information presented in this article, you can share your queries on the Samsung Developers Forum. You can also contact us directly for more specialized support through the Samsung Developer Support Portal.
      View the full blog at its source
    • By Samsung Newsroom
      Integrating payments into a mobile app is a security-critical and UX-sensitive task. While Flutter simplifies cross-platform development, platform-specific payment systems like Samsung Pay still require careful handling.
      Samsung provides an official Samsung Pay SDK Flutter Plugin, which allows Flutter applications to integrate Samsung Pay without writing custom platform channels. However, for production-grade integration, using the plugin correctly is essential, especially when it comes to checking Samsung Pay readiness.
      In this blog, you learn how to build a sample Flutter application by using the official Samsung Pay SDK Flutter Plugin and following Samsung-recommended best practices. You can download the complete sample project at the end of this blog.
      Why Use the Official Samsung Pay SDK Flutter Plugin?
      Integrating payment systems requires careful handling of platform constraints, security, and long-term maintainability. The Samsung Pay SDK Flutter Plugin addresses these concerns by providing an official abstraction over the native Samsung Pay SDK, enabling Flutter applications to leverage Samsung Wallet features without direct interaction with platform-specific APIs.
      By exposing supported Dart APIs and managing native SDK communication internally, the Flutter plugin removes the need for custom MethodChannel implementations and reduces integration risk. For Flutter applications targeting Samsung Galaxy devices, this approach offers the most stable and maintainable path to Samsung Pay integration.
      The following diagram illustrates the high-level architecture of the Samsung Pay integration.

      Figure 1: Samsung Pay integration architecture
      Prerequisites
      Before starting, ensure the following requirements are met:
      You are an approved Samsung Pay partner (approval typically takes a few days) A service is created in the Samsung Pay partner portal. Find details from here. The latest version of Android Studio is installed The Flutter SDK is installed and configured The Samsung Pay SDK Flutter Plugin is downloaded Set Up the Integration Code
      To start the integration process, add the Samsung Pay SDK Flutter Plugin to your project dependencies:
      dependencies: samsung_pay_sdk_flutter: path: ./samsungpaysdkflutter_v1.03.00/samsungpaysdkflutter Next, configure the Samsung Pay SDK API level by setting a valid Samsung Pay SDK API version (latest version: 2.22) by opening android > app > src > main > AndroidManifest.xml and adding the API level in the metadata inside the <application> tag.
      <meta-data android:name="spay_sdk_api_level" android:value="2.22" /> <!-- Use the most recent SDK version to leverage the latest APIs --> Initialize Samsung Pay in Flutter
      Create an instance of SamsungPaySdkFlutter with valid PartnerInfo (which contains the service ID and service type). If you are a merchant, then the service type must be set to INAPP_PAYMENT.
      The following code snippet initializes the Samsung Pay SDK using your service ID and in-app payment configuration.
      import 'package:samsung_pay_sdk_flutter/samsung_pay_sdk_flutter.dart'; static final SamsungPaySdkFlutter sdk = SamsungPaySdkFlutter( PartnerInfo( serviceId: SERVICE_ID, data: { SpaySdk.PARTNER_SERVICE_TYPE: ServiceType.INAPP_PAYMENT.name } ) ); Check Samsung Pay Availability
      Samsung Pay readiness must be checked before calling any API of the Samsung Pay SDK Flutter Plugin. There are several reasons why Samsung Pay might not be in the ready state, such as an unsupported device, unsupported region, or incomplete Samsung Wallet setup, so this check is mandatory.
      SamsungPayConfig.sdk.getSamsungPayStatus( StatusListener( onSuccess: (status, bundle) { // Status "2" means Samsung Pay is READY onResult(status == "2"); }, onFail: (errorCode, bundle) { // If status check fails, Samsung Pay is not ready onResult(false); } ) ); NoteDo not show the Samsung Pay button if the Samsung Pay status is not READY. Create Payment Information with a Custom Payment Sheet
      To initiate a transaction, you must create a payment request using a custom payment sheet.
      The AmountBoxControl object is mandatory for building a CustomSheet. It provides the monetary details of the transaction.
      AmountBoxControl amountControl = AmountBoxControl( Strings.AMOUNT_CONTROL_ID, Strings.currency ); // Add product item to the payment sheet amountControl.addItem( product.productId, product.name, product.price, "" ); // Set total amount (product price + additional fees) // You can add tax, shipping, or other fees here amountControl.setAmountTotal( product.price + 5.00, // Add $5 for shipping/fees as example SpaySdk.FORMAT_TOTAL_PRICE_ONLY ); Next, add the amountBoxControl to the CustomSheet instance.
      CustomSheet customSheet = CustomSheet(); customSheet.addControl(amountControl); Finally, create the payment information by populating the CustomSheetPaymentInfo instance
      // Configure merchant information for the payment CustomSheetPaymentInfo paymentInfo = CustomSheetPaymentInfo( merchantName: "Samsung Pay Flutter App", customSheet: customSheet ); // Set merchant details paymentInfo.merchantId = "123456"; paymentInfo.setMerchantName("Sample Merchant"); paymentInfo.setMerchantCountryCode("US"); Request Payment
      To start the payment process, call the startInAppPayWithCustomSheet() API. This API requires CustomSheetPaymentInfo and CustomSheetTransactionInfoListener instances set up in the last step.
      When this API is called, a custom payment sheet is displayed on the merchant application screen. The user can select a registered card for the payment and change the billing and shipping addresses if needed. Payment results are delivered to the CustomSheetTransactionInfoListener.
      The onCardInfoUpdated() callback is triggered when the user changes the payment card. In this callback, the updateSheet() method must be called to update current payment sheet.
      CustomSheetTransactionInfoListener listener = CustomSheetTransactionInfoListener( onCardInfoUpdated: (PaymentCardInfo cardInfo, CustomSheet sheet) { // Called when user changes the selected card on payment sheet // You can update the sheet here if needed (e.g., change fees based on card) SamsungPayConfig.sdk.updateSheet(sheet); }, onSuccess: (paymentInfo, paymentCredential, extraData) { // Payment completed successfully // paymentCredential contains the encrypted card details to send to your backend print("Payment Successful!"); print("Payment Credential: $paymentCredential"); onSuccess(); }, onFail: (errorCode, bundle) { // Payment failed or user cancelled print("Payment Failed: $errorCode"); onFail(errorCode); } ); Lastly, call startInAppPayWithCustomSheet() API to start the payment:
      SamsungPayConfig.sdk.startInAppPayWithCustomSheet(paymentInfo, listener); Testing Samsung Pay Integration
      Follow the steps below to test Samsung Pay integration
      Configure the STG environment: Add tester accounts to your service and generate a debug expiration date for the test accounts. Install Samsung Wallet test application: To test your application in the staging environment, the latest version of the Samsung Wallet test application is required. You can install it from the Samsung Pay Partner portal. However, to test your app in production mode, you need to use a market released application. Test cards: To thoroughly test your application, you must add at least one payment card to the Samsung Wallet application. Samsung provides test cards for this purpose. Keep in mind that the test cards only work in staging environments, not in production. Run the application: After setting up the environment, build the application and test it on any supported Galaxy device.
      Figure 2: Samsung Pay Flutter sample application
      Release Your Application
      After successful testing, submit your application for release approval through the Samsung Pay Developers Portal. Once approved, your app can be published for your users.
      Conclusion
      Using the official Samsung Pay SDK Flutter Plugin makes it simpler to create a secure and reliable payment integration for Flutter applications on Galaxy devices. By following Samsung-recommended practices, such as checking Samsung Pay readiness and handling custom payment sheets correctly, you can build a production-ready and maintainable payment experience.
      Additional Resources
      Samsung Pay Documentation provides an overview of the key features and highlights the benefits of using Samsung Pay. Samsung Pay Partner Onboarding is an end-to-end guide of becoming a partner to release your app. Samsung Pay – Code Lab is an interactive, hands-on tutorial that teaches you to how to integrate Samsung Pay SDK. Samsung Developer Forums is an open community for developers where you can post your query and get support from other developers. Samsung Developer Tech Support Channel is a 1-on-1 support channel where you can get assistance from the Samsung engineers. Download the complete sample project here. View the full blog at its source
    • By Samsung Newsroom
      Samsung Health Data SDK has been updated with support for additional health data types, expanding the range of health insights available to developers building digital health apps.
      This update introduces support for two new data areas generated by Samsung Health Monitor on compatible Galaxy Watch devices. It includes accessing Irregular Heart Rhythm Notification (IHRN) and sleep apnea data.
      Irregular Heart Rhythm Notification (IHRN)
      The SDK provides a new data type to retrieve Irregular Heart Rhythm events detected on Galaxy Watches by Samsung Health Monitor application. While the app itself can notify users when potential irregular rhythms are detected, thanks to Samsung Health Data SDK you can now access history record of all these events. Having such data, you could easily observe heart rhythm patterns and elevate monitoring of your health condition.
      Sleep apnea data
      Support has also been added for sleep apnea data reported by Samsung Health Monitor. This feature analyzes overnight data collected across multiple nights to assess signs associated with obstructive sleep apnea. Developers can query these results through the SDK to incorporate sleep health insights into their apps.
      These data types are intended for informational and integration purposes only and are not a substitute for medical diagnosis or treatment.
      With these additions, developers can leverage the Samsung Health Data SDK’s existing APIs for data reading and change queries to work with a broader set of cardiovascular and sleep health data, enabling richer healthcare experiences.
      You’ll find these new features in Samsung Health Data SDK. Refer to Release Note for more information.
      View the full blog at its source
    • By Samsung Newsroom
      Digital identity verification has become a rising topic in the current technological landscape. Samsung Wallet allows Samsung Galaxy device users to securely register their state-issued US driver's license in their device, letting them use it as a mobile driver's license (mDL). Through the "Verify with Wallet" (VWW) functionality, Samsung Wallet provides Android developers with the ability to authenticate a user's identity directly from their application by utilizing the user's registered mDL on the device. The implementation of the functionality is based on and is fully compliant with the ISO 18013-5 standard. In this article, we explore the complete process of implementing Verify with Wallet in an Android application.
      Prerequisites
      In order to complete the tasks in this article and implement a complete sample application for verifying a user's identity, you need the following:
      Valid US driver's license or state ID US region Samsung Galaxy device with mDL support Complete the Samsung Wallet Partner onboarding process Understanding the Verify with Wallet process
      Samsung Wallet offers a native Relying Party (RP) SDK for Android applications. RP SDK is an App2App SDK designed for enabling Samsung Wallet's mDL service in online use cases. By integrating this SDK, you can leverage the VWW functionality within their applications.
      In your application, you need to create a JSON object for defining the request and a JSON payload for the Relying Party card. Then, you can utilize the RP SDK to create a valid mDoc request using the provided information. Finally, the request needs to be sent to the Samsung Wallet application.
      In response, Samsung Wallet sends an encrypted response back to the application, which contains the requested information in a CBOR encoded format. The application can then decode the provided data and use it as necessary. Refer to the ISO 18013-5 standard, AAMVA mDL guidelines and the Samsung Wallet documentation for a better understanding of the VWW process.
      Implementing the Verify with Wallet Functionality in Your Android Application
      The process of implementing VWW in an Android application includes creating a Relying Party card for Samsung Wallet, downloading and integrating the RP SDK into the Android application and implementing the necessary functions in the Android application for completing the verification process.
      Creating a Relying Party Wallet Card Template in the Samsung Wallet Partners Portal
      In order to implement and use the VWW functionality, you need a wallet card of the Relying Party type for this purpose.
      To create a Relying Party wallet card template:
      Go to the Samsung Wallet Partners Portal. Select Wallet Card > Create Wallet Cards. From Wallet Card Templates, select Relying Party. Select the applicable Service Location and Authentication Issuer from the Advanced setting section. Make sure to select the proper values for the card, otherwise the verification process may not work. Figure 1: Creating a Relying Party card for VWW
      Integrating the RP SDK in an Android Application
      Once the Relying Party card template has been created, we can download and integrate the RP SDK to work with the Android application.
      Step 1: Download the RP SDK for Android
      To download the RP SDK:
      Download the ZIP file containing the latest RP SDK release AAR file from Samsung Wallet Code Resources on the Samsung Developer website. Extract the AAR file from the downloaded ZIP file. Copy and paste the downloaded rp-sdk-x.xx-release.aar file inside a new directory in the Android Studio project (for example, \libs\). Step 2: Add Android Manifest Permissions
      To implement the Verify with Wallet functionality, the application needs both the Internet access permission and the ability to query the installed Samsung Wallet application. To provide the application with these permissions, open the AndroidManifest.xml file in the Android Studio project and add the following lines:
      <uses-permission android:name="android.permission.INTERNET" /> <queries> <package android:name="com.samsung.android.spay" /> </queries> Step 3: Add Gradle Dependencies
      In the application's build.gradle file, load the RP SDK AAR file and the necessary additional dependencies for using the SDK, as follows:
      // Load RP SDK AAR file implementation(files("libs/rp-sdk-1.05-release.aar")) //CBOR decoding dependencies implementation("com.upokecenter:cbor:4.0.1") implementation("com.augustcellars.cose:cose-java:1.1.0") // Other dependencies implementation("com.google.code.gson:gson:2.11.0") implementation("org.bouncycastle:bcprov-jdk15to18:1.66") implementation("com.nimbusds:nimbus-jose-jwt:9.37.3") implementation("io.reactivex.rxjava2:rxjava:2.2.21") implementation("io.reactivex.rxjava2:rxkotlin:2.4.0") implementation("io.reactivex.rxjava2:rxandroid:2.1.1") implementation("com.squareup.okhttp3:okhttp:4.11.0") After these steps, the RP SDK is ready for use in your Android application.
      Configuring the Android Application for Verify with Wallet
      Next, we need to complete the implementation of the Verify with Wallet functionality in your Android application.
      Step 1: Build a Card Payload for the Relying Party Card
      First, we need to create a request payload for the Relying Party card following the specification.
      private fun buildApp2AppPayload(): String { return PAYLOAD .replace("{refId}", UUID.randomUUID().toString()) .replace("{createdAt}", System.currentTimeMillis().toString()) .replace("{updatedAt}", System.currentTimeMillis().toString()) } private val PAYLOAD = """ { "card": { "type": "relyingparty", "data": [ { "createdAt": {createdAt}, "updatedAt": {updatedAt}, "language": "en", "refId": "{refId}", "attributes": { "clientPackageName": "com.ahsan.verifyappsample", "clientType": "app", "fontColor": "#ffffff", "logoImage": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "logoImage.darkUrl": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "logoImage.lightUrl": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "providerName": "Samsung Verification Sample" } } ] } } """.trimIndent() Step 2: Build the AppLink
      The AppLink is a tokenized URL that is similar to the CData tokens used for Samsung Wallet cards. The Samsung Wallet RP SDK includes a function to generate the AppLink using the payload and the partner credentials (private key, public key, partner ID, card ID, certificate ID, etc.).
      To build the AppLink, you can simply call the rpClientApis.buildAppLink() function with the required parameters:
      val rpClientApis = RpClientApis(this) val appLink = rpClientApis.buildAppLink( partnerId = PARTNER_ID, cardId = CARD_ID, payload = buildApp2AppPayload(), samsungPublicKey = SAMSUNG_CERTIFICATE, partnerPublicKey = PARTNER_CERTIFICATE, partnerPrivateKey = PARTNER_PRIVATE_KEY, partnerCertificateId = CERTIFICATE_ID, isStagingServer = true ) Step 3: Build the Request Data
      Finally, once the AppLink creation is complete, we can send the verification request using the RP SDK.
      Before sending the request, we need to specify exactly which information we wish to retrieve. For this purpose, we need to create a JSON document following the ISO 18013-5 specification and specify the fields we wish to retrieve in the response. It is possible to request for the following fields in the request data under the "org.iso.18013.5.1" namespace:
      portrait family_name given_name document_number age_in_years resident_address birth_date issue_date expiry_date sex height weight_range weight eye_colour hair_colour organ_donor driving_privileges veteran Additionally, it is also possible to request for the following 3 fields, under the "org.iso.18013.5.1.aamva" namespace:
      domestic_driving_privileges DHS_compliance EDL_credential In our example, we only try to retrieve the following 4 fields: family_name, age_in_years, issue_date, and expiry_date. In the following code example, we build the request string accordingly:
      val requestData = """ { "docType": "org.iso.18013.5.1.mDL", "nameSpaces": { "org.iso.18013.5.1": { "family_name": true, "age_in_years": true, "issue_date": true, "expiry_date": true } } } """.trimIndent() Step 4: Create the OnResponseListener Class
      When using the VWW RP SDK, it is necessary to create a listener class for both sending the request and for receiving and processing the response from the mDoc server.
      For our example, let's create an empty placeholder OnResponseListener class which extends the RP SDK's OnResponseListener class.
      class OnResponseListener(private val requestData: String) : RpClientApis.OnResponseListener{ override fun onGetMdocRequestData(deviceEngagementBytes: ByteArray): ByteArray? { TODO("Not yet implemented") } override fun onMdocResponse(encryptedResponseBytes: ByteArray) { TODO("Not yet implemented") } override fun onMdocResponseFailed(exception: Exception) { Log.e(TAG, "Response processing failed", exception) } } Initiating the Verification Request
      To initiate the identity verification process, we need to establish a secure session and send a structured request to the Samsung Wallet application. We can use the previously created OnResponseListener class for this purpose.
      Step 1: Define the onGetMdocRequestData() Function for Sending the Request Data
      Inside the onGetMdocRequestData() function, we need to do 2 things for establishing a secure encrypted session:
      Generate an elliptic curve key pair Build session establishment bytes following the ISO-18013-5 specification. Once the key pair is generated, we can use this key pair, the device engagement bytes, and the previously created request data for building the encrypted session establishment bytes. The device engagement bytes are provided automatically inside the onGetMdocRequestData() function by the RP client SDK.
      private val secureRepository = SecureRepository() override fun onGetMdocRequestData(deviceEngagementBytes: ByteArray): ByteArray? { val keyPair = secureRepository.generateEcKeyPair() val encryptedSessionEstablishmentBytes = secureRepository.buildSessionEstablishment(requestData, deviceEngagementBytes, keyPair) return encryptedSessionEstablishmentBytes!! } For further information regarding generating the key pair and building the session establishment bytes, check the provided sample code.
      Step 2: Initiate a Verification Request with the AppLink
      Once the onGetMdocRequestData() function is ready, we can use the request() function to initiate the verification request.
      val sessionId = UUID.randomUUID().toString() val WALLET_PACKAGE = "com.samsung.android.spay" rpClientApis.request( WALLET_PACKAGE, sessionId, appLink, OnResponseListener(requestData) ) Processing the Request Response
      Once the mDoc request has been sent and processed successfully, the application should receive a ByteArray as response in the onMdocResponse() function inside the listener class. This ByteArray is an encrypted JSON object. Once decrypted, the response should look like the following:
      { "documents": [ { "issuerSigned": { "nameSpaces": { "org.iso.18013.5.1": [ "pGhkaWdlc3RJRBkU-mZyYW5kb21UaGNkNGduZDl5Z2I1cTRjaDV4ZnpxZWxlbWVudElkZW50aWZpZXJrZXhwaXJ5X2RhdGVsZWxlbWVudFZhbHVlwHQyMDMxLTExLTIxVDA3OjAwOjAwWg", "pGhkaWdlc3RJRBknbWZyYW5kb21Udjg1NmsydzIzZzQ3OHk5cTQ0aHJxZWxlbWVudElkZW50aWZpZXJsYWdlX2luX3llYXJzbGVsZW1lbnRWYWx1ZRgr", "pGhkaWdlc3RJRBlvWWZyYW5kb21UbnRtdnJ5OXlucXcyZjY2bmp2NXRxZWxlbWVudElkZW50aWZpZXJqaXNzdWVfZGF0ZWxlbGVtZW50VmFsdWXAdDIwMjMtMTEtMDhUMDc6MDA6MDBa", "pGhkaWdlc3RJRBnXQWZyYW5kb21UOXJqd2NydjZ6cXpqZm1xajNkcnhxZWxlbWVudElkZW50aWZpZXJrZmFtaWx5X25hbWVsZWxlbWVudFZhbHVlZUFoc2Fu" ] }, "issuerAuth": [ "dCBa", { "33": "..." }, "...", "..." ] }, "deviceSigned": {…}, "docType": "org.iso.18013.5.1.mDL" } ], "version": "1.0", "status": 0 } The values inside the org.iso.18013.5.1 JSON Array are the information we requested, in the CBOR (Concise Binary Object Representation) format.
      For example, if we decode the value: "pGhkaWdlc3RJRBlvWWZyYW5kb21UbnRtdnJ5OXlucXcyZjY2bmp2NXRxZWxlbWVudElkZW50aWZpZXJqaXNzdWVfZGF0ZWxlbGVtZW50VmFsdWXAdDIwMjMtMTEtMDhUMDc6MDA6MDBa", we find that this CBOR object contains the issue_date field and its value is 2023-11-08T07:00:00.000Z. Similarly, every value provided in the array is a CBOR object that can be decoded using CBOR decoders to find a key-value pair containing the requested information.
      We can now receive the mDoc response in the onMdocResponse() function and decode it to retrieve the final requested values:
      override fun onMdocResponse(encryptedResponseBytes: ByteArray) { val plainResponse = secureRepository.decryptMdocResponse(encryptedResponseBytes) Log.i(TAG, "plainResponse=${plainResponse?.toPrettyJson()}") val mDocContent = Mdoc18013Utils.parseMdocResponse(plainResponse!!) mDocContent.forEach { (key, value) -> Log.i(TAG, "$key: $value") } } Here, secureRepository.decryptMdocResponse() performs the decryption operation and converts the encrypted bytes into a plain JSON response. Afterwards, the Mdoc18013Utils.parseMdocResponse() function takes the plain response and decodes each CBOR-encoded element contained in the org.iso.18013.5.1 array and returns these values in a simplified dictionary of key-value pairs. If you wish to learn more about these functions, you can check out the provided sample code.
      With this step, the sample application's implementation of Verify with Wallet is complete. You can now build and run the application. In the sample application, once the user clicks the "Verify with Samsung Wallet" button, the VWW procedure is initiated. Once the user confirms that they wish to share their information, the application will receive the requested information about the user.
      Figure 2: Complete the verification process using VWW
      Conclusion
      In this article, we have explored how you can integrate the Verify with Wallet RP SDK directly into your application and use it to verify the user's identity. Feel free to integrate the RP SDK in your own application and test the Verify with Samsung Wallet process as well. If you have any further queries regarding this process, feel free to reach out to us through the Samsung Developers Forum.
      Related Resources
      ISO/IEC 18013-5:2021 - Personal identification — ISO-compliant driving licence — Part 5: Mobile driving licence (mDL) application Mobile Driver License - American Association of Motor Vehicle Administrators - AAMVA RP SDK download link Verify with Wallet API Guidelines Relying Party Card Specifications Sample Code Download Link View the full blog at its source
    • Government UFO Files
    • By Samsung Newsroom
      Digital identity verification has become a rising topic in the current technological landscape. Samsung Wallet allows Samsung Galaxy device users to securely register their state-issued US driver's license in their device, letting them use it as a mobile driver's license (mDL). Through the "Verify with Wallet" (VWW) functionality, Samsung Wallet provides Android developers with the ability to authenticate a user's identity directly from their application by utilizing the user's registered mDL on the device. The implementation of the functionality is based on and is fully compliant with the ISO 18013-5 standard. In this article, we explore the complete process of implementing Verify with Wallet in an Android application.
      Prerequisites
      In order to complete the tasks in this article and implement a complete sample application for verifying a user's identity, you need the following:
      Valid US driver's license or state ID US region Samsung Galaxy device with mDL support Complete the Samsung Wallet Partner onboarding process Understanding the Verify with Wallet process
      Samsung Wallet offers a native Relying Party (RP) SDK for Android applications. RP SDK is an App2App SDK designed for enabling Samsung Wallet's mDL service in online use cases. By integrating this SDK, you can leverage the VWW functionality within their applications.
      In your application, you need to create a JSON object for defining the request and a JSON payload for the Relying Party card. Then, you can utilize the RP SDK to create a valid mDoc request using the provided information. Finally, the request needs to be sent to the Samsung Wallet application.
      In response, Samsung Wallet sends an encrypted response back to the application, which contains the requested information in a CBOR encoded format. The application can then decode the provided data and use it as necessary. Refer to the ISO 18013-5 standard, AAMVA mDL guidelines and the Samsung Wallet documentation for a better understanding of the VWW process.
      Implementing the Verify with Wallet Functionality in Your Android Application
      The process of implementing VWW in an Android application includes creating a Relying Party card for Samsung Wallet, downloading and integrating the RP SDK into the Android application and implementing the necessary functions in the Android application for completing the verification process.
      Creating a Relying Party Wallet Card Template in the Samsung Wallet Partners Portal
      In order to implement and use the VWW functionality, you need a wallet card of the Relying Party type for this purpose.
      To create a Relying Party wallet card template:
      Go to the Samsung Wallet Partners Portal. Select Wallet Card > Create Wallet Cards. From Wallet Card Templates, select Relying Party. Select the applicable Service Location and Authentication Issuer from the Advanced setting section. Make sure to select the proper values for the card, otherwise the verification process may not work. Figure 1: Creating a Relying Party card for VWW
      Integrating the RP SDK in an Android Application
      Once the Relying Party card template has been created, we can download and integrate the RP SDK to work with the Android application.
      Step 1: Download the RP SDK for Android
      To download the RP SDK:
      Download the ZIP file containing the latest RP SDK release AAR file from Samsung Wallet Code Resources on the Samsung Developer website. Extract the AAR file from the downloaded ZIP file. Copy and paste the downloaded rp-sdk-x.xx-release.aar file inside a new directory in the Android Studio project (for example, \libs\). Step 2: Add Android Manifest Permissions
      To implement the Verify with Wallet functionality, the application needs both the Internet access permission and the ability to query the installed Samsung Wallet application. To provide the application with these permissions, open the AndroidManifest.xml file in the Android Studio project and add the following lines:
      <uses-permission android:name="android.permission.INTERNET" /> <queries> <package android:name="com.samsung.android.spay" /> </queries> Step 3: Add Gradle Dependencies
      In the application's build.gradle file, load the RP SDK AAR file and the necessary additional dependencies for using the SDK, as follows:
      // Load RP SDK AAR file implementation(files("libs/rp-sdk-1.05-release.aar")) //CBOR decoding dependencies implementation("com.upokecenter:cbor:4.0.1") implementation("com.augustcellars.cose:cose-java:1.1.0") // Other dependencies implementation("com.google.code.gson:gson:2.11.0") implementation("org.bouncycastle:bcprov-jdk15to18:1.66") implementation("com.nimbusds:nimbus-jose-jwt:9.37.3") implementation("io.reactivex.rxjava2:rxjava:2.2.21") implementation("io.reactivex.rxjava2:rxkotlin:2.4.0") implementation("io.reactivex.rxjava2:rxandroid:2.1.1") implementation("com.squareup.okhttp3:okhttp:4.11.0") After these steps, the RP SDK is ready for use in your Android application.
      Configuring the Android Application for Verify with Wallet
      Next, we need to complete the implementation of the Verify with Wallet functionality in your Android application.
      Step 1: Build a Card Payload for the Relying Party Card
      First, we need to create a request payload for the Relying Party card following the specification.
      private fun buildApp2AppPayload(): String { return PAYLOAD .replace("{refId}", UUID.randomUUID().toString()) .replace("{createdAt}", System.currentTimeMillis().toString()) .replace("{updatedAt}", System.currentTimeMillis().toString()) } private val PAYLOAD = """ { "card": { "type": "relyingparty", "data": [ { "createdAt": {createdAt}, "updatedAt": {updatedAt}, "language": "en", "refId": "{refId}", "attributes": { "clientPackageName": "com.ahsan.verifyappsample", "clientType": "app", "fontColor": "#ffffff", "logoImage": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "logoImage.darkUrl": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "logoImage.lightUrl": "https://kr-cdn-gpp.mcsvc.samsung.com/mcp25/resource/2024/9/4/b940b7a2-0f55-42ce-8da7-025d50dbb6b7.png", "providerName": "Samsung Verification Sample" } } ] } } """.trimIndent() Step 2: Build the AppLink
      The AppLink is a tokenized URL that is similar to the CData tokens used for Samsung Wallet cards. The Samsung Wallet RP SDK includes a function to generate the AppLink using the payload and the partner credentials (private key, public key, partner ID, card ID, certificate ID, etc.).
      To build the AppLink, you can simply call the rpClientApis.buildAppLink() function with the required parameters:
      val rpClientApis = RpClientApis(this) val appLink = rpClientApis.buildAppLink( partnerId = PARTNER_ID, cardId = CARD_ID, payload = buildApp2AppPayload(), samsungPublicKey = SAMSUNG_CERTIFICATE, partnerPublicKey = PARTNER_CERTIFICATE, partnerPrivateKey = PARTNER_PRIVATE_KEY, partnerCertificateId = CERTIFICATE_ID, isStagingServer = true ) Step 3: Build the Request Data
      Finally, once the AppLink creation is complete, we can send the verification request using the RP SDK.
      Before sending the request, we need to specify exactly which information we wish to retrieve. For this purpose, we need to create a JSON document following the ISO 18013-5 specification and specify the fields we wish to retrieve in the response. It is possible to request for the following fields in the request data under the "org.iso.18013.5.1" namespace:
      portrait family_name given_name document_number age_in_years resident_address birth_date issue_date expiry_date sex height weight_range weight eye_colour hair_colour organ_donor driving_privileges veteran Additionally, it is also possible to request for the following 3 fields, under the "org.iso.18013.5.1.aamva" namespace:
      domestic_driving_privileges DHS_compliance EDL_credential In our example, we only try to retrieve the following 4 fields: family_name, age_in_years, issue_date, and expiry_date. In the following code example, we build the request string accordingly:
      val requestData = """ { "docType": "org.iso.18013.5.1.mDL", "nameSpaces": { "org.iso.18013.5.1": { "family_name": true, "age_in_years": true, "issue_date": true, "expiry_date": true } } } """.trimIndent() Step 4: Create the OnResponseListener Class
      When using the VWW RP SDK, it is necessary to create a listener class for both sending the request and for receiving and processing the response from the mDoc server.
      For our example, let's create an empty placeholder OnResponseListener class which extends the RP SDK's OnResponseListener class.
      class OnResponseListener(private val requestData: String) : RpClientApis.OnResponseListener{ override fun onGetMdocRequestData(deviceEngagementBytes: ByteArray): ByteArray? { TODO("Not yet implemented") } override fun onMdocResponse(encryptedResponseBytes: ByteArray) { TODO("Not yet implemented") } override fun onMdocResponseFailed(exception: Exception) { Log.e(TAG, "Response processing failed", exception) } } Initiating the Verification Request
      To initiate the identity verification process, we need to establish a secure session and send a structured request to the Samsung Wallet application. We can use the previously created OnResponseListener class for this purpose.
      Step 1: Define the onGetMdocRequestData() Function for Sending the Request Data
      Inside the onGetMdocRequestData() function, we need to do 2 things for establishing a secure encrypted session:
      Generate an elliptic curve key pair Build session establishment bytes following the ISO-18013-5 specification. Once the key pair is generated, we can use this key pair, the device engagement bytes, and the previously created request data for building the encrypted session establishment bytes. The device engagement bytes are provided automatically inside the onGetMdocRequestData() function by the RP client SDK.
      private val secureRepository = SecureRepository() override fun onGetMdocRequestData(deviceEngagementBytes: ByteArray): ByteArray? { val keyPair = secureRepository.generateEcKeyPair() val encryptedSessionEstablishmentBytes = secureRepository.buildSessionEstablishment(requestData, deviceEngagementBytes, keyPair) return encryptedSessionEstablishmentBytes!! } For further information regarding generating the key pair and building the session establishment bytes, check the provided sample code.
      Step 2: Initiate a Verification Request with the AppLink
      Once the onGetMdocRequestData() function is ready, we can use the request() function to initiate the verification request.
      val sessionId = UUID.randomUUID().toString() val WALLET_PACKAGE = "com.samsung.android.spay" rpClientApis.request( WALLET_PACKAGE, sessionId, appLink, OnResponseListener(requestData) ) Processing the Request Response
      Once the mDoc request has been sent and processed successfully, the application should receive a ByteArray as response in the onMdocResponse() function inside the listener class. This ByteArray is an encrypted JSON object. Once decrypted, the response should look like the following:
      { "documents": [ { "issuerSigned": { "nameSpaces": { "org.iso.18013.5.1": [ "pGhkaWdlc3RJRBkU-mZyYW5kb21UaGNkNGduZDl5Z2I1cTRjaDV4ZnpxZWxlbWVudElkZW50aWZpZXJrZXhwaXJ5X2RhdGVsZWxlbWVudFZhbHVlwHQyMDMxLTExLTIxVDA3OjAwOjAwWg", "pGhkaWdlc3RJRBknbWZyYW5kb21Udjg1NmsydzIzZzQ3OHk5cTQ0aHJxZWxlbWVudElkZW50aWZpZXJsYWdlX2luX3llYXJzbGVsZW1lbnRWYWx1ZRgr", "pGhkaWdlc3RJRBlvWWZyYW5kb21UbnRtdnJ5OXlucXcyZjY2bmp2NXRxZWxlbWVudElkZW50aWZpZXJqaXNzdWVfZGF0ZWxlbGVtZW50VmFsdWXAdDIwMjMtMTEtMDhUMDc6MDA6MDBa", "pGhkaWdlc3RJRBnXQWZyYW5kb21UOXJqd2NydjZ6cXpqZm1xajNkcnhxZWxlbWVudElkZW50aWZpZXJrZmFtaWx5X25hbWVsZWxlbWVudFZhbHVlZUFoc2Fu" ] }, "issuerAuth": [ "dCBa", { "33": "..." }, "...", "..." ] }, "deviceSigned": {…}, "docType": "org.iso.18013.5.1.mDL" } ], "version": "1.0", "status": 0 } The values inside the org.iso.18013.5.1 JSON Array are the information we requested, in the CBOR (Concise Binary Object Representation) format.
      For example, if we decode the value: "pGhkaWdlc3RJRBlvWWZyYW5kb21UbnRtdnJ5OXlucXcyZjY2bmp2NXRxZWxlbWVudElkZW50aWZpZXJqaXNzdWVfZGF0ZWxlbGVtZW50VmFsdWXAdDIwMjMtMTEtMDhUMDc6MDA6MDBa", we find that this CBOR object contains the issue_date field and its value is 2023-11-08T07:00:00.000Z. Similarly, every value provided in the array is a CBOR object that can be decoded using CBOR decoders to find a key-value pair containing the requested information.
      We can now receive the mDoc response in the onMdocResponse() function and decode it to retrieve the final requested values:
      override fun onMdocResponse(encryptedResponseBytes: ByteArray) { val plainResponse = secureRepository.decryptMdocResponse(encryptedResponseBytes) Log.i(TAG, "plainResponse=${plainResponse?.toPrettyJson()}") val mDocContent = Mdoc18013Utils.parseMdocResponse(plainResponse!!) mDocContent.forEach { (key, value) -> Log.i(TAG, "$key: $value") } } Here, secureRepository.decryptMdocResponse() performs the decryption operation and converts the encrypted bytes into a plain JSON response. Afterwards, the Mdoc18013Utils.parseMdocResponse() function takes the plain response and decodes each CBOR-encoded element contained in the org.iso.18013.5.1 array and returns these values in a simplified dictionary of key-value pairs. If you wish to learn more about these functions, you can check out the provided sample code.
      With this step, the sample application's implementation of Verify with Wallet is complete. You can now build and run the application. In the sample application, once the user clicks the "Verify with Samsung Wallet" button, the VWW procedure is initiated. Once the user confirms that they wish to share their information, the application will receive the requested information about the user.
      Figure 2: Complete the verification process using VWW
      Conclusion
      In this article, we have explored how you can integrate the Verify with Wallet RP SDK directly into your application and use it to verify the user's identity. Feel free to integrate the RP SDK in your own application and test the Verify with Samsung Wallet process as well. If you have any further queries regarding this process, feel free to reach out to us through the Samsung Developers Forum.
      Related Resources
      ISO/IEC 18013-5:2021 - Personal identification — ISO-compliant driving licence — Part 5: Mobile driving licence (mDL) application Mobile Driver License - American Association of Motor Vehicle Administrators - AAMVA RP SDK download link Verify with Wallet API Guidelines Relying Party Card Specifications Sample Code Download Link View the full blog at its source





×
×
  • Create New...