Skip to content

Create your own Intents

Introduction

This documentation describes how you can communicate with the NIMMSTA app and the HS-50 scanner without using the higher-level NIMMSTAIntentConnection.

If you still use the Intent Library but want lower-level access, prefer these helpers first:

  • NIMMSTAIntentServiceConnection.bindServiceToActivity(...) for the installed app's intent service
  • NIMMSTAWebServiceConnection.bindServiceToContext(...) for the installed app's webservice

Android Manifest

The following needs to be added to your AndroidManifest.xml in order to send intents to the NIMMSTA app and to resolve multiple installed app packages.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="com.nimmsta.intent.SERVICE" />

    <queries>
        <package android:name="com.nimmsta" />
        <package android:name="com.nimmsta.intent" />

        <!-- Optional custom package -->
        <package android:name="com.nimmsta.custom" />

        <intent>
            <action android:name="com.nimmsta.intent.SEND" />
        </intent>
    </queries>
</manifest>

Bind NIMMSTA Intent Service with the helper

Before you can send intents to the NIMMSTA app, you have to bind the installed app's NIMMSTAIntentService.

The helper supports this order automatically:

  1. Preferred custom package, if configured
  2. Standard App: com.nimmsta
  3. Intent App: com.nimmsta.intent
  4. Webserver App: current builds also use com.nimmsta
NIMMSTAService.preferredPackageName = "custom"

val serviceConnection = NIMMSTAIntentServiceConnection
    .bindServiceToActivity(applicationContext)
    .onComplete { task ->
        task.result
    }
NIMMSTAService.setPreferredPackageName("custom");

NIMMSTAIntentServiceConnection serviceConnection =
    NIMMSTAIntentServiceConnection.bindServiceToActivity(getApplicationContext())
        .onComplete(task -> {
            task.getResult();
            return null;
        });

Bind NIMMSTA Intent Service manually

If you do not want to use the helper, iterate over the package candidates yourself.

private fun bindIntentService(customPackageName: String? = null): Boolean {
    val packageNames = listOfNotNull(
        customPackageName,
        "com.nimmsta",
        "com.nimmsta.intent"
    ).distinct()

    val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            // connected
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            // disconnected
        }
    }

    for (packageName in packageNames) {
        val intent = Intent().apply {
            component = ComponentName(
                packageName,
                "com.nimmsta.core.android.intents.NIMMSTAIntentService"
            )
            flags += Intent.FLAG_INCLUDE_STOPPED_PACKAGES
        }

        val didBind = applicationContext.bindService(
            intent,
            serviceConnection,
            Context.BIND_AUTO_CREATE
        )

        if (didBind) {
            return true
        }
    }

    return false
}
private boolean bindIntentService(String customPackageName) {
    List<String> packageNames = new ArrayList<>();
    if (customPackageName != null && !customPackageName.isBlank()) {
        packageNames.add(customPackageName);
    }
    packageNames.add("com.nimmsta");
    packageNames.add("com.nimmsta.intent");

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // connected
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // disconnected
        }
    };

    for (String packageName : new LinkedHashSet<>(packageNames)) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(
            packageName,
            "com.nimmsta.core.android.intents.NIMMSTAIntentService"
        ));
        intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

        boolean didBind = getApplicationContext().bindService(
            intent,
            serviceConnection,
            Context.BIND_AUTO_CREATE
        );
        if (didBind) {
            return true;
        }
    }

    return false;
}

Start NIMMSTA Intent Service (Deprecated from app v7)

This is the older fallback if binding is not possible. Prefer binding first.

Note

Please make sure you install the NIMMSTA app before your app. Otherwise, the permissions may not be obtained correctly.

private fun startNimmstaIntentService(customPackageName: String? = null) {
    val packageNames = listOfNotNull(
        customPackageName,
        "com.nimmsta",
        "com.nimmsta.intent"
    ).distinct()

    for (packageName in packageNames) {
        val intent = Intent().apply {
            component = ComponentName(
                packageName,
                "com.nimmsta.core.android.intents.NIMMSTAIntentService"
            )
        }

        val serviceName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent)
        } else {
            startService(intent)
        }

        if (serviceName != null) {
            return
        }
    }

    throw IllegalStateException("Could not start NIMMSTA Intent service for any configured package.")
}
private void startNimmstaIntentService(String customPackageName) {
    List<String> packageNames = new ArrayList<>();
    if (customPackageName != null && !customPackageName.isBlank()) {
        packageNames.add(customPackageName);
    }
    packageNames.add("com.nimmsta");
    packageNames.add("com.nimmsta.intent");

    for (String packageName : new LinkedHashSet<>(packageNames)) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(
            packageName,
            "com.nimmsta.core.android.intents.NIMMSTAIntentService"
        ));

        ComponentName serviceName;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            serviceName = startForegroundService(intent);
        } else {
            serviceName = startService(intent);
        }

        if (serviceName != null) {
            return;
        }
    }

    throw new IllegalStateException("Could not start NIMMSTA Intent service for any configured package.");
}

Create Intent

To send intents to the NIMMSTA app, create the intent like this. The JSON in the extra called data follows the same structure as the JSON used by the websocket communication. To learn more about the JSON structure, see Protocol Overview.

val intent = Intent("com.nimmsta.intent.RECEIVE")
intent.putExtra("data", json.toString())
sendBroadcast(intent)
Intent intent = new Intent("com.nimmsta.intent.RECEIVE");
intent.putExtra("data", json.toString());
sendBroadcast(intent);

Receive Responses

Register a BroadcastReceiver like this to receive responses.

val intentFilter = IntentFilter().apply {
    addAction("com.nimmsta.intent.SEND")
}
val receiver = YourBroadcastReceiver(this)
registerReceiver(receiver, intentFilter)
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.nimmsta.intent.SEND");
YourBroadcastReceiver receiver = new YourBroadcastReceiver(this);
registerReceiver(receiver, intentFilter);

The responses can then be received as follows.

override fun onReceive(context: Context?, intent: Intent?) {
  val data = intent?.extras?.getString("data")
}
@Override
public void onReceive(Context context, Intent intent) {
  String data = intent.getExtras().getString("data");
}