Skip to content

5.4 (Optional) Webservice Option

Use the webservice option when your Android setup should expose NIMMSTA functionality through the Web Library or the Websocket API, or when you want silent deployment without a separate websocket app.

The most important distinction is this:

  • NIMMSTAWebServiceConnection starts and binds the SDK-local WebService that ships with the Android Core Library.
  • It does not bind to an already installed NIMMSTA Android app.

If you want a helper that automatically resolves the installed app package and supports Standard App, Intent App, Webserver App, and a preferred custom package, use the Intent Library webservice connection documentation.

Choose the right setup by app type

App type Recommended setup Why
Native Android app that only uses Core SDK APIs directly Do not use the webservice option NIMMSTAServiceConnection is enough for direct device access
Native Android app that embeds its own web UI or wants to expose a local websocket endpoint Use NIMMSTAWebServiceConnection The helper starts the bundled WebService in your app and connects it to the local NIMMSTAConnectionManager
Separate Android app, browser app, or PWA on the same device that should talk to NIMMSTA Bind to the installed NIMMSTA app's webservice Your app stays decoupled from Core SDK lifecycle and updates
Xamarin, .NET MAUI, or other non-native mobile app where direct Android SDK integration is not ideal Prefer the websocket integration or the Intent Library This matches the recommended app-to-app integration path

Approach 1: Bind to the webservice of an installed NIMMSTA app

Use this when the NIMMSTA Android app is already installed on the device and should host the webservice for your integration.

This is the better choice for:

  • browser-based apps running on the device
  • a second Android app that should talk to NIMMSTA without embedding the Core SDK webservice
  • setups where NIMMSTA app updates should deliver webservice improvements independently of your app release

Step 1: Add package visibility to AndroidManifest.xml

Declare the installed app packages you want to query before binding to the external service.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

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

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

    <application>
        <!-- Your application's components here -->
    </application>
</manifest>

Step 2: Create a ServiceConnection

Define a connection object that keeps the external binder reference and reacts to connect and disconnect events:

import android.content.ComponentName
import android.content.ServiceConnection
import android.os.IBinder

class InstalledWebServiceConnection : ServiceConnection {
    var binder: IBinder? = null

    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
        binder = service
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        binder = null
    }
}
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;

public class InstalledWebServiceConnection implements ServiceConnection {
    private IBinder binder;

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = service;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        binder = null;
    }
}

Step 3: Bind to the installed app

Try the packages in order until one bind succeeds. If you already use the Intent Library, prefer its built-in helper instead of reimplementing this loop.

Current Webserver App builds also use com.nimmsta, so there is no separate webserver package to add here.

private fun bindInstalledWebservice(customPackageName: String? = null): Boolean {
    val serviceConnection = InstalledWebServiceConnection()
    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.webservice.WebService"
            )
            flags += Intent.FLAG_INCLUDE_STOPPED_PACKAGES
        }

        val didBind = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            applicationContext.bindService(
                intent,
                serviceConnection,
                Context.BIND_ALLOW_ACTIVITY_STARTS or Context.BIND_AUTO_CREATE
            )
        } else {
            applicationContext.bindService(
                intent,
                serviceConnection,
                Context.BIND_AUTO_CREATE
            )
        }

        if (didBind) {
            return true
        }
    }

    return false
}
private boolean bindInstalledWebservice(String customPackageName) {
    InstalledWebServiceConnection serviceConnection = new InstalledWebServiceConnection();
    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.webservice.WebService"
        ));
        intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

        boolean didBind;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            didBind = getApplicationContext().bindService(
                intent,
                serviceConnection,
                Context.BIND_ALLOW_ACTIVITY_STARTS | Context.BIND_AUTO_CREATE
            );
        } else {
            didBind = getApplicationContext().bindService(
                intent,
                serviceConnection,
                Context.BIND_AUTO_CREATE
            );
        }

        if (didBind) {
            return true;
        }
    }

    return false;
}

Unbind the service again when the owning component is destroyed.

Approach 2: Start the webservice inside your own Android app with NIMMSTAWebServiceConnection

Use this when your app already includes the Android Core Library and should host the webservice itself.

This is the right choice for:

  • native Android apps that ship their own local HTML or Web Library frontend
  • kiosk-style apps that expose a websocket endpoint locally
  • single-APK solutions where Bluetooth connection management and webservice hosting should live in the same app

NIMMSTAWebServiceConnection.bindServiceToContext(...) binds to the bundled WebService, which in turn:

  1. binds to NIMMSTAConnectionManagerService
  2. enables background notifications for connected devices
  3. starts the websocket server once the service is ready

The helper returns immediately. Use onSuccess or onComplete before assuming that the webserver is already running.

Manifest notes for the local approach

  • You do not need the <queries> block from Approach 1, because this setup stays inside your own app.
  • The Android library already declares NIMMSTAConnectionManagerService and WebService in its manifest, so standard manifest merging is usually enough.
  • If your project does not merge library manifests, make sure those service declarations stay present in your app manifest.

Basic usage

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.nimmsta.core.android.webservice.NIMMSTAWebServiceConnection

class MainActivity : AppCompatActivity() {
    private var webServiceConnection: NIMMSTAWebServiceConnection? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        webServiceConnection = NIMMSTAWebServiceConnection
            .bindServiceToContext(applicationContext)
            .onSuccess {
                // The websocket server is ready on the default port 64693.
            }
            .onError { throwable ->
                Toast.makeText(this, throwable.message, Toast.LENGTH_LONG).show()
            }
    }

    override fun onDestroy() {
        webServiceConnection?.close()
        super.onDestroy()
    }
}
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.nimmsta.core.android.webservice.NIMMSTAWebServiceConnection;

public class MainActivity extends AppCompatActivity {
    private NIMMSTAWebServiceConnection webServiceConnection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        webServiceConnection = NIMMSTAWebServiceConnection
            .bindServiceToContext(getApplicationContext())
            .onSuccess(connection -> {
                // The websocket server is ready on the default port 64693.
            })
            .onError(throwable -> {
                Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_LONG).show();
            });
    }

    @Override
    protected void onDestroy() {
        if (webServiceConnection != null) {
            webServiceConnection.close();
        }
        super.onDestroy();
    }
}

Using a custom port

If your app should expose the server on a different local port, pass it when binding:

webServiceConnection = NIMMSTAWebServiceConnection
    .bindServiceToContext(applicationContext, port = 64694)
    .onSuccess {
        // Webservice is ready on ws://localhost:64694
    }
webServiceConnection = NIMMSTAWebServiceConnection
    .bindServiceToContext(getApplicationContext(), 64694)
    .onSuccess(connection -> {
        // Webservice is ready on ws://localhost:64694
    });

Lifecycle recommendations

  • Prefer applicationContext when binding the local webservice, because the webservice often outlives a single activity instance.
  • Keep the returned NIMMSTAWebServiceConnection reference and call close() when your app no longer needs the webservice.
  • If you need to start making websocket calls immediately after startup, do that from onSuccess, not directly after bindServiceToContext(...).