Android Permissions¶
Libsoftphone needs Android permissions to access the microphone and other device features.
Some permissions are declared in the SDK's AndroidManifest.xml; others must be added by your app when enabling optional features.
A manifest declaration does not grant a runtime permission: your app must also handle permission requests and their results.
The manifest inventory below describes SDK 26.1; see the migration guide when upgrading from 25.3.
The Android SDK categorizes permissions into two main categories. You can read more about them and their impact to the users here:
Handling permission requests¶
SDK 26.1 and later¶
The permission API requires an explicit context.
Permission checks such as Permission.check(context, permission) accept a Context; requests that can show Android's permission dialog require a PermissionRequestLauncher.
Your app is responsible for providing a suitable activity context and managing its lifecycle.
Create an activity launcher and forward results¶
Use PermissionRequestLauncher.of(activity) to wrap the activity that will display permission dialogs.
The helper also accepts a Context that wraps an activity; it throws IllegalArgumentException if it cannot find an activity in that context chain.
An application or service context alone cannot be used with this helper.
Have the activity implement PermissionRequestLauncherOwner and pass that owner when reporting permission results:
import androidx.appcompat.app.AppCompatActivity
import cz.acrobits.libsoftphone.permission.Permission
import cz.acrobits.libsoftphone.permission.PermissionRequestLauncher
import cz.acrobits.libsoftphone.permission.PermissionRequestLauncherOwner
class MainActivity : AppCompatActivity(), PermissionRequestLauncherOwner {
private val permissionLauncher by lazy { PermissionRequestLauncher.of(this) }
override fun getPermissionRequestLauncher(): PermissionRequestLauncher =
permissionLauncher
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
Permission.onRequestPermissionResult(this, requestCode, permissions, grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
Keep the launcher scoped to its activity. If your SDK observer outlives the activity, have it obtain the current owner from your app's activity or navigation lifecycle management. Update that owner when activities change, and clear references when an activity is no longer available for permission dialogs. Avoid retaining a destroyed activity through its launcher.
Handle requests from the SDK¶
When the SDK needs a runtime permission, it invokes Observer.onPermissionRequested(permission, callback).
In your existing observer or Listeners implementation, obtain the current owner, pass its launcher to Permission.request(...), and forward the result to PermissionCallback.onResult(...).
For example, this listener accepts an app-provided function that returns the activity owner currently available for permission dialogs:
import cz.acrobits.libsoftphone.permission.Permission
import cz.acrobits.libsoftphone.permission.PermissionCallback
import cz.acrobits.libsoftphone.permission.PermissionRequestLauncherOwner
import cz.acrobits.libsoftphone.support.Listeners
class AppListeners(
private val currentPermissionOwner: () -> PermissionRequestLauncherOwner?
) : Listeners() {
override fun onPermissionRequested(permission: String, callback: PermissionCallback) {
val owner = currentPermissionOwner()
if (owner == null) {
// No activity is available to show a permission dialog.
callback.onResult(Permission.Status.DeniedForNow)
return
}
Permission.request(owner.permissionRequestLauncher, permission, callback::onResult)
}
}
Register your observer with Instance.setObserver(...) as part of SDK initialization.
The currentPermissionOwner function is supplied by your app; the SDK does not select an activity for you.
In the example, requests made without an available activity complete with DeniedForNow.
Your app can instead defer a request until an activity is ready, provided it eventually completes the callback.
Call the permission API on the main thread.
Permission.request(...) may invoke its result callback synchronously when the permission's status is already known.
SDK 25.3: legacy result reporting¶
For SDK 25.3, keep forwarding permission results using the overload without a launcher owner:
@MainThread
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] results)
{
Permission.onRequestPermissionResult(requestCode, permissions, results);
super.onRequestPermissionsResult(requestCode, permissions, results);
}
For more guidance on handling runtime permissions in Android, refer to the official Android documentation on Requesting Permissions at Runtime.
Refresh audio after a permission grant¶
With SDK 26.1 and later, notify the SDK after obtaining Bluetooth or microphone permission, including during an active call:
| Permission granted | SDK notification |
|---|---|
BLUETOOTH_CONNECT |
Instance.Audio.reloadAudioEndpoints() |
RECORD_AUDIO |
Instance.Audio.reloadAudioRecorderPermissions() |
Call these methods on the main thread after a successful grant, rather than on a denied result. See Managed Telecom integration for details.
Runtime permissions declared by the SDK¶
These permissions are declared in the SDK's AndroidManifest.xml.
Handle runtime requests through the integration described above so the SDK can use the corresponding features.
Request the permissions needed by the features your app uses:
-
RECORD_AUDIO This permission is required because libSoftphone needs to access the device's microphone to capture audio during VoIP calls.
-
READ_PHONE_STATE Used to retrieve the state of ongoing calls. Used to manage PhoneAccounts to be used with ConnectionService.
-
BLUETOOTH_CONNECT Used for Bluetooth device access on Android 12 (API 31) and later, including identifying connected audio devices. SDK
26.1declares this permission and the optionalandroid.hardware.bluetoothfeature, so your app does not need to duplicate them. After a successful runtime grant, callInstance.Audio.reloadAudioEndpoints()on the main thread. -
POST_NOTIFICATIONS Used to post non-exempt notifications on Android 13 (API 33) and later. SDK
26.1declares this permission; your app must still handle the runtime request where needed. This is not a prerequisite for starting a foreground service, and some call notifications can qualify for an exemption; see Android's notification permission guidance.
Required Foreground Service Permissions¶
SDK 26.1 declares the following foreground-service permissions and matching service types.
These are manifest permissions, not runtime permission dialogs; the associated microphone or camera access still needs a runtime grant.
As per the recent changes in the Google Play Console, these permissions need to be declared and a justification for their use needs to be provided. The explanations here should give you a good starting point for completing the foreground service declaration form.
Here is a list of the required foreground service permissions for libSoftphone:
-
FOREGROUND_SERVICE_PHONE_CALL Required to handle SIP registration and VoIP calls, must be added together with
MANAGE_OWN_CALLS. -
FOREGROUND_SERVICE_MICROPHONE Required to guarantee access to microphone during calls.
-
FOREGROUND_SERVICE_CAMERA Supports camera capture during outgoing video calls. The SDK also declares
cz.acrobits.libsoftphone.internal.process.ServiceBundle$CameraServicewithandroid:foregroundServiceType="camera". Your app must separately declare and requestCAMERAbefore camera use; see Android's camera foreground-service requirements.
Required Normal Permissions¶
There permission are granted by Android automatically and do not require any additional code to be written by the developer.
They are bundled within the library's AndroidManifest.xml file, ensuring that the necessary access is granted at runtime without additional configuration by developers.
As of writing they also do not require any justification in the Google Play Console.
Here is a list of the required normal permissions for libSoftphone:
-
FOREGROUND_SERVICE This is a baseline permission that is required if any Foreground Service is to be used.
-
INTERNET We need to access the internet to make and receive calls.
-
ACCESS_NETWORK_STATE This permission is required to check the network state and to determine if the device is connected to the internet.
-
ACCESS_WIFI_STATE This permission is required to check the WiFi state and to determine if the device is connected to a WiFi network.
-
CHANGE_NETWORK_STATE We use this to enforce calls to be made over WiFi, or Mobile Data.
-
VIBRATE This permission is required to vibrate the device when a call is received.
-
WAKE_LOCK Allows the SDK to keep the device awake while needed for its work.
-
MANAGE_OWN_CALLS This is an essential permission to properly support ConnectionService.
Bluetooth declarations when upgrading¶
In SDK 25.3, your app had to add BLUETOOTH_CONNECT and the optional android.hardware.bluetooth feature for Bluetooth device identification.
In SDK 26.1, both are included in the SDK manifest.
It also declares the legacy BLUETOOTH permission with android:maxSdkVersion="30" for older Android versions.
Review the merged manifest after upgrading; Bluetooth runtime access on Android 12 and later still requires a grant.
Optional Runtime Permissions¶
The permissions from this section enable additional features in the SDK that you might want to include depending on your final app's usecase.
These permissions are not included in the libSoftphone library's AndroidManifest.xml file.
It is up to the application developer to add the permissions to application's manifest and to request these permissions in the application's code.
Here is a list of the optional runtime permissions for libSoftphone:
-
CAMERA Required for camera capture when sending video. Your app must declare and request this permission even though SDK
26.1already declaresFOREGROUND_SERVICE_CAMERAand the camera foreground service. -
ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION To be used when your app is using the registration or call location policy features.
-
READ_CONTACTS This permission is used to access the device's contacts and enables contact matching for
CallEvents. -
CALL_PHONE This is used to place GSM calls from the SDK, e.g. as a fallback when VoIP is not available or not suitable.
Exact alarm access¶
SDK 26.1 also declares SCHEDULE_EXACT_ALARM.
It is used to periodically wake up the SDK in standard (non-push) incoming calls mode; push mode does not need it.
This is special app access, not a runtime permission requested through a standard permission dialog.
Optional Foreground Service Permissions¶
Same as the optional runtime permissions, these permissions are not included in the libSoftphone library's AndroidManifest.xml file.
As per the recent changes in the Google Play Console, these permissions need to be declared and a justification for their use needs to be provided. The explanations here should give you a good starting point for completing the foreground service declaration form.
- FOREGROUND_SERVICE_LOCATION The SDK uses this when your app is using the registration or call location policy features.