Quickstart with sample app

To demonstrate the capabilities of Retail Merchant Services SDK, we have provided an Android Sample App here.

This guide provides an overview of how to build and run the sample app using our Android SDK.

Prerequisites

  • Android Studio
  • A physical Android device (phone or tablet) with Android version 5.1+
  • Valid SDK credentials (SB Client ID, SB Secret, oAuth URL, API Base URL, and Callback URL)
  • Experience building Android Apps

Step 1: Create a new project

  • Open Android Studio > File > New > New Project.
  • On the New Project, click Phone and Tablet.
  • Select Empty Activity from Phone and Tablet list.
  • Click Next.
  • On the Empty Activity, enter project Name, Language, and select Minimum SDK.
  • Click Finish.

Alt text

Step 2: Import SDK

  • Download .aar file here.
  • Click Android.
  • Select Project > mydemo > app.
  • On the app, click file build.gradle.
  • Under dependencies {, insert the following code
implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation fileTree(include: ['*.jar'], dir: 'app/libs')
  • Save the file.
  • After that, copy the SDK package from the download folder to folder libs in app.
  • Click sync now.

Alt text

Step 3: Initialize SDK

After importing SDK to your project, you must Initialize SDK using this step.

  • On the app, open folder src > main > java > com > android > mydemo.
  • Right-click mydemo > select New > select Kotlin Class/File.
  • Give Class name ApplicationGlobal.
  • Under package com.android.mydemo, insert the following code
class ApplicationGlobal : Application() {

    companion object {
        var accessToken: String? = null
        var refreshToken: String? = null
    }

    override fun onCreate() {
        super.onCreate()

        RmsClient.configure(
            this, RmsConfiguration(
                clientID = "YOUR-CLIENTID",
                clientSecret = "YOUR-CLIENTSECRET",
                callbackUrl = "YOUR-SIGN-IN-CALLBACK-URL",
                signOutUrl = "YOUR-SIGN-OUT-CALLBACK-URL",
                baseUrl = "YOUR-BASEURL",
                oAuthUrl = "YOUR-OAUTHURL"
            )
        )

        RmsClient.enableLogging()
    }
}

AndroidManifest.xml

 android:name=".utils.ApplicationGlobal"
  • Save the file.
  • Select AndroidManifest.xml in folder res.
  • Add to <application the following code:
android:name=".ApplicationGlobal"
  • Save the file.

Alt text

Step 4: Register sign in activity for auth callback

  • Select AndroidManifest.xml in folder res.
  • Under android:exported=”true”, in activity tag insert the following code
android:launchMode="singleTask"
  • Under </intent-filter> , insert the following code
<intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="YOUR-CALLBACK-URL"
                    android:path="YOUR-CALLBACK-URL-PATH"
                    android:scheme="YOUR-CALLBACK-URL-SCHEME" />
            </intent-filter>
  • Save the file.

Alt text

Step 5: Override onNewIntent for auth callback

  • On the app, open folder src > main > java > com > android > mydemo.
  • Open MainActivity, Under function onCreate, insert the following code
override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        RmsClient.verifyoAuthCallback(intent)
    }
  • Save MainActivity

Alt text

Step 6: Add Sign-in button

  • On the folder res, select folder layout.
  • Open activity_main.xml, Delete tag TextView, and insert the following code
<Button
        android:id="@+id/btSignIn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/sign_in"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  • Save the file.

Alt text

Step 7: Call sign-in function from SDK

To make the button works, you must call sign-in function from SDK

  • On the app, open folder src > main > java > com > android > mydemo.
  • Open MainActivity, Under setContentView(R.layout.activity_main) , insert the following code.
btSignIn.setOnClickListener {
            RmsClient.signIn(this, object : RmsAuthCallback {
                override fun success(accessToken: String, refreshToken: String) {
                    ApplicationGlobal.accessToken = accessToken
                    ApplicationGlobal.refreshToken = refreshToken
                    startActivity(Intent(this@MainActivity, HomeActivity::class.java))
                    finishAffinity()
                }

                override fun error(exception: RmsAuthException) {
                }

                override fun signOut() {

                }
            })
        }
  • Save the file.

