Embedding Whereby in Android
Learn how to embed Whereby rooms in your native Android app using the WebView class.
In order to embed a room in Android, add these permissions to the manifest:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
You will need to use the WebView class. Start by creating a custom WebChromeClient
class and override the onPermissionRequest
method:
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
public class CustomWebChromeClient extends WebChromeClient {
private Activity activity;
public CustomWebChromeClient(Activity parentActivity) {
super();
activity = parentActivity;
}
@Override
public void onPermissionRequest(final PermissionRequest request) {
activity.runOnUiThread(new Runnable() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void run() {
request.grant(request.getResources());
}
});
}
}
Then, create a WebViewUtils
helper class to configure the WebView. Here is a possible configuration:
import android.annotation.SuppressLint;
import android.webkit.CookieManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
public class WebViewUtils {
@SuppressLint("SetJavaScriptEnabled")
public static void configureWebView(WebView webView) {
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
}
}
Finally, set up your activity following these steps:
Configure the webView.
Request the permissions if needed.
Add the
?skipMediaPermissionPrompt
parameter to the room URL and load it.
Here is an example:
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public String roomUrlString = ""; // Replace by your own
private String roomParameters = "?skipMediaPermissionPrompt";
private static final int PERMISSION_REQUEST_CODE = 1234;
private String[] requiredDangerousPermissions = {
Manifest.permission.CAMERA,
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.RECORD_AUDIO
};
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.webView = findViewById(R.id.webView);
WebViewUtils.configureWebView(this.webView);
this.webView.setWebChromeClient(new CustomWebChromeClient(this));
this.webView.setWebViewClient(new WebViewClient());
}
@Override
protected void onResume() {
super.onResume();
if (this.webView.getUrl() == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && this.isPendingPermissions()) {
// This explicitly requests the camera and audio permissions.
// It's fine for a demo app but should probably be called earlier in the flow,
// on a user interaction instead of onResume.
this.requestCameraAndAudioPermissions();
} else {
this.loadEmbeddedRoomUrl();
}
}
}
private void loadEmbeddedRoomUrl() {
this.webView.loadUrl(roomUrlString + roomParameters);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (this.grantResultsContainsDenials(grantResults)) {
// Show some permissions required dialog.
} else {
// All necessary permissions granted, continue loading.
this.loadEmbeddedRoomUrl();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestCameraAndAudioPermissions() {
this.requestPermissions(this.getPendingPermissions(), PERMISSION_REQUEST_CODE);
}
@RequiresApi(api = Build.VERSION_CODES.M)
private String[] getPendingPermissions() {
List<String> pendingPermissions = new ArrayList<>();
for (String permission : this.requiredDangerousPermissions) {
if (this.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
pendingPermissions.add(permission);
}
}
return pendingPermissions.toArray(new String[pendingPermissions.size()]);
}
private boolean isPendingPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return false;
}
return this.getPendingPermissions().length > 0;
}
private boolean grantResultsContainsDenials(int[] grantResults) {
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
return true;
}
}
return false;
}
}
Last updated
Was this helpful?