SmsForwarder Pure Client Mode: Use Cases and Implementation Guide

Pure Client Mode converts SmsForwarder into a remote-control client only, disabling all forwarding services while preserving manual SMS sending and device query capabilities.

The SmsForwarder repository (pppscn/SmsForwarder) provides a specialized operational state called Pure Client Mode that transforms the application from a message forwarder into a command-only client. This mode is controlled by the SettingUtils.enablePureClientMode boolean flag and is essential for deployments where a device must respond to remote instructions without automatically forwarding local notifications or SMS messages.

What Is Pure Client Mode?

Pure Client Mode is a runtime configuration stored under the shared preference key enable_pure_client_mode (defined in app/src/main/kotlin/cn/ppps/forwarder/utils/Constants.kt at line 86). When SettingUtils.enablePureClientMode is set to true, the application instantly disables its forwarding engine while maintaining client-side functionality. This behavior is implemented through early-return guards in the core service layer, ensuring that no SMS, notifications, or call states are intercepted or forwarded.

Core Components Disabled in Pure Client Mode

When Pure Client Mode is active, the following components immediately cease forwarding operations:

Active Features in Pure Client Mode

While forwarding services are disabled, the following client-only capabilities remain operational:

  • SMS Sending: The SmsSendFragment (app/src/main/kotlin/cn/ppps/forwarder/fragment/client/SmsSendFragment.kt, lines 90-92) allows users to send SMS messages from the device via the UI.
  • Device Queries: Client fragments can query stored SMS, call logs, contacts, battery level, and location, building signed HTTP requests to send to a remote server.
  • Remote Control: Wake-on-LAN, shell command execution, and other remote-control endpoints remain accessible through the client-only UI.
  • HTTP Client: The built-in HTTP client continues functioning for outgoing requests to the configured server.

Practical Use Cases for Pure Client Mode

Backup Phone Receiving Remote Commands Only

Deploy Pure Client Mode on secondary devices that should only execute commands from a primary "server" phone. The secondary device will not forward its own messages, maintaining a clean separation between server and client responsibilities.

Testing and Debugging the Client API

Developers can enable this mode to test remote-control endpoints—such as sending SMS or querying device data—without the noise of automatic forwarding processes interfering with API validation.

Battery-Saving Mode

Eliminate background listeners for notifications, SIM changes, and SMS interception to remove associated wake-locks. This significantly reduces power consumption while preserving manual control capabilities for urgent operations.

Privacy-First Deployment

In environments requiring a guarantee that the device never forwards local data, enabling Pure Client Mode ensures that no inbound SMS or notification is ever transmitted externally, creating an air-gapped client-only state.

Device-Limited Environments

On Android 13+ devices with strict background-execution restrictions, running SmsForwarder as a foreground UI-only client avoids system limits on background services while maintaining full remote-control functionality.

How to Enable and Use Pure Client Mode

Enable Pure Client Mode Programmatically

Set the flag via SettingUtils to disable all forwarding services:

// Located in app/src/main/kotlin/cn/ppps/forwarder/utils/SettingUtils.kt (lines 132-133)
SettingUtils.enablePureClientMode = true

This corresponds to the UI toggle found in SettingsFragment.kt (lines 1109-1112).

Send an SMS from the Client Side

The following pattern is used internally by SmsSendFragment to dispatch messages while in client mode:

val timestamp = System.currentTimeMillis()
val msgMap = mutableMapOf<String, Any>(
    "type" to "sms",
    "content" to "Hello from client",
    "timestamp" to timestamp
)

// Optional signature if a key is configured
val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) {
    msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
}

// Dispatch via the built-in HTTP client
HttpServerUtils.post("/send_sms", msgMap)

Query Device Battery Level

While in Pure Client Mode, you can still query device state and send results to the server:

val request = mapOf(
    "action" to "queryBattery",
    "timestamp" to System.currentTimeMillis()
)
HttpServerUtils.post("/client_query", request) { response ->
    Log.d("Client", "Battery info: $response")
}

Summary

  • Pure Client Mode disables all forwarding services (NotificationService, SmsReceiver, ForegroundService) via early-return checks when enable_pure_client_mode is true.
  • The mode preserves client-side functionality including manual SMS sending, device queries, and remote command execution through the HTTP client.
  • Ideal for backup devices, API testing, battery conservation, privacy compliance, and Android 13+ background restriction compliance.
  • Configuration is managed through SettingUtils.enablePureClientMode with UI controls in SettingsFragment.kt.

Frequently Asked Questions

Does Pure Client Mode stop all background processes?

No, it specifically stops forwarding-related services such as NotificationService, ForegroundService, and broadcast receivers for SMS and calls. The HTTP client and UI remain active for client operations.

Can I still send SMS from the device in Pure Client Mode?

Yes, the client fragments—including SmsSendFragment (lines 90-92)—remain fully functional for manual SMS sending, as these use the outgoing HTTP client rather than the forwarding listeners.

How do I verify Pure Client Mode is active?

Check that the toggle in SettingsFragment.kt (line 1109) is enabled, or inspect logs to confirm that NotificationService.kt returns early at line 36 without processing notification posts.

Is the HTTP server completely disabled in this mode?

Yes, HttpServerService.kt returns early at lines 30-45, preventing the device from accepting incoming HTTP requests. However, the app can still send outgoing requests to a remote server using the internal HTTP client.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →