Android

Add the Metamap button to your Android app.

Android Demo App

You can go to GitHub to download the MetaMap Android Java demo app.

Requirements

  • Android SDK size ~ 3.5 MB
  • Android OS version: v5.0 (API v21) or higher.
  • compileSdkVersion: 31
  • targetSdkVersion: 31
  • Kotlin: 1.6.21 or higher.

Install the MetaMap Android SDK

To install the MetaMap Android SDK using Gradle, you will need to do the following:

  • Ensure that your top-level build.gradle references to the following repository:

    mavenCentral()
    
  • Enable Java 1.8 source compatibility.

    android {
      compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
      }
    }
    
  • Add the following to your app-level gradle dependencies using your version of the MetaMap Android SDK:

    implementation ('com.metamap:android-sdk: <your MetaMap SDK version number>')
    

    For example, if you are using the MetaMap Android SDK version 3.35.0, you would include the following:

    implementation ('com.metamap:android-sdk:3.35.0')
    

Then sync your project with the gradle files.

Note The list below shows the libraries used by Metamap SDK in its latest version. If you use any of these libraries in your project it's important for you to use the same versions to avoid any crashes. The actual dependencies and their versions for each MetaMap SDK version can be found here.

  • androidx.appcompat:appcompat:1.3.1
  • androidx.recyclerview:recyclerview:1.2.1
  • androidx.constraintlayout:constraintlayout:2.1.4
  • androidx.lifecycle:lifecycle-process:2.2.0
  • androidx.lifecycle:lifecycle-common-java8:2.2.0
  • com.google.code.gson:gson:2.8.5
  • androidx.camera:camera-core:1.1.0
  • androidx.camera:camera-camera2:1.1.0
  • androidx.camera:camera-lifecycle:1.1.0
  • androidx.camera:camera-video:1.1.0
  • androidx.camera:camera-view:1.1.0
  • androidx.window:window:1.0.0
  • org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4
  • androidx.navigation:navigation-fragment-ktx:2.5.3
  • androidx.navigation:navigation-ui-ktx:2.5.3
  • androidx.exifinterface:exifinterface:1.3.6
  • io.coil-kt:coil:2.2.2
  • io.coil-kt:coil-svg:2.2.2
  • org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2
  • io.ktor:ktor-client-android:2.0.3
  • io.ktor:ktor-client-content-negotiation:2.0.3
  • io.ktor:ktor-client-logging-jvm:2.0.3
  • io.ktor:ktor-serialization-kotlinx-json:2.0.3
  • org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.32

