Skip to content

Commit 572193d

Browse files
Merge pull request #218775 from enricohuang/android-wv-1
Add Android WebView Quickstart document
2 parents bd88ec6 + b974071 commit 572193d

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
ms.author: enricohuang
3+
title: Azure Communication Calling Web SDK in Android WebView environment
4+
titleSuffix: An Azure Communication Services document
5+
description: In this quickstart, you'll learn how to integrate Azure Communication Calling WebJS SDK in an Android WebView environment
6+
author: sloanster
7+
services: azure-communication-services
8+
ms.date: 12/9/2022
9+
ms.topic: quickstart
10+
ms.service: azure-communication-services
11+
ms.subservice: calling
12+
---
13+
# Android WebView quickstart
14+
15+
[!INCLUDE [Public Preview](../../includes/public-preview-include-document.md)]
16+
17+
Webview technology is an embeddable browser that can be integrated directly into a native mobile application. If you want to develop an ACS calling application directly a native Android application, besides using the Azure Communication Calling Android SDK, you can also use Azure Communication Calling Web SDK on Android WebView. In this quickstart, you'll learn how to run webapps developed with the Azure Communication Calling Web SDK in an Android WebView environment.
18+
19+
## Prerequisites
20+
21+
- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F).
22+
- [Android Studio](https://developer.android.com/studio), for creating your Android application.
23+
- A web application using the Azure Communication Calling Web SDK. [Get started with the web calling sample](../../samples/web-calling-sample.md).
24+
25+
This quickstart guide assumes that you already have an Android WebView application.
26+
If you don't have one, you can [download the WebViewQuickstart sample app](https://github.com/Azure-Samples/communication-services-android-quickstarts/tree/main/WebViewQuickstart).
27+
28+
If you use the [WebViewQuickstart sample app](https://github.com/Azure-Samples/communication-services-android-quickstarts/tree/main/WebViewQuickstart),
29+
all the necessary configurations and permission handling are in place. You can skip to Known Issues.
30+
All you have to do is update the `defaultUrl` in `MainActivity` to the url of the calling web application you deployed and build the application.
31+
32+
## Add permissions to application manifest
33+
34+
To request the permissions required to make a call, you must declare the permissions in the application manifest. (app/src/main/AndroidManifest.xml)
35+
Make sure you have the following permissions added to the application manifest:
36+
```xml
37+
<uses-permission android:name="android.permission.INTERNET" />
38+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
39+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
40+
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
41+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
42+
<uses-permission android:name="android.permission.CAMERA" />
43+
```
44+
45+
## Request permissions at run time
46+
Adding permissions to the application manifest isn't enough. You must also [request the dangerous permissions at runtime](https://developer.android.com/training/permissions/requesting) to access camera and microphone.
47+
48+
You have to call `requestPermissions()` and override `onRequestPermissionsResult`.
49+
Besides app permissions, you have to handle browser permission requests by overriding `WebChromeClient.onPermissionRequest`
50+
51+
The [WebViewQuickstart sample app](https://github.com/Azure-Samples/communication-services-android-quickstarts/tree/main/WebViewQuickstart)
52+
also shows how to handle permission requests from browser and request app permissions at runtime.
53+
54+
## WebView configuration
55+
Azure Communication Calling Web SDK requires JavaScript enabled.
56+
In some cases, we saw `play() can only be initiated by a user gesture` error message in Android WebView environment, and users aren't able to hear incoming audio.
57+
Therefore, we recommend setting `MediaPlaybackRequiresUserGesture` to false.
58+
59+
```java
60+
WebSettings settings = webView.getSettings();
61+
settings.setJavaScriptEnabled(true);
62+
settings.setMediaPlaybackRequiresUserGesture(false);
63+
```
64+
65+
## Known issues
66+
67+
### MediaDevices.enumerateDevices() API returns empty labels
68+
69+
It's a [known issue](https://bugs.chromium.org/p/chromium/issues/detail?id=669492) on Android WebView.
70+
The issue will affect the following API in Web SDK:
71+
72+
- DeviceManager.getCameras()
73+
- DeviceManager.getMicrophones()
74+
- DeviceManager.getSpeakers() (If the device supports speaker enumeration)
75+
76+
The value of name field in the result object will be an empty string. This issue won't affect the function of streaming in the video call but the application users won't be able to know the camera label they select for sending the video.
77+
To provide a better UI experience, you can use the following workaround in the web application to get device labels and map the label by `deviceId`.
78+
79+
Although we can't get device labels from MediaDevices.enumerateDevices(), we can get the label from MediaStreamTrack.
80+
This workaround requires the web application to use getUserMedia to get the stream and map the `deviceId`.
81+
If there are many cameras and microphones on the Android device, it may take a while to collect labels.
82+
83+
```js
84+
async function getDeviceLabels() {
85+
const devices = await navigator.mediaDevices.enumerateDevices();
86+
const result = {};
87+
for (let i = 0; i < devices.length; i++) {
88+
const device = devices[i];
89+
if(device.kind != 'audioinput' && device.kind != 'videoinput') continue;
90+
if(device.label) continue;
91+
const deviceId = device.deviceId;
92+
const deviceConstraint = {
93+
deviceId: {
94+
exact: deviceId
95+
}
96+
};
97+
const constraint = (device.kind == 'audioinput') ?
98+
{ audio: deviceConstraint } :
99+
{ video: deviceConstraint };
100+
try {
101+
const stream = await navigator.mediaDevices.getUserMedia(constraint);
102+
stream.getTracks().forEach(track => {
103+
let namePrefix = '';
104+
if (device.kind == 'audioinput') {
105+
namePrefix = 'microphone:';
106+
} else if(device.kind == 'videoinput') {
107+
namePrefix = 'camera:';
108+
}
109+
if (track.label === '' && deviceId == 'default') {
110+
result[namePrefix + deviceId] = 'Default';
111+
} else {
112+
result[namePrefix + deviceId] = track.label;
113+
}
114+
track.stop();
115+
});
116+
} catch(e) {
117+
console.error(`get stream failed: ${device.kind} ${deviceId}`, e);
118+
}
119+
}
120+
return result;
121+
}
122+
```
123+
124+
:::image type="content" source="./media/android-webview/get-device-label.png" alt-text="Screenshot of getDeviceLabels() result.":::
125+
126+
After you get the mapping between deviceId and label, you can use it to relate the label with the `id` from `DeviceManager.getCameras()` or `DeviceManager.getMicrophones()`
127+
128+
:::image type="content" source="./media/android-webview/device-name-workaround.png" alt-text="Screenshot showing the device name workaround.":::
129+
130+
## Next steps
131+
132+
For more information, see the following articles:
133+
134+
- Learn about [Calling SDK capabilities](./getting-started-with-calling.md?pivots=platform-web)
135+
- Learn more about [how calling works](../../concepts/voice-video-calling/about-call-types.md)
138 KB
Loading
44.5 KB
Loading

0 commit comments

Comments
 (0)