|
| 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) |
0 commit comments