I'm currently learning how to build an Android WebView app that includes features like chat and WebRTC audio calls. All my files (HTML, JS, CSS) are loaded locally from the assets/ folder inside the app.
When I preview the app in a regular mobile browser (by opening the HTML file directly), everything works perfectly — the WebRTC call connects, chat messages work, etc.
However, after building the APK, the WebRTC call feature no longer works. I believe it's due to the microphone/audio permission not being granted correctly. I have already added all the necessary permissions in the AndroidManifest.xml, but I suspect that those permissions only apply to native components and not to the WebView.
Why would the WebView behave differently than a browser when it comes to accessing the microphone for WebRTC?
Here's my MainActivity.java:
import android.Manifest;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebSettings;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.webkit.PermissionRequest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
public class MainActivity extends Activity {
private WebView webView;
private static final int REQUEST_CODE = 123;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
REQUEST_CODE);
}
}
webView = new WebView(this);
setContentView(webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setDomStorageEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(final PermissionRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
runOnUiThread(new Runnable() {
@Override
public void run() {
for (String res : request.getResources()) {
if (res.equals(PermissionRequest.RESOURCE_AUDIO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_AUDIO_CAPTURE});
return;
}
}
request.deny();
}
});
}
}
});
webView.loadUrl("file:///android_asset/index.html");
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
And here's my AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tesnide"
android:versionCode="1"
android:versionName="1.0">
<!-- SDK level -->
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="27" />
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name="com.tesnide.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyForegroundService"
android:enabled="true"
android:exported="false" />
</application>
</manifest>
Any help, suggestions, or guidance would be greatly appreciated. Thank you so much in advance.