Alt text

Step 8: Create terminal list activity

  • Go to app > src > main > java > com > android > mydemo
  • Select mydemo > right-click > select New > Kotlin Class/File.
    • Give Class name TerminalListActivity.
    • In TerminalListActivity.kt , insert the following code:
class TerminalsListFragment : BaseFragment<TerminalListViewModel>() {
}
  • Save the file.
  • Go to res > layout > right-click > New > Layout Resource File.
  • Give file name activity_terminal_list
  • In fragment_terminals_list.xml, insert the following code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvTerminals"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • Save the file.

Alt text

Step 9: Create terminal list activity

  • Go to res > right-click layout > New > Layout Resource File.
  • Give file name layout_terminal_list.
  • In layout_terminal_list_item.xml, insert the following code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvManufacturer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Manufacturer: VERIFONE" />

    <TextView
        android:id="@+id/tvTerminalName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        app:layout_constraintTop_toBottomOf="@id/tvManufacturer"
        tools:text="Terminal Name: Ronko" />

    <TextView
        android:id="@+id/tvPos"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        app:layout_constraintTop_toBottomOf="@id/tvTerminalName"
        tools:text="Pos: WorkFlowDigital" />

    <TextView
        android:id="@+id/tvTerminalStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        android:gravity="center"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tvPos"
        tools:text="Status: Online" />

    <Button
        android:id="@+id/btView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="@string/create_transaction"
        app:layout_constraintTop_toBottomOf="@id/tvTerminalStatus" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/black"
        app:layout_constraintTop_toBottomOf="@id/btView" />

</androidx.constraintlayout.widget.ConstraintLayout>

Alt text

Step 10: Create adaptor for terminal list

  • Go to app > src > main > java > com > android > mydemo
  • Select mydemo > right-click > select New > Kotlin Class/File.
    • Give Class name TerminalListAdapter.
    • In TransactionsListApiAdapter.kt , insert the following code and save file:
