User Guide for Android SDK

This Quick Start guide will walk you through the key concepts behind AIQ's SDK and the steps required to get the included sample application up and running so you can start experimenting with the SDK as soon as possible.

For a more comprehensive guide we have divided into 3 different tutorials, which AIQ's SDK collective currently supported:

The source code of the tutorials can be found here.

Quick Start

The section summarizes the steps to use aiqkit in your Android project.

To start, users would need to login to AIQ's client portal, obtain your app's unique AppID and Secret, ingest some materials into our CRM under your account.

Note

The App ID is shared across Operating Systems, including Android and iOS now, if the ingestion is shared

  • AppID and Ingestion
  • Add aiqkit as a Dependency
  • Initialize the SDK with AppID and Secret
  • Call image match API or invoke scanner

1. AppID and Ingestion

Before using the sdk, an AppID/Secret pair is required. This can be obtained from the client portal at https://client.aiq.tech/.
Note the staging server https://client.staging.aiq.tech/ is for trial users. You also need to ingest some image/pdf/video before you can search for them.

2. Add aiqkit as a Dependency

The library is available from both jcenter and mavenCentral.

Add aiqkit as a Dependency


dependencies {
    implementation "tech.aiq:aiqkit:0.9.4"
}
                    

3. Initlaize the SDK with AppID and Secret

In your Application class, initialize the SDK with AppID and Secret

initialize sdk


public class MyApplication extends Application {
 
 private static final String TAG = MyApplication.class.getSimpleName();
 
    @Override
    public void onCreate() {
        super.onCreate();
 
        Log.d(TAG, "MyApplication Started");
 
        String serverUrl = BuildConfig.AIQ_APP_SERVER;
 
        if (TextUtils.isEmpty(serverUrl)) {
            serverUrl = AIQKit.getServiceEndPoint(AIQKit.ServiceType.STAG);
            Log.d(TAG, "Using AIQ staging server");
        }
 
        //initialize aiqkit
        AIQKit.init(this, BuildConfig.AIQ_APP_ID, BuildConfig.AIQ_APP_SECRET, serverUrl);
        Log.d(TAG, "Initialized AIQKit SDK");
    }
}
                    

The code above assumes build configuration variables AIQ_APP_ID, AIQ_APP_SECRET are set, AIQ_APP_SERVER is optional. One way is put these values into gradle.properties and refer from build.gradle.

configure the app_id, app_secret etc


In build.gradle
    defaultConfig {
        .......
        buildConfigField('String', 'AIQ_APP_ID', "\"${AIQ_APP_ID}\"")
        buildConfigField('String', 'AIQ_APP_SECRET', "\"${AIQ_APP_SECRET}\"")
        buildConfigField('String', 'AIQ_APP_SERVER', "\"${AIQ_APP_SERVER}\"")
    }
 
In gradle.properties
      AIQ_APP_ID=<app id here>
      AIQ_APP_SECRET=<app secret here>
      AIQ_APP_SERVER=<service url here>
                    

You can retrieve the preset urls with AIQKit.getServiceEndPoint(AIQKit.ServiceType.STAG) for staging, and AIQKit.getServiceEndPoint(AIQKit.ServiceType.PROD) for production.

4. Call image match API or invoke scanner

After the sdk is initialised, the service is ready to use. You could use the service by passing a bitmap object in memory, a file from the storage or use the builtin image scanner.

4.1. Builtin Scanner

The sdk contains a builtin scanner which sends queries to AIQ backend server at a frequency at around 1fps until a query is matched. The response is usually a URL, and will be opened by an embedded webview. To start the scanner, add the following line. The best place to put this line is in event handler code, for example, a button's OnClick() handler.

start builtin scanner


public void OnClick(View view){
    AIQKit.startScanner(this); // "this" is a activity object
}
                    

startScanner(Activity) starts the builtin ScannerActivity, which is basically a live camera view with an animated scanner line overlay, indicating the scanner is actively sending queries.

4.2. Searching a static image

You can search an image file or a in-memory bitmap with the matchImage() function:

call the matchImage api


AIQKit.matchImage(image_data); // image data is either url of the image file, or a bitmap object
                    

The matchImage() function returnes a RxJava1.* Observable which you can either synchronously or asynchronously process the response.

The following code snippet calls the match function in blocking mode. Note that it is not a good idea to block the ui thread, in the worst case it may cause your application to crash.

wait for the response


Observable<AIQKit.MatchResult> result= AIQKit.matchImage(uri);
 // use blocking mode to wait for the result
 try {
     AIQKit.MatchResult matchResult = result.toBlocking().first();
     if (matchResult != null) {
         Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(matchResult.getPayload()));
         startActivity(myIntent);
     }
 } catch (Throwable t) {
     if (AIQKit.isImageNotFoundError(t.getCause())) {
         showToast("No match found");
     } else {
         showToast("Error: " + t.getMessage());
     }
 }
                    

Instead you should invoke matchImage() in asynchronous mode:

handle the response


Observable<AIQKit.MatchResult> result= AIQKit.matchImage(uri);
 
result.observeOn(AndroidSchedulers.mainThread()).subscribe(
        new Action1<AIQKit.MatchResult>() {
            @Override
            public void call(AIQKit.MatchResult result) {
                // take the returned payload as url and show it in browser window
                if (result != null) {
                    Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(result.getPayload()));
                    startActivity(myIntent);
                } else {
                    showToast("No match found");
                }
            }
        },
        new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                // check if the result is "no match found'
                if (AIQKit.isImageNotFoundError(throwable)) {
                    showToast("No match found");
                } else {
                    showToast("Error: " + throwable.getMessage());
                }
            }
        }
);