Android Advanced WebView Component
http://www.viralandroid.com/2020/05/android-advanced-webview-component.html
Enhanced WebView component for Android that works as intended out of the box
Requirements
- Android 2.2+
Installation
- Add this library to your project
- Declare the Gradle repository in your root
build.gradle
allprojects { repositories { maven { url "https://jitpack.io" } } }
- Declare the Gradle dependency in your app module's
build.gradle
dependencies { compile 'com.github.delight-im:Android-AdvancedWebView:v3.0.0' }
Usage
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Layout (XML)
<im.delight.android.webview.AdvancedWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Activity (Java)
Without Fragments
public class MyActivity extends Activity implements AdvancedWebView.Listener {
private AdvancedWebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mWebView = (AdvancedWebView) findViewById(R.id.webview);
mWebView.setListener(this, this);
mWebView.loadUrl("http://www.example.org/");
// ...
}
@SuppressLint("NewApi")
@Override
protected void onResume() {
super.onResume();
mWebView.onResume();
// ...
}
@SuppressLint("NewApi")
@Override
protected void onPause() {
mWebView.onPause();
// ...
super.onPause();
}
@Override
protected void onDestroy() {
mWebView.onDestroy();
// ...
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
mWebView.onActivityResult(requestCode, resultCode, intent);
// ...
}
@Override
public void onBackPressed() {
if (!mWebView.onBackPressed()) { return; }
// ...
super.onBackPressed();
}
@Override
public void onPageStarted(String url, Bitmap favicon) { }
@Override
public void onPageFinished(String url) { }
@Override
public void onPageError(int errorCode, String description, String failingUrl) { }
@Override
public void onDownloadRequested(String url, String suggestedFilename, String mimeType, long contentLength, String contentDisposition, String userAgent) { }
@Override
public void onExternalPageRequest(String url) { }
}
android.app.Fragment
)
With Fragments (
Note: If you're using the
Fragment
class from the support library (android.support.v4.app.Fragment
), please refer to the next section (see below) instead of this one.public class MyFragment extends Fragment implements AdvancedWebView.Listener {
private AdvancedWebView mWebView;
public MyFragment() { }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_my, container, false);
mWebView = (AdvancedWebView) rootView.findViewById(R.id.webview);
mWebView.setListener(this, this);
mWebView.loadUrl("http://www.example.org/");
// ...
return rootView;
}
@SuppressLint("NewApi")
@Override
public void onResume() {
super.onResume();
mWebView.onResume();
// ...
}
@SuppressLint("NewApi")
@Override
public void onPause() {
mWebView.onPause();
// ...
super.onPause();
}
@Override
public void onDestroy() {
mWebView.onDestroy();
// ...
super.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
mWebView.onActivityResult(requestCode, resultCode, intent);
// ...
}
@Override
public void onPageStarted(String url, Bitmap favicon) { }
@Override
public void onPageFinished(String url) { }
@Override
public void onPageError(int errorCode, String description, String failingUrl) { }
@Override
public void onDownloadRequested(String url, String suggestedFilename, String mimeType, long contentLength, String contentDisposition, String userAgent) { }
@Override
public void onExternalPageRequest(String url) { }
}
android.support.v4.app.Fragment
)
With Fragments from the support library (- Use the code for normal
Fragment
usage as shown above - Change
mWebView.setListener(this, this);
tomWebView.setListener(getActivity(), this);
- Add the following code to the parent
FragmentActivity
in order to forward the results from theFragmentActivity
to the appropriateFragment
instancepublic class MyActivity extends FragmentActivity implements AdvancedWebView.Listener { @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (mFragment != null) { mFragment.onActivityResult(requestCode, resultCode, intent); } } }
ProGuard (if enabled)
-keep class * extends android.webkit.WebChromeClient { *; }
-dontwarn im.delight.android.webview.**
Cleartext (non-HTTPS) traffic
If you want to serve sites or just single resources over plain
http
instead of https
, there’s usually nothing to do if you’re targeting Android 8.1 (API level 27) or earlier. On Android 9 (API level 28) and later, however, cleartext support is disabled by default. You may have to set android:usesCleartextTraffic="true"
on the <application>
element in AndroidManifest.xml
or provide a custom network security configuration.Features
- Optimized for best performance and security
- Features are patched across Android versions
- File uploads are handled automatically (check availability with
AdvancedWebView.isFileUploadAvailable()
)- Multiple file uploads via single input fields (
multiple
attribute in HTML) are supported on Android 5.0+. The application that is used to pick the files (i.e. usually a gallery or file manager app) must provide controls for selecting multiple files, which some apps don't.
- Multiple file uploads via single input fields (
- JavaScript and WebStorage are enabled by default
- Includes localizations for the 25 most widely spoken languages
- Receive callbacks when pages start/finish loading or have errors
@Override public void onPageStarted(String url, Bitmap favicon) { // a new page started loading } @Override public void onPageFinished(String url) { // the new page finished loading } @Override public void onPageError(int errorCode, String description, String failingUrl) { // the new page failed to load }
- Downloads are handled automatically and can be listened to
@Override public void onDownloadRequested(String url, String suggestedFilename, String mimeType, long contentLength, String contentDisposition, String userAgent) { // some file is available for download // either handle the download yourself or use the code below if (AdvancedWebView.handleDownload(this, url, suggestedFilename)) { // download successfully handled } else { // download couldn't be handled because user has disabled download manager app on the device // TODO show some notice to the user } }
- Enable geolocation support (needs
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
)mWebView.setGeolocationEnabled(true);
- Add custom HTTP headers in addition to the ones sent by the web browser implementation
mWebView.addHttpHeader("X-Requested-With", "My wonderful app");
- Define a custom set of permitted hostnames and receive callbacks for all other hostnames
mWebView.addPermittedHostname("example.org");
and@Override public void onExternalPageRequest(String url) { // the user tried to open a page from a non-permitted hostname }
- Prevent caching of HTML pages
boolean preventCaching = true; mWebView.loadUrl("http://www.example.org/", preventCaching);
- Check for alternative browsers installed on the device
if (AdvancedWebView.Browsers.hasAlternative(this)) { AdvancedWebView.Browsers.openUrl(this, "http://www.example.org/"); }
- Disable cookies
// disable third-party cookies only mWebView.setThirdPartyCookiesEnabled(false); // or disable cookies in general mWebView.setCookiesEnabled(false);
- Disallow mixed content (HTTP content being loaded inside HTTPS sites)
mWebView.setMixedContentAllowed(false);
- Switch between mobile and desktop mode
mWebView.setDesktopMode(true); // or // mWebView.setDesktopMode(false);
- Load HTML file from “assets” (e.g. at
app/src/main/assets/html/index.html
)mWebView.loadUrl("file:///android_asset/html/index.html");
- Load HTML file from SD card
// <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { mWebView.getSettings().setAllowFileAccess(true); mWebView.loadUrl("file:///sdcard/Android/data/com.my.app/my_folder/index.html"); }
- Load HTML source text and display as page
myWebView.loadHtml("<html>...</html>"); // or final String myBaseUrl = "http://www.example.com/"; myWebView.loadHtml("<html>...</html>", myBaseUrl);
- Enable multi-window support
myWebView.getSettings().setSupportMultipleWindows(true); // myWebView.getSettings().setJavaScriptEnabled(true); // myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); myWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { AdvancedWebView newWebView = new AdvancedWebView(MyNewActivity.this); // myParentLayout.addView(newWebView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(newWebView); resultMsg.sendToTarget(); return true; } }
Download complete project source code from GitHub