class TransactionsListApiAdapter(private val listener: TransactionActionListener) :
    RecyclerView.Adapter<TransactionsListApiAdapter.TerminalViewHolder>() {

    /**
     * List of [com.sdk.rms.model.TerminalResource] for adapter reference.
     */
    private val arrayList = arrayListOf<Transaction>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TerminalViewHolder {
        //Create viewholder for the album
        return TerminalViewHolder(parent)
    }

    override fun getItemCount() = arrayList.size //Count of terminals

    override fun onBindViewHolder(holder: TerminalViewHolder, position: Int) {
        //Bind the terminal into viewholder
        holder.bind(arrayList[position])

        //Add click listeners
        holder.btCancel.setOnClickListener {
            Log.e("UrlTransaction", "onBindViewHolder: " + arrayList[position]._links.self.href)
            listener.onCancelTransaction(arrayList[position], position)
        }

    }

    /**
     * Updates the transaction list.
     *
     * @param items New list of [TerminalResource].
     */
    fun updateData(items: List<Transaction>) {
        //Clear old terminals
        arrayList.clear()
        //Add new terminals
        arrayList.addAll(items)
        //Notify the adapter for the change
        notifyDataSetChanged()
    }

    /**
     * View holder for adapter.
     */
    class TerminalViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        /**
         * Title view for the transaction list view item.
         */
        private val tvTransactionAmount: TextView = itemView.findViewById(R.id.tvTransactionAmount)
        private val tvTransactionId: TextView = itemView.findViewById(R.id.tvTransactionId)
        private val tvTransactionStage: TextView = itemView.findViewById(R.id.tvTransactionStage)
        private val tvTransactionStatus: TextView = itemView.findViewById(R.id.tvTransactionStatus)
        private val tvTransactionType: TextView = itemView.findViewById(R.id.tvTransactionType)
        private val tvCashBackAmount: TextView = itemView.findViewById(R.id.tvCashBackAmount)
        private val tvFinalTransactionAmount: TextView = itemView.findViewById(R.id.tvFinalTransactionAmount)
        val btCancel: Button = itemView.findViewById(R.id.btCancel)

        constructor(parent: ViewGroup) : this(
            LayoutInflater.from(parent.context).inflate(
                R.layout.layout_transaction_list, parent, false
            )
        )

        /**
         * Binds the transaction data to list view item.
         *
         * @param item [TerminalResource] containing transaction data.
         */
        fun bind(item: Transaction) {

            with(item) {
                //Set title of the album
                tvTransactionAmount.text = Html.fromHtml(
                    "<b>Transaction Amount: </b>${amount.toDouble() / 100} $currencyCode",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionId.text = Html.fromHtml(
                    "<b>Transaction Id: </b>$transactionRefId",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionStage.text = Html.fromHtml(
                    "<b>Transaction Stage: </b>$transactionStage",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionStatus.text = Html.fromHtml(
                    "<b>Transaction Status: </b>$transactionStatus",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionType.text = Html.fromHtml(
                    "<b>Transaction Type: </b>$transactionType",
                    Html.FROM_HTML_MODE_LEGACY
                )

                if (amountCashback>0) {
                    tvCashBackAmount.visibility = View.VISIBLE
                    tvFinalTransactionAmount.visibility = View.VISIBLE

                    tvCashBackAmount.text = Html.fromHtml(
                        "<b>Cashback Amount: </b>${(amountCashback.toDouble() / 100)} $currencyCode",
                        Html.FROM_HTML_MODE_LEGACY
                    )

                    tvFinalTransactionAmount.text = Html.fromHtml(
                        "<b>Final Transaction Amount: </b>${(finalTransactionAmount.toDouble() / 100)} $currencyCode",
                        Html.FROM_HTML_MODE_LEGACY
                    )

                } else {
                    tvCashBackAmount.visibility = View.GONE
                    tvFinalTransactionAmount.visibility = View.GONE
                }
            }

        }
    }
}
  • Go to app > src > main > java > com > android > mydemo
  • Select mydemo > right-click > select New > Kotlin Class/File.
    • Give Interface name TerminalActionListener.
    • In TerminalActionListener.kt , insert the following code and save file:
interface TerminalActionListener {

    fun onViewClicked(terminal: Terminal)
    fun onDetailClicked(terminal: Terminal)
}

Alt text

Step 11: Setup Listing in TerminalListActivity

  • Go to app > src > main > java > com > android > mydemo
  • Open TerminalListFragment.kt , insert the following code and save file:
class TerminalsListFragment : BaseFragment<TerminalListViewModel>() {

    override fun provideBaseViewModel() =
        ViewModelProvider(this).get(TerminalListViewModel::class.java)

    private val terminalAdapter by lazy {
        TerminalListApiAdapter(object : TerminalActionListener {
            override fun onViewClicked(terminal: Terminal) {
                viewModel.openPayScreen(terminal)
            }

            override fun onDetailClicked(terminal: Terminal) {
                viewModel.viewTerminal(terminal)
            }
        })
    }

    override fun getLayoutResource() = R.layout.fragment_terminals_list

    override fun init() {
        rvTerminals.apply {
            layoutManager =
                LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
            adapter = terminalAdapter
        }

        //Set click listener
        actionSearch.setOnClickListener {
            viewModel.searchTransaction()
        }
    }

    override fun registerObservables() {
        viewModel.terminalList.observe(viewLifecycleOwner) {
            it?._embedded?.terminals?.let { terminalList ->
                terminalAdapter.updateData(terminalList)
            }
        }
        viewModel.viewTerminalDetails.observe(viewLifecycleOwner) {
            it?.let { terminalId ->
                parentFragmentManager.beginTransaction()
                    .replace(R.id.container, TerminalDetailsFragment.newInstance(terminalId))
                    .addToBackStack(TerminalDetailsFragment::class.simpleName)
                    .commit()
            }
        }
        viewModel.viewPayScreen.observe(viewLifecycleOwner) {
            it?.let { terminal ->
                parentFragmentManager.beginTransaction()
                    .replace(R.id.container, PayFragment.newInstance(terminal))
                    .addToBackStack(PayFragment::class.simpleName)
                    .commit()
            }
        }

        viewModel.searchTransaction.observe(viewLifecycleOwner) {
            it?.let {
                parentFragmentManager.beginTransaction()
                    .replace(R.id.container, SearchTransactionFragment())
                    .addToBackStack(SearchTransactionFragment::class.simpleName)
                    .commit()
            }
        }
    }

    override fun onResume() {
        super.onResume()
        requireActivity().title = "List of terminals"
    }
}

Alt text

Step 12: Call terminal listing after sign in

  • Select AndroidManifest.xml in folder res.
  • After the last </activity>, Insert the following code and save:
<activity
            android:name=".views.activities.HomeActivity"
            android:exported="true"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustPan">

            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="www.rmssdk.com"
                    android:path="/callback_signout"
                    android:scheme="rmssdk" />
            </intent-filter>

        </activity>
  • Go to app > src > main > java > com > android > mydemo
  • Open MainActivity.kt , Replace Todo with this following code on MainActivity.kt:
  • First Todo replace with this code:
exception.printStackTrace()
  • Second Todo replace with this code and save:
startActivity(Intent(this@MainActivity, TerminalListActivity::class.java))

Alt text

Step 13: Create design for transaction page

  • Go to res > right-click layout > New > Layout Resource File.
  • Give file name fragment_make_transaction.
  • In fragment_make_transaction.xml, insert the following code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/tvEnterAmount"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="32dp"
        android:layout_marginTop="32dp"
        android:hint="@string/enter_amount"
        android:paddingHorizontal="4dp"
        app:boxStrokeWidth="0dp"
        app:boxStrokeWidthFocused="0dp"
        app:hintTextColor="@color/colorGrey"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/etEnterAmount"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:completionThreshold="1"
            android:imeOptions="actionDone"
            android:inputType="number"
            android:maxLines="1"
            android:textColor="@color/colorBlack" />
    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/btPay"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="@string/pay"
        app:layout_constraintEnd_toEndOf="@id/tvEnterAmount"
        app:layout_constraintStart_toStartOf="@id/tvEnterAmount"
        app:layout_constraintTop_toBottomOf="@id/tvEnterAmount" />

    <Button
        android:id="@+id/btCancel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:text="@string/cancel"
        app:layout_constraintEnd_toEndOf="@id/tvEnterAmount"
        app:layout_constraintStart_toStartOf="@id/tvEnterAmount"
        app:layout_constraintTop_toBottomOf="@id/btPay" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • Create value color resource for color black in android:textColor="@color/colorBlack"
  • Insert on field Resource value: #00000 and click OK.
  • Create string value resource for pay in android:text="@string/pay"
  • Give Resource value name Pay and click OK.
  • Create string value resource for cancel in android:text="@string/cancel"
  • Give Resource value name Cancel and click OK.
  • Save the file.

Alt text

Step 14: Create design for transaction receipt

  • Go to res > right-click layout > New > Layout Resource File.
  • Give file name layout_transaction_receipt.
  • In layout_transaction_receipt.xml, insert the following code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/clReceipt"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginHorizontal="32dp"
    android:layout_marginTop="16dp"
    android:background="@drawable/bg_receipt"
    android:padding="12dp">

    <TextView
        android:id="@+id/tvTransactionAmount"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:text="Transaction Amount: 200"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvCashBackAmount"
        android:text="Cashback Amount: 21w21"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintTop_toBottomOf="@id/tvTransactionAmount" />

    <TextView
        android:id="@+id/tvFinalTransactionAmount"
        android:text="Final Transaction Amount: 21w21"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintTop_toBottomOf="@id/tvCashBackAmount" />


    <TextView
        android:id="@+id/tvTransactionId"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:text="Transaction Id: 1234"
        app:layout_constraintTop_toBottomOf="@id/tvFinalTransactionAmount" />

    <TextView
        android:id="@+id/tvTransactionStage"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        android:text="Transaction Stage: Online"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tvTransactionId" />

    <TextView
        android:id="@+id/tvTransactionStatus"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        android:text="Transaction Status: Online"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tvTransactionStage" />

    <TextView
        android:id="@+id/tvTransactionType"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:drawablePadding="8dp"
        android:gravity="center"
        android:text="Transaction Type: Online"
        app:drawableEndCompat="@drawable/ic_dot"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tvTransactionStatus" />

    <Button
        android:id="@+id/btCheckStatus"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="@string/refresh_status"
        app:layout_constraintTop_toBottomOf="@id/tvTransactionType" />

    <Button
        android:id="@+id/btCancelTransaction"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="@string/cancel_transaction"
        app:layout_constraintTop_toBottomOf="@id/btCheckStatus" />


</androidx.constraintlayout.widget.ConstraintLayout>
  • Create drawable resource file for bg_receipt in android:background="@drawable/bg_receipt"
  • Give Root elemet name shape and click OK.
  • On bg_receipt.xml, insert the following code and save:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/white" />
    <stroke
        android:width="1px"
        android:color="@color/black" />
</shape>
  • Back to layout_transaction_receipt.xml, Create string value resource for refresh_status in android:text="@string/refresh_status"
  • Give Resource value name Refresh Status and click OK.
  • Save the file.

Alt text

Step 15: Create adapter for transaction receipts

  • Go to app > src > main > java > com > android > mydemo
  • Select mydemo > right-click > select New > Kotlin Class/File.
    • Give Class name TransactionReceiptAdapter.
    • In TransactionReceiptAdapter.kt , insert the following code and save file:
class TransactionReceiptAdapter(private val listener: TransactionActionListener) :
    RecyclerView.Adapter<TransactionReceiptAdapter.TransactionViewHolder>() {

    /**
     * List of [com.kachyng.rmssdk.repository.model.Transaction] for adapter reference.
     */
    private val arrayList = arrayListOf<Transaction>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
        //Create viewHolder for the album
        return TransactionViewHolder(parent)
    }

    override fun getItemCount() = arrayList.size //Count of terminals

    override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) {
        //Bind the terminal into viewHolder
        holder.bind(arrayList[position])

        //Add click listeners
        holder.btCheckStatus.setOnClickListener {
            listener.onRefreshClicked(arrayList[position])
        }

        holder.btCancelTransaction.setOnClickListener {
            Log.e("UrlTransaction", "onBindViewHolder: " + arrayList[position]._links.self.href)
            listener.onCancelTransaction(arrayList[position],position)
        }
    }

    /**
     * Updates the terminal list.
     *
     * @param items New list of [TerminalResource].
     */
    fun updateData(items: List<Transaction>) {
        //Clear old terminals
        arrayList.clear()
        //Add new terminals
        arrayList.addAll(items)
        //Notify the adapter for the change
        notifyDataSetChanged()
    }

    /**
     * View holder for adapter.
     */
    class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        /**
         * Title view for the terminal list view item.
         */
        private val tvTransactionId: TextView = itemView.findViewById(R.id.tvTransactionId)
        private val tvTransactionAmount: TextView = itemView.findViewById(R.id.tvTransactionAmount)
        private val tvTransactionStage: TextView = itemView.findViewById(R.id.tvTransactionStage)
        private val tvTransactionStatus: TextView = itemView.findViewById(R.id.tvTransactionStatus)
        private val tvTransactionType: TextView = itemView.findViewById(R.id.tvTransactionType)
        private val tvCashBackAmount: TextView = itemView.findViewById(R.id.tvCashBackAmount)
        private val tvFinalTransactionAmount: TextView = itemView.findViewById(R.id.tvFinalTransactionAmount)
        val btCheckStatus: TextView = itemView.findViewById(R.id.btCheckStatus)
        val btCancelTransaction: TextView = itemView.findViewById(R.id.btCancelTransaction)

        constructor(parent: ViewGroup) : this(
            LayoutInflater.from(parent.context).inflate(
                R.layout.layout_transaction_receipt, parent, false
            )
        )

        /**
         * Binds the terminal data to list view item.
         *
         * @param item [TerminalResource] containing terminal data.
         */
        fun bind(item: Transaction) {
            with(item) {
                //Set title of the album
                tvTransactionAmount.text = Html.fromHtml(
                    "<b>Transaction Amount: </b>${(amount.toDouble() / 100)} $currencyCode",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionId.text = Html.fromHtml(
                    "<b>Transaction Id: </b>$transactionRefId",
                    Html.FROM_HTML_MODE_LEGACY
                )

                tvTransactionStage.text = Html.fromHtml(
                    "<b>Transaction Stage: </b>$transactionStage",
                    Html.FROM_HTML_MODE_LEGACY
                )

                if (null != transactionStatus) {
                    tvTransactionStatus.visibility = View.VISIBLE
                    tvTransactionStatus.text = Html.fromHtml(
                        "<b>Transaction Status: </b>$transactionStatus",
                        Html.FROM_HTML_MODE_LEGACY
                    )
                } else {
                    tvTransactionStatus.visibility = View.GONE
                }


                tvTransactionType.text = Html.fromHtml(
                    "<b>Transaction Type: </b>$transactionType",
                    Html.FROM_HTML_MODE_LEGACY
                )

                if (item.amountCashback>0) {
                    tvCashBackAmount.visibility = View.VISIBLE
                    tvFinalTransactionAmount.visibility = View.VISIBLE

                    tvCashBackAmount.text = Html.fromHtml(
                        "<b>Cashback Amount: </b>${(amountCashback.toDouble() / 100)} $currencyCode",
                        Html.FROM_HTML_MODE_LEGACY
                    )

                    tvFinalTransactionAmount.text = Html.fromHtml(
                        "<b>Final Transaction Amount: </b>${(finalTransactionAmount.toDouble() / 100)} $currencyCode",
                        Html.FROM_HTML_MODE_LEGACY
                    )

                } else {
                    tvCashBackAmount.visibility = View.GONE
                    tvFinalTransactionAmount.visibility = View.GONE
                }



            }
        }
    }
}
  • Create Interface for TransactionActionListener in class TransactionReceiptAdapter(private val listener: TransactionActionListener) :
  • Choose Extract to separate file
  • Select Destination package in com.android.mydemo and click OK
  • On TransactionActionListener.kt, insert the following code and save:
interface TransactionActionListener {
    fun onCancelTransaction(transaction: Transaction, position: Int)
    fun onRefreshClicked(transaction: Transaction)

}

Alt text

Step 16: Add listing into pay screen design

  • Open fragment_make_transaction.xml before </androidx.constraintlayout.widget.ConstraintLayout>, Insert the following code and save:
<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvReceipts"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginVertical="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@id/tvEnterAmount"
        app:layout_constraintStart_toStartOf="@id/tvEnterAmount"
        app:layout_constraintTop_toBottomOf="@id/btCancel" />

Alt text

Step 17: Create style for loader

  • On the folder res, select folder values and open themes.xml
  • In themes.xml before </resources>, Insert the following code and save:
<style name="TransparentProgressDialog" parent="android:Theme.Material.Light.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowTitleStyle">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:background">@android:color/transparent</item>
    </style>

Alt text

Step 18: Create progress loader

  • Go to app > src > main > java > com > android > mydemo
  • Select mydemo > right-click > select New > Kotlin Class/File.
    • Give Class name TransparentProgressDialog.
    • In TransparentProgressDialog.kt , insert the following code and save file:
class TransparentProgressDialog(context: Context) :
    Dialog(context, R.style.TransparentProgressDialog) {

    init {
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        window?.attributes?.gravity = Gravity.CENTER_HORIZONTAL
        setTitle(null)
        setCancelable(false)
        setOnCancelListener(null)

        val layout = FrameLayout(context)
        val params = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        val progressBar = ProgressBar(context)
        layout.addView(progressBar, params)
//        layout.addView(ProgressBar(context), params)
        addContentView(layout, params)
    }
}

Alt text

💬 We're here to help!

If you're looking for help, shoot us an email. Please include a description of the issues that you are running into.