Android: fix digital assistant invocation with proxy activity and missing intent filters

This commit is contained in:
yishai 2026-01-28 18:29:01 +02:00
parent b5c0a66fb7
commit a3b467167f
3 changed files with 95 additions and 1 deletions

View File

@ -15,6 +15,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
@ -37,13 +38,56 @@
android:name=".NodeForegroundService"
android:exported="false"
android:foregroundServiceType="dataSync|microphone|mediaProjection" />
<service
android:name=".assistant.ClawdbotVoiceInteractionService"
android:exported="true"
android:permission="android.permission.BIND_VOICE_INTERACTION">
<intent-filter>
<action android:name="android.service.voice.VoiceInteractionService" />
</intent-filter>
<meta-data
android:name="android.voice_interaction"
android:resource="@xml/voice_interaction_service" />
</service>
<service
android:name=".assistant.ClawdbotVoiceInteractionSessionService"
android:exported="true"
android:permission="android.permission.BIND_VOICE_INTERACTION" />
<service
android:name=".assistant.ClawdbotRecognitionService"
android:exported="true"
android:permission="android.permission.BIND_RECOGNITION_SERVICE">
<intent-filter>
<action android:name="android.speech.RecognitionService" />
</intent-filter>
</service>
<activity
android:name=".assistant.AssistProxyActivity"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:noHistory="true"
android:taskAffinity="">
<intent-filter>
<action android:name="android.intent.action.ASSIST" />
<action android:name="android.intent.action.VOICE_ASSIST" />
<action android:name="android.intent.action.VOICE_COMMAND" />
<action android:name="android.intent.action.SEARCH_LONG_PRESS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.clawdbot.android.ACTION_ASSISTANT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,41 @@
package com.clawdbot.android.assistant
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import com.clawdbot.android.MainActivity
/**
* Invisible proxy activity that handles all assistant invocation intents.
* Extracts any assist data and forwards to MainActivity, then finishes immediately.
*
* This is a Theme.NoDisplay activity that serves as the entry point for:
* - Long-press home button (ACTION_ASSIST)
* - Voice assistant triggers (VOICE_ASSIST, VOICE_COMMAND)
* - Search button long-press (SEARCH_LONG_PRESS)
*/
class AssistProxyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("AssistProxyActivity", "onCreate: action=${intent?.action}")
// Extract any assist data from the triggering intent
val assistBundle = intent?.extras
// Launch the real assistant UI (MainActivity)
val launchIntent = Intent(this, MainActivity::class.java).apply {
action = "com.clawdbot.android.ACTION_ASSISTANT"
if (assistBundle != null) {
putExtras(assistBundle)
}
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
startActivity(launchIntent)
// Finish immediately (this activity is invisible)
finish()
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<voice-interaction-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:sessionService=".assistant.ClawdbotVoiceInteractionSessionService"
android:recognitionService=".assistant.ClawdbotRecognitionService"
android:settingsActivity=".MainActivity"
android:supportsAssist="true"
android:supportsLaunchVoiceAssistFromKeyguard="true"
android:supportsLocalInteraction="false" />