Just like on a phone, accessing sensitive hardware like the camera and microphone on AI glasses requires explicit user consent. These are considered glasses-specific permissions, and your app must request them at runtime, even if it already has the corresponding permissions on the phone.
Follow this guide to:
- Declare permissions in your app's manifest
- Request permissions
- Learn about the permissions user flow
Declare the permissions in your app's manifest
Before requesting permissions, you must declare them in your app's manifest
file using the <uses-permission> element. This declaration remains the
same whether the permission is for a phone or an AI-glasses-specific feature, but
you must still explicitly request it for glasses-specific hardware or
functionality.
<manifest ...>
<!-- Only declare permissions that your app actually needs. In this example,
we declare permissions for the microphone. -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application ...>
...
</application>
</manifest>
Request permissions
To request permissions for AI glasses, you use the ActivityResultLauncher
with the ProjectedPermissionsResultContract() method. You need to specify
which permissions your app requires, such as Manifest.permission.CAMERA
or Manifest.permission.RECORD_AUDIO. Provide a clear and concise
rationale explaining why your app needs these permissions. This rationale is
displayed to the user to help them make an informed decision.
class SampleGlassesActivity : ComponentActivity() {
// Register the permissions launcher
private val requestPermissionLauncher: ActivityResultLauncher<List<ProjectedPermissionsRequestParams>> =
registerForActivityResult(ProjectedPermissionsResultContract()) { results ->
// Check the result for the specific RECORD_AUDIO permission
if (results[Manifest.permission.RECORD_AUDIO] == true) {
onPermissionGranted()
} else {
onPermissionDenied()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Audio permission is critical for the displayless AI glasses experience
checkAndRequestAudioPermission()
setContent {
GlimmerTheme {
DisplayGlassesUi()
}
}
}
// Checks for the required RECORD_AUDIO permission and requests it if necessary.
private fun checkAndRequestAudioPermission() {
val permission = Manifest.permission.RECORD_AUDIO
val permissionStatus = ContextCompat.checkSelfPermission(this, permission)
if (permissionStatus == PackageManager.PERMISSION_GRANTED) {
// Permission is already granted
onPermissionGranted()
} else {
// Permission is not granted, request it
requestAudioPermission()
}
}
private fun requestAudioPermission() {
val params = ProjectedPermissionsRequestParams(
permissions = listOf(Manifest.permission.RECORD_AUDIO),
// The rationale should explain why this permission is needed.
// For displayless AI glasses, it's often the main input mechanism.
rationale = "Microphone access is essential for voice commands and features on these AI glasses."
)
requestPermissionLauncher.launch(listOf(params))
}
private fun onPermissionGranted() {
// Implement the logic for when the permission is granted
}
private fun onPermissionDenied() {
// Implement the logic for when the permission is denied.
// On displayless AI glasses, if the app requires voice/mic it should exit the activity if the critical permission is denied.
finish()
}
}
Key points about the code
- We create an
ActivityResultLauncherusing theProjectedPermissionsResultContract()method. The callback receives a map of permission names to their granted status. - The
requestAudioPermission()function builds aProjectedPermissionsRequestParamsobject. This object bundles the list of permissions we need and the user-facing rationale. - Calling
launch()on the launcher triggers the permission request user flow. - Your app should handle both granted and denied results gracefully in the launcher's callback.
Understand the permission request user flow
When you launch a permission request using the
ProjectedPermissionsResultContract() method, the system initiates a
coordinated user flow across both the AI glasses and the phone.
If your app already has an Activity displayed on the phone, you should use
Activity#requestPermissions(permissions, requestCode, deviceId), where
the deviceId comes from calling the getDeviceId() method on the
Context returned by calling
ProjectedContext.createProjectedDeviceContext().
During the permissions user flow, here is what your app and the user can expect:
On the AI glasses: An activity appears on the projected device (glasses), instructing the user to look at their phone to continue.
tts?.speak("Please review the permission request on your host device", TextToSpeech.QUEUE_ADD, null, "permission_request")On the phone: Concurrently, an activity launches on the host device (phone). This screen displays the rationale string you provided and gives the user the option to proceed or cancel.
On the phone: If the user accepts the rationale, a modified Android system permission dialog appears on the phone telling the user that they are granting the permission for the AI glasses device (not the phone), and the user can formally grant or deny the permission.
Receiving the result: After the user makes their final choice, the activities on both the phone and AI glasses are dismissed. Your
ActivityResultLaunchercallback is then invoked with a map containing the granted status for each requested permission.