facebook noscript

How to Secure Sensitive Data Sent From Android Apps

September 3, 2018

How to Secure Sensitive Data Sent From Android Apps

Wherever there is sensitive data, there is also motivation for malicious third parties to try and steal it. In order to ensure your company’s sensitive information never gets leaked, it’s essential to take steps for securing it.

Let’s consider the scenario of sending sensitive data from an Android mobile device to your API server. How do you make sure that the data is safely received by the server?

By using VGS.

Secure sensitive data from android apps

It’s common for sensitive data such as credit card forms, personal data, or user credentials to be uploaded from mobile apps to API servers, but this doesn’t guarantee the data is received by the server safely. VGS bridges that gap. Check out the VGS getting started guide to get acquainted with the product and create your first vault.

If you need to secure PII, credit card, or bank account data sent from mobile devices, the VGS inbound routes would look similar to these:

image2

As soon as you’re set up, check out your inbound route vault URL. This will be used as a path for your upstream API server to which you send requests.

Now that you are set up in VGS, let’s see what using this on Android looks like. Typical Android apps use libraries like Retrofit or OkHttp for making HTTP calls. The code itself wouldn’t look much different from regular calls to your API. We’ll use httpbin service as our API:


package com.verygoodsecurity.samples.http

import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST

interface HttpbinService {
    @POST("post")
    fun post(@Body data: PiiData): Call<HttpbinResponse<PiiData>>

    @POST("post")
    fun post(@Body data: CardData): Call<HttpbinResponse<CardData>>

    @POST("post")
    fun post(@Body data: BankData): Call<HttpbinResponse<BankData>>
}
        val retrofit = Retrofit.Builder()
                .baseUrl(getString(R.string.vgs_proxy_url))
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        httpbinService = retrofit.create(HttpbinService::class.java)

Here the vgs_proxy_url string would look similar to this:

<string name="vgs_proxy_url">https://tntzklp0qzc.SANDBOX.verygoodproxy.com/</string>

In this case we’ll send personal SSN data. We’ll use an Android screen layout for entering data:

...

    <EditText
        android:id="@+id/editBankSsn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="numberSigned"
        android:hint="@string/ssn"
        android:layout_margin="8dp"
        android:maxLength="10"
        app:layout_constraintBottom_toTopOf="@id/btnBankSubmit"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="@id/editBankAccount"/>

    <Button
        android:id="@+id/btnBankSubmit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/submit"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="@id/textBankRedactedData"
        app:layout_constraintBottom_toBottomOf="@id/editBankSsn"/>

    <TextView
        android:id="@+id/textBankRedactedData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:layout_margin="8dp"
        android:textAppearance="@android:style/TextAppearance.Large"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="@id/textBankName"
        app:layout_constraintBottom_toBottomOf="@id/btnBankSubmit"/>

    ...

    <TextView
        android:id="@+id/textBankSsn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:gravity="center"
        android:textAppearance="@android:style/TextAppearance.Medium"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="@id/textBankAccount"/>

    ...

Check out content_bank.xml for the full XML layout.

With everything lined up, you can now easily send the data to your upstream API server. Just set an onClickListener for a button:


setSubmitClickListener(btnBankSubmit, {
           httpbinService.post(BankData(
                   editBankName.text.toString(),
                   editBankAccount.text.toString(),
                   editBankSsn.text.toString()
           ))
       }) {
           textBankRedactedData.text = getString(R.string.redacted_data)

           textBankName.text = getString(R.string.bankName, it.name)
           textBankAccount.text = getString(R.string.bankAccount, it.bankAccount)
           textBankSsn.text = getString(R.string.bankSsn, it.ssn)
       }


 private fun <T> setSubmitClickListener(btn: Button, httpPost: () -> Call<HttpbinResponse<T>>, printFunction: (T) -> Unit) {
        btn.setOnClickListener {
            progressBar.visibility = VISIBLE
            httpPost.invoke()
                    .enqueue(object : Callback<HttpbinResponse<T>> {
                        override fun onResponse(call: Call<HttpbinResponse<T>>?, response: Response<HttpbinResponse<T>>) {
                            printFunction.invoke(response.body()!!.json)
                            progressBar.visibility = GONE
                        }

                        override fun onFailure(call: Call<HttpbinResponse<T>>, t: Throwable?) {
                            Toast.makeText(this@DataSendActivity, "Unexpected Error", Toast.LENGTH_LONG).show()
                            progressBar.visibility = GONE
                        }
                    })
        }
    }

As a result, data in transit will be secured and your API will receive a token instead of the real SSN number: tok_sandbox_fMP3z4JUx8woswFg7WD2Ep.

Group 5

With this simple process, you can secure your data quickly, with zero additional lines of code.

Don't miss the next Developer Office Hours with our CTO

Join Us
Yuriy Yunikov

Yuriy Yunikov

Engineering Manager at VGS

Linkedin Icon

You Might Also Be Interested In...

Introducing VGS’s Account Validation
Payments
Introducing VGS’s Account Validation

Learn how VGS Account Validation uses card verification, CVC verification, AVS, and ANI to reduce payment failures and fraud, without exposing sensitive data. See why merchants and enterprise platforms trust VGS for secure payment operations.

May 28, 2026
PSP Vault vs. Independent Token Vault: How Merchants Should Choose
Payments
PSP Vault vs. Independent Token Vault: How Merchants Should Choose

PSP vault or independent token vault? Learn how credential storage impacts payment flexibility, network token portability, multi-processor routing, vendor lock-in, and when merchants should choose a neutral vault to scale globally.

May 27, 2026
VGS is the Universal Translation Layer for Agentic Protocols
Agentic
VGS is the Universal Translation Layer for Agentic Protocols

VGS is the universal translation layer for any agentic protocol. Through tokenization and protocol interoperability, VGS enables agents to communicate securely and seamlessly across any protocol stack.

May 15, 2026