ws1-sdk-flutter
Use this document to install the Workspace One SDK Plugin for Flutter. The plugin helps enterprise app developers add enterprise-grade security, conditional access, and compliance capabilities to mobile applications.
Package installation
Add plugin as dependency to the application pubspec.yaml
dependencies:
flutter:
sdk: flutter
workspaceone_sdk_flutter:^26.1.4
$ dart pub get
Supported Components
This plugin works with the listed component versions.
- Workspace ONE UEM Console 2402+ (may need to be higher depending on specific features)
- Android 7.0+ (for Android SDK component) / API level 26 OR above / Android Studio with the Gradle Android Build System (Gradle) 8.12.1+ or later / Workspace ONE Intelligent Hub for Android version 25.08 or later
- iOS & iPadOS 16+ or later (for iOS SDK component) / Xcode 16.4+ or later
Initial Setup
Additional Setup
iOS
-
Add the AWSDK through Swift Package Manager. Click here for integrating the AWSDK framework through Swift Package Manager
-
Add following code in AppDelegate
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
//Add following code for posting Notification for URL
NSNotification *info = [[NSNotification alloc]initWithName:@"UIApplicationOpenURLOptionsSourceApplicationKey" object:url userInfo:options];
[[NSNotificationCenter defaultCenter] postNotification:info];
return YES;
}
- Add Post Install script in Podfile.
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
# Add this line to get the AWSDK Swift Package from SPM
$workspaceone_sdk_flutter.post_install(installer)
end
Android
- Modify AndroidManifest.xml for Main Launcher
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
</activity>
<activity
android:name="com.airwatch.gateway.ui.GatewaySplashActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- Update your Main Activity
import com.workspaceone_sdk_flutter.WorkspaceOneSdkActivity
class MainActivity: WorkspaceOneSdkActivity() {
}
- Add WS1EventImpl
import android.content.Context
import android.os.Bundle
import android.util.Log
import com.airwatch.sdk.profile.AnchorAppStatus
import com.airwatch.sdk.profile.ApplicationProfile
import com.airwatch.sdk.shareddevice.ClearReasonCode
import com.airwatch.event.WS1AnchorEvents
import org.koin.core.component.KoinComponent
class WS1EventImpl : WS1AnchorEvents,KoinComponent {
override fun onApplicationConfigurationChange(bundle: Bundle?, context: Context) {}
override fun onApplicationProfileReceived(context: Context, s: String, applicationProfile: ApplicationProfile) {
Log.d("SDK Init", "onApplicationProfileReceived")
}
override fun onClearAppDataCommandReceived(context: Context, clearReasonCode: ClearReasonCode) {
Log.d("SDK Init", "onClearAppDataCommandReceived")
}
override fun onAnchorAppStatusReceived(context: Context, anchorAppStatus: AnchorAppStatus) {}
override fun onAnchorAppUpgrade(context: Context, b: Boolean) {}
}
- Update your Android Application subclass as follows
- Declare that the class implements the WorkspaceOneSDKApplication interface.
- Move the code from the body of your onCreate method, if any, to an override of the AWSDKApplication onPostCreate method.
- Override the AWSDKApplication getMainActivityIntent() method to return an Intent for the application’s main Activity.
- Override the following Android Application methods:
- attachBaseContext
import com.workspaceone_sdk_flutter.WorkspaceOneSdkApplication
class MainApplication : WorkspaceOneSdkApplication() {
// Application-specific overrides : Comment onCreate() out and move the code to onPostCreate()
// @Override
// public void onCreate() {
// super.onCreate();
// }
// Application-specific overrides : Copy all the code from onCreate() to onPostCreate()
override fun onPostCreate() {
super.onPostCreate()
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
attachBaseContext(this)
}
override fun getMainActivityIntent(): Intent {
return Intent(this,MainActivity::class.java)
}
override fun getEventHandler(): WS1AnchorEvents {
return WS1EventImpl()
}
}
Feature Description
Initialization of the SDK adds the listed features to your application, depending on the configurations set in the SDK profile in the Workspace One UEM Console.
- Application level passcode
- Integrated authentication / single sign on
- Data loss prevention
- Disable Screenshot (Android only)
- Restrict open-in for documents, web links, and email to approved applications only Restrict copy/paste (SDK provides flag value)
- Restrict access to app when device is offline
- Branding of AirWatch splash screens when SDK application is launched on device
Feature Implementation
Please follow document at implementation.
Tunneling — Load URLs via WS1 Tunnel
The WS1 SDK provides App Tunnel functionality for Android to intercept and proxy network traffic through the enterprise gateway. To ensure HTTP calls are intercepted by the WS1 tunnel, use the loadURLViaTunnel method, which routes requests through the native Android networking layer where WS1 hooks are active.
Why Use loadURLViaTunnel?
- Direct Dart HTTP calls (
dart:ioHttpClient) bypass WS1 tunnel hooks ❌ - Native Android calls (
java.net.HttpURLConnection) are intercepted by WS1 ✅ loadURLViaTunnelroutes Flutter requests to native Android via MethodChannel for automatic tunnel interception
Usage
Dart (Flutter):
import 'package:flutter/services.dart';
static const _channel = MethodChannel('workspaceone_sdk_flutter');
Future<void> loadURLViaTunnel(String url) async {
try {
final Map result = await _channel.invokeMethod(
'loadURLViaTunnel',
{'url': url},
);
final int statusCode = result['statusCode'] as int;
final String body = result['body'] as String? ?? '';
print('Status: $statusCode');
print('Response: $body');
} on PlatformException catch (e) {
print('Error: ${e.message}');
}
}
// Call it with any URL
await loadURLViaTunnel('https://internal-resource.company.com/api/data');
Return Value:
Map<String, dynamic> {
'statusCode': 200, // HTTP status code (int)
'body': '<response text>' // Response body as String
}
Implementation Details
- Android Handler:
WorkspaceoneSdkFlutterPlugin.kt→"loadURLViaTunnel" - Native Layer: Uses
java.net.HttpURLConnectionon a background thread - Timeout: 15 seconds (connect + read)
- Follows Redirects: Enabled by default
- Error Handling: Returns
PlatformExceptionwith details on failure
Example: Tunneling Screen
See example/lib/tunneling.dart for a complete implementation with:
- URL input field
- HTTP response tab (raw response display)
- WebView tab (rendered page display)
- Status code display with color coding (green for 2xx, red for others)
Release Notes
- Latest versions of Workspace One SDKs (25.8.0 for iOS and 25.02.1 for Android).
Workspace One SDK Documentation
For further details about the Workspace One SDK, navigate to https://developer.omnissa.com/sdks/ and select the required platform, SDK version and Workspace ONE UEM console version.
Questions and Feedback
For any questions/feedback or to report an issue, please reach out to Omnissa Customer Connect