Developpers corner

How to install Android SDK

Getting started

 

Include the SDK in your project

Find the latest version of the library in the ZIP file. It should be named stimshop-sdk-commons-<X.Y.Z>.aar, where <X.Y.Z> is the release version.

  • Copy the AAR file into your application module's libs directory
  • Add the Jitpack repository to your root build.gradle:
allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
  • Add the following line to your application module's build.gradle file, in the dependencies section:
// This is required to locate the SDK's AAR file specified in the dependencies block
repositories {
    flatDir {
        dirs 'lib'
    }
}

dependencies {
    implementation 'com.google.guava:guava:24.1-android'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-jackson:2.3.0'
    implementation 'com.google.android.gms:play-services-ads:12.0.1'
    implementation 'net.sourceforge.jtransforms:jtransforms:2.4.0'
    implementation 'com.github.tozny:java-aes-crypto:1.1.0'

    // Stimshop SDK
    // Change stimshop-sdk-commons-release to the AAR file name you have
    // Usually stimshop-sdk-commons-x.y.z where x.y.z is the version number
    implementation(name: 'stimshop-sdk-commons-x.y.z', ext: 'aar') {
        transitive = true
    }
}

Now you can synchronize the project with the gradle files (either from the toolbar button or from the menu Tools > Android > Sync project with Gradle files.

TODO Using a Maven repository would allow the user to only specify the SDK dependency. All other dependencies would be pull automatically.

Get an API key

We assume you already have your API key to use the Stimshop services.

Update the application manifest

Add permissions

    <!-- ALLOW RECORDING AUDIO TO DETECT SIGNALS -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- INTERNET ACCESS REQUIRED TO CHECK API KEY AND GET RELATED SIGNALS -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- REQUIRED TO CHECK NETWORK AVAILABILITY -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- OPTIONAL, ONLY REQUIRED IF YOU WANT TO USER STIMSHOP API -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Note: If stimshop_notify_url is set to true in your stimshop.xml file, make sure to add the location permission.

Declare the services for detection

As of SDK version 4.1, this step is not needed anymore. The SDK already declares these services in its own manifest file and that one will be merged with your application manifest.

Add your custom permission

This step is only required if you plan to use the system broadcaster. If your application does not need to communicate with other applications, you can ignore it. The SDK will by default use a local broadcaster which does not transmit the messages outside of the application.

In order to prevent other apps from receiving your messages. You will have to create your own permission and declare you will use it:

    <permission
        android:name="<YOUR.PACKAGE.NAME>.permission.STIMSHOP_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="<YOUR.PACKAGE.NAME>.permission.STIMSHOP_MESSAGE" />

Note: it is important to follow the scheme <YOUR.PACKAGE.NAME>.permission.STIMSHOP_MESSAGE

Initialize the StimShop SDK

The StimShop SDK must be initialized in a custom application class.

package <YOUR.PACKAGE.NAME>;
import com.stimshop.sdk.common.StimShop;

public class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        StimShop.create(this)
            .enableDebug(BuildConfig.DEBUG) // This is optional
            .start();
    }
}

Don't forget to tell Android to use that custom class in your AndroidManifest.xml file:

    <application
        android:name="<YOUR.PACKAGE.NAME>.Application"
        ...

Configure the SDK

Using an XML resource file

The SDK can be configured using an XML file. You can create the file src/main/res/values/stimshop.xml in your application module's with the following content:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- STIMSHOP API KEY -->
    <string name="stimshop_api_key">12345678901234567890123456789012</string>

    <!-- YOUR CREDENTIALS -->
    <string name="stimshop_username">your_username</string>
    <string name="stimshop_password">your_password</string>

    <!-- CHANNELS TO ENABLE -->
    <integer-array name="stimshop_channels">
        <item>1</item>
        <!-- etc. -->
    </integer-array>

    <!-- DETECTORS TO ENABLE -->
    <string-array name="stimshop_detectors">
        <item>audio</item>
        <!-- <item>bluetooth_le</item> -->
    </string-array>

    <!-- MESSENGER TYPE (optional, defaults to local_broadcaster) -->
    <string name="stimshop_messenger">local_broadcaster</string>
