phase 3(android): RECORD_AUDIO permission + runtime request in MainActivity
Oboe fails silently to open the AAudio input stream without android.permission.RECORD_AUDIO, so the call audio would never actually flow even after phase 3's engine wiring. - AndroidManifest.xml: declare RECORD_AUDIO and MODIFY_AUDIO_SETTINGS, and android.hardware.microphone as a required feature. These files are the cargo-tauri-generated scaffold — nothing in .gitignore excludes them, so the intended Tauri 2 mobile workflow is to commit them once populated. - MainActivity.kt: override onCreate to call ActivityCompat.requestPermissions for the audio perms on first launch. The dialog shows exactly once; the grant is persisted per-package. onRequestPermissionsResult logs the outcome so we can spot failures in logcat. A full native Tauri permission plugin integration is deferred to Step 6 (polish) together with notifications, icon, and background service.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-feature android:name="android.hardware.microphone" android:required="true" />
|
||||
|
||||
<!-- AndroidTV support -->
|
||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.wzp_desktop"
|
||||
android:usesCleartextTraffic="${usesCleartextTraffic}">
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/main_activity_title"
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<!-- AndroidTV support -->
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.wzp.desktop
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
class MainActivity : TauriActivity() {
|
||||
companion object {
|
||||
private const val TAG = "WzpMainActivity"
|
||||
private const val AUDIO_PERMISSIONS_REQUEST = 4242
|
||||
private val REQUIRED_AUDIO_PERMISSIONS = arrayOf(
|
||||
Manifest.permission.RECORD_AUDIO,
|
||||
Manifest.permission.MODIFY_AUDIO_SETTINGS
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Request RECORD_AUDIO early so Oboe (inside libwzp_native.so) can open
|
||||
// the AAudio input stream without silently failing. The grant is
|
||||
// persisted, so after the first launch the dialog no longer appears.
|
||||
// MODIFY_AUDIO_SETTINGS is requested alongside because Oboe toggles the
|
||||
// audio mode to communication on some devices.
|
||||
val needsRequest = REQUIRED_AUDIO_PERMISSIONS.any {
|
||||
ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
if (needsRequest) {
|
||||
Log.i(TAG, "requesting audio permissions")
|
||||
ActivityCompat.requestPermissions(this, REQUIRED_AUDIO_PERMISSIONS, AUDIO_PERMISSIONS_REQUEST)
|
||||
} else {
|
||||
Log.i(TAG, "audio permissions already granted")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == AUDIO_PERMISSIONS_REQUEST) {
|
||||
val allGranted = grantResults.isNotEmpty() &&
|
||||
grantResults.all { it == PackageManager.PERMISSION_GRANTED }
|
||||
Log.i(TAG, "audio permissions result: allGranted=$allGranted grants=${grantResults.toList()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user