Usage

  1. Add the MetamapButton to your layout

    <com.metamap.metamap_sdk.MetamapButton
    android:id="@+id/metamapButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:color="@color/metamapButtonColor"
    app:textColor="@color/metamapButtonTextColor"
    app:text="YOUR CUSTOM TEXT" />
    
  2. Call setParams with the following arguments to authorize the app and start verification:

    ParameterTypeRequired
    activityResultLauncher@NonNull ActivityResultLauncherOptional
    activity@NonNull ActivityRequired
    CLIENT_ID@NonNull StringRequired
    FLOW_ID@Nullable StringRequired
    BUTTON_TITLE@NonNull StringOptional
    METADATA
    Note Go to the Metadata section
    to learn more about using metadata
    @Nullable MetadataOptional
    requestCode@NonNull IntOptional

    Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.activity_main);
    
        ...
    
        this.<MetamapButton>findViewById(R.id.metamapButton).setParams(
            activityResultLauncher,
            this,
            "YOUR_CLIENT_ID",
            "YOUR_FLOW_ID",
            METADATA,
    	"configurationId", //optional
    	"encryptionConfigurationId"); //optional
    }
    

    or you can use onActivityResult

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.activity_main);
    
        ...
    
        this.<MetamapButton>findViewById(R.id.metamapButton).setParams(
            this,
            "YOUR_CLIENT_ID",
            "YOUR_FLOW_ID",
            new Metadata.Builder()
                    .additionalData("userId", "qwfguweo")
                    .additionalData("type", 2)
                    .build());
    }
    

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        setContentView(R.layout.activity_main);
    
        ...
    
        findViewById<MetamapButton>(R.id.metamapButton).setParams(
        	activityResultLauncher,
        	this,
            "YOUR_CLIENT_ID",
            "YOUR_FLOW_ID",
            METADATA)
    }
    

    or you can use onActivityResult

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        setContentView(R.layout.activity_main);
    
        ...
    
        findViewById<MetamapButton>(R.id.metamapButton).setParams(
        	this,
            "YOUR_CLIENT_ID",
            "YOUR_FLOW_ID",
            METADATA)
    }
    
  3. Listen for the result

    Java

    ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    Intent data = result.getData();
                    if (data == null) {
                        Toast.makeText(MainActivity.this, "Verification cancelled", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        // There are no request codes
                        Toast.makeText(
                                MainActivity.this,
                                "Verification success! " +
                                        "VerificationId:" + data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID) +
                                        "IdentityId: " + data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID),
                                Toast.LENGTH_SHORT
                        ).show();
                    } else {
                        Toast.makeText(
                                MainActivity.this,
                                "Verification cancelled! " +
                                        "VerificationId:" + data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID) +
                                        "IdentityId: " + data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID),
                                Toast.LENGTH_SHORT
                        ).show();
                    }
                });
    

    or you can use onActivityResult

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == MetamapSdk.DEFAULT_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK && data != null) {
                // There are no request codes
                Toast.makeText(
                        this,
                        "onActivityResult Verification success! " +
                                "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                        Toast.LENGTH_SHORT
                ).show();
            } else {
                if (data != null) {
                    Toast.makeText(
                            this,
                            "onActivityResult Verification cancelled! " +
                                    "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                    "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                            Toast.LENGTH_SHORT
                    ).show();
                } else {
                    Toast.makeText(
                            this,
                            "onActivityResult Verification cancelled!",
                            Toast.LENGTH_SHORT
                    ).show();
                }
            }
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
    

    Kotlin

    private val activityResultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                val data = result.data
                if (data == null) {
                    Toast.makeText(requireContext(), "Verification cancelled", Toast.LENGTH_SHORT)
                        .show()
                    return@registerForActivityResult
                }
                if (result.resultCode == Activity.RESULT_OK) {
                    // There are no request codes
                    Toast.makeText(
                        requireContext(),
                        "Verification success! " +
                                "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                        Toast.LENGTH_SHORT
                    ).show()
                } else {
                    Toast.makeText(
                        requireContext(),
                        "Verification cancelled! " +
                                "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
    

    or you can use onActivityResult

     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            if (requestCode == MetamapSdk.DEFAULT_REQUEST_CODE) {
                if (resultCode == Activity.RESULT_OK && data != null) {
                    // There are no request codes
                    Toast.makeText(
                        this,
                        "onActivityResult Verification success! " +
                                "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                        Toast.LENGTH_SHORT
                    ).show()
                } else {
                    if (data != null) {
                        Toast.makeText(
                            this,
                            "onActivityResult Verification cancelled! " +
                                    "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                    "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                            Toast.LENGTH_SHORT
                        ).show()
                    } else {
                        Toast.makeText(
                            this,
                            "onActivityResult Verification cancelled!",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }
            } else {
                super.onActivityResult(requestCode, resultCode, data)
            }
        }
    
  4. Check for your activity

    Java

    public class YourActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_main);
    
            this.<MetamapButton>findViewById(R.id.metamapButton).setParams(
            activityResultLauncher,
    	    this,
                "YOUR_CLIENT_ID",
                "YOUR_FLOW_ID",
                new Metadata.Builder()
                    .additionalData("key_1", "value1")
                    .additionalData("key2", 2)
                    .build());
        }
    
        ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
                        new ActivityResultContracts.StartActivityForResult(),
                        result -> {
                            Intent data = result.getData();
                            if (data == null) {
                                Toast.makeText(MainActivity.this, "Verification cancelled", Toast.LENGTH_SHORT).show();
                                return;
                            }
                            if (result.getResultCode() == Activity.RESULT_OK) {
                                // There are no request codes
                                Toast.makeText(
                                        MainActivity.this,
                                        "Verification success! " +
                                                "VerificationId:" + data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID) +
                                                "IdentityId: " + data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID),
                                        Toast.LENGTH_SHORT
                                ).show();
                            } else {
                                Toast.makeText(
                                        MainActivity.this,
                                        "Verification cancelled! " +
                                                "VerificationId:" + data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID) +
                                                "IdentityId: " + data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID),
                                        Toast.LENGTH_SHORT
                                ).show();
                            }
                        });
    }
    

    Kotlin

    class SecondActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_second)
    
            findViewById<MetamapButton>(R.id.metamapButton).setParams(
            activityResultLauncher,
    	    this,
                "YOUR_CLIENT_ID",
                "YOUR_FLOW_ID",
                Metadata.Builder()
                    .additionalData("key_1", "value1")
                    .additionalData("key2", 2)
                    .build(),
    	    "configurationId", //optional
    	    "encryptionConfigurationId") //optional
        }
    
        private val activityResultLauncher =
                    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                        val data = result.data
                        if (data == null) {
                            Toast.makeText(requireContext(), "Verification cancelled", Toast.LENGTH_SHORT)
                                .show()
                            return@registerForActivityResult
                        }
                        if (result.resultCode == Activity.RESULT_OK) {
                            // There are no request codes
                            Toast.makeText(
                                requireContext(),
                                "Verification success! " +
                                        "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                        "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                                Toast.LENGTH_SHORT
                            ).show()
                        } else {
                            Toast.makeText(
                                requireContext(),
                                "Verification cancelled! " +
                                        "VerificationId: ${data.getStringExtra(MetamapSdk.ARG_VERIFICATION_ID)}, " +
                                        "IdentityId: ${data.getStringExtra(MetamapSdk.ARG_IDENTITY_ID)}",
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                    }
    }
    

Metadata Usage

You can use metadata to set specific parameters, including setting a selected language and hiding the language selection to make it permanent.

key: fixedLanguage

value: locale code of language

Example: Set the Language Code for Spain

To set the language code for Spain to Spanish, we would set the fixedLanguage parameter to es.

Java


UIConfig uiConfig = new UIConfig(MetamapLanguage.SPANISH);

new Metadata.Builder()
                .uiConfig(uiConfig)
                .build();

Kotlin


val uiConfig = UIConfig(fixedLanguage = MetamapLanguage.SPANISH)

Metadata.Builder()
                .uiConfig(uiConfig)
                .build()

If you don't use MetamapButton, you can set the buttons' primary color and text color with metadata:

key: buttonColor
value: parsed color-int value

key: buttonTextColor
value: parsed color-int value

Example: Set button color red(#FF0000) and text color white(#FFFFFF)

Java


UIConfig uiConfig = new UIConfig(
                        null,
                        Color.parseColor("#EF0404"), //or ContextCompat.getColor(context, R.color.yourColor)
                        Color.parseColor("#FFFFFF") //or ContextCompat.getColor(context, R.color.yourColor)
                    );

new Metadata.Builder()
                .uiConfig(uiConfig)
                .build();

Kotlin


val uiConfig = UIConfig(
                    buttonColor = Color.parseColor("#EF0404"), //or ContextCompat.getColor(context, R.color.yourColor)
                    buttonTextColor = Color.parseColor("#FFFFFF") //or ContextCompat.getColor(context, R.color.yourColor)
                )

Metadata.Builder()
                .uiConfig(uiConfig)
                .build()

If you use MetamapButton, these values will be ignored and MetamapButton's colors will be applied to all screens.

Example: Set identityId for re-verification

To set the identity id you can use the Metadata builder method identityId like in the example below:

Java


new Metadata.Builder()
                .identityId("MY_IDENTITY_ID")
                .build();

Kotlin


Metadata.Builder()
                .identityId("MY_IDENTITY_ID")
                .build()

Example: other data

For other data you can use additionalData builder method providing key value pairs like in the example below:

Java


new Metadata.Builder()
                .additionalData("key1" "value")
                .additionalData("key2" 24)
                .build();

Kotlin


Metadata.Builder()
                .additionalData("key1" "value")
                .additionalData("key2" 32)
                .build()

Smart Capture

To enable document smart capture you should add jitpack.io to your repositories inside the settings.gradle file
and add smart capture dependency to your build.gradle

repositories {
    ...
    ...
    maven { url 'https://jitpack.io' }
}

implementation "com.metamap:android-sdk-smart-capture:0.2.0"

It will add extra MB to the app based on CPU architecture

  • armeabi-v7a: 3.1 MB
  • arm64-v8a: 5.6 MB
  • x86: 16.7 MB
  • x86_64: 25.1 MB

If you will add the smart capture dependency, it will automatically enable smart capture, if you want to enable/disable it manually, please use those methods

Java


MetamapSdk.INSTANCE.enableSmartCapture();
MetamapSdk.INSTANCE.disableSmartCapture();

Kotlin


MetamapSdk.enableSmartCapture()
MetamapSdk.disableSmartCapture()

Please note that the smart capture is still in beta.

Some error codes you may get during integration

402 - MetaMap services are not paid: please contact your customer success manager

403 - MetaMap credentials issues: please check your client id and MetaMap id