</resources>

This file will automatically be used when you initialize the SDK in the application with the code snippet in the previous section.

Using Java code

However, if you prefer, you can also configure the SDK directly from code. In which case you don't need to create that XML file and you need to change the initialization code as below:

public class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        StimShop.create(this)
            .withConfiguration(
                    new JavaSdkConfiguration.Builder()
                            .apiKey("1234...")
                            .credentials("your_username", "your_password")
                            .channels(new int[]{2, 3})
                            .requestedDetectorTypes(new Detector.Type[]{
                                    Detector.Type.AUDIO,
                                    Detector.Type.BLUETOOTH_LE})
                            .build())
            .start();
    }
}

Implement the BroadcastReceiver

The StimShop SDK communicates with you via broadcast messages which is built in the Android SDK.

You have two options. You can either have a receiver which receives detection signals even when the application is not in foreground, or you can have a receiver which is tied to an activity.

Global receiver

First, register the receiver in your AndroidManifest.xml file:

    <receiver android:name="<YOUR.PACKAGE.NAME>.MyReceiver">
        <intent-filter>
            <action android:name="com.stimshop.sdk.action.RECEIVE_MESSAGES" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

Note: above, we assume the receiver will be implemented in the MyReceiver class located in the package <YOUR.PACKAGE.NAME> (replace with your own names).

Then create a class which overrides the methods your care about from the SDK's StimShopBroadcastReceiver class:

public class MyReceiver extends StimShopBroadcastReceiver {
    @Override
    protected void onSignalDetected(Context context, Detector.Type detectorType, String signalCode, Proximity proximity) {
        // Do something with that code
    }
}

Please note that depending on the configuration in the stimshop.xml, not all functions will be called. By default only the callback onSignalDetected would be called.

Finally, do not forget to initialize the receiver in your Application class:

// Start listening when the app starts
LocalBroadcastManager.getInstance(this).registerReceiver(
        new MyReceiver(),
        new IntentFilter(AbstractBroadcaster.ACTION_RECEIVE_MESSAGES));

You will then be able to dispatch the Stimshop's events to the other classes the way you prefer to, using for example EventBus, Otto or ordinary listeners.

Activity-related receiver

You don't need to declare the receiver in the manifest. Instead, you will register it directly from the activity. Here is a sample activity code:

public class MyActivity extends Activity {

    @Override
    protected void onResume() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocalBroadcaster.ACTION_RECEIVE_MESSAGES);
        LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, filter);
        super.onResume();
    }

    @Override
    protected void onPause() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
        super.onPause();
    }

    private StimShopBroadcastReceiver myReceiver = new StimShopBroadcastReceiver() {
        @Override
        protected void onSignalDetected(Context context, Detector.Type detectorType, String signalCode, Proximity proximity) {
            // Do something with that code
        }
    };
}

Listening Policy

You can start and stop listening whenever you want (provided the SDK is ready) by calling the StimShop methods startDetection() and stopDetection().

Detection is always a burden on the device's battery, so you should try as much as possible to detect only when necessary. If you need to keep detection enabled for a long period of time, the SDK will soon provide a way to enable/disable a power saving mode which would give better battery life in exchange for a higher detection latency.

Recommended: Let the user have the control over the background detection

  • As the Stimshop SDK relies on AudioRecord, other applications which are requiring the microphone can not instantiate their AudioRecord session while our own session is on (while detecting).

  • And because of the way the AudioRecord class was designed, an application which is using AudioRecord can not know or be notified when an external app is requesting the microphone.

  • What we recommend our users to do, is to let the user the control over the background detection (since the typical use case we are talking about is when another application in foreground is asking for the microphone). This is basically what we have done in our own apps, like ucheck.in.

The critical apps like the telephone calls are not concerned though.

  • Example below: Your users are now able to stop the background detection at any moment so they can Shazam

NB: This "is scanning" notification's code is available in the StimshopService in our demo app.

screenshot

How to install Stimshop iOS SDK

SDK-demo-iOS

Stimshop SDK demo application for iOS.

Installation of the SDK

Import the files to your xcode project

Import the header file StimshopSDK.h and the library file libStimshop_SDK.a into your iOS application project.

Configure your API key

We assume you already have your API key, allowing you to use Stimshop services.

Initialization of the SDK

  1. Initialize the SDK by calling the takeOffWithAPIKey: method on the StimshopSDK singleton :

    [[StimshopSDK sharedInstance] takeOffWithAPIKey:@"STIMSHOP-APIKEY"];
    

    Where STIMSHOP-APIKEY is the API key provided by Stimshop.

  2. Choose the frequency channels to work with and to listen to by calling the setActivatedChannels: method on the StimshopSDK singleton, with the proper bitmask :

    [[StimshopSDK sharedInstance] setActivatedChannels:channelOne]; // Activates channel 1
    
    [[StimshopSDK sharedInstance] setActivatedChannels:channelTwo|channelThree]; // Activates channel 2 and 3
    
    [[StimshopSDK sharedInstance] setActivatedChannels:channelOne|channelTwo|channelThree]; // Activates all channels
    

    Here are the frequencies related to the channels :

    • channelOne : from 17kHz to 18kHz
    • channelTwo : from 18kHz to 19kHz
    • channelThree : from 19kHz to 20kHz

Use of the SDK

Set the delegate

In the class you want to use to perform signal detection, declare the delegate which will implement the StimshopDelegate protocol, by calling the setDelegate: method on the SimshopSDK singleton :

[[StimshopSDK sharedInstance] setDelegate:self]; 
/* Use self if the delegate is an instance of the class in which you want the signal
 * detection to be performed.
 */

Implement the StimshopDelegate protocol methods

  1. Required methods

    • didDetectWavWithCode: is called whenever a correct and authorized code has been detected in the sound signal :

          /*! Called when a correct code has been detected in the sound signal
           * \param code The detected code
           */
          - (void)didDetectWavWithCode:(NSString *)code {
                  NSLog(@"CODE DETECTED : %@", code);
          }
      
    • didStopWithErrorMessage: is called when an error occurred during takeoff :

          /*! Called when an error occurred during take off.
           * \param message The corresponding error message
           */
          - (void)didStopWithErrorMessage:(NSString *)message {
                  NSLog(@"AN ERROR OCCURRED : %@", message);
          }
      

      Here are the two possible error messages :

      • stimshopErrorInvalidAPIKey : "API key is not valid anymore, starting canceled"
      • stimshopErrorInvalidID : "Invalid ID, starting canceled"
  2. Optional methods

    • didStopDetecting is called when the SDK stopped listening to signals :

          /*! Called when the SDK stopped listening to signals
           */
          - (void)didStopDetecting {
                  // Do something
          }
      
    • didReceiveWinUrl: is called whenever the detected code is related to an asset :

          /*! Called when the detected code is corresponding to an asset url
           * \param url The string representing the url of the asset
           */
          - (void)didReceiveWinUrl:(NSString *)url {
                  NSLog(@"ASSET URL : %@", url);
          }
      

Everything's now ready, let's start detecting !

The SDK can start listening to signals by calling the startListener method on the StimshopSDK singleton :

[[Stimshop_SDK sharedInstance] startListener];

When done, the SDK can be stopped by calling the stopListener method on the StimshopSDK singleton :

[[Stimshop_SDK sharedInstance] stopListener];

The isListening method notifies whether the SDK is listening to signal or not.

The isDetecting method notifies whether the SDK has detected a corred code.