com.tfc.webviewer.ui.WebViewerActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.tfc.webviewer.ui.WebViewerActivity.java

Source

/*
 * Copyright Fobid. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.tfc.webviewer.ui;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatImageButton;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.webkit.DownloadListener;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.tfc.webviewer.R;
import com.tfc.webviewer.presenter.WebViewPresenterImpl;
import com.tfc.webviewer.util.ClipboardUtils;
import com.tfc.webviewer.util.FileUtils;
import com.tfc.webviewer.util.PermissionUtils;

/**
 * author @Fobid
 */
public class WebViewerActivity extends AppCompatActivity implements WebViewPresenterImpl.View, View.OnClickListener,
        SwipeRefreshLayout.OnRefreshListener, DownloadListener, View.OnCreateContextMenuListener {

    private static final String TAG = "WebViewerActivity";
    private static final int REQUEST_FILE_CHOOSER = 0;
    private static final int REQUEST_FILE_CHOOSER_FOR_LOLLIPOP = 1;
    private static final int REQUEST_PERMISSION_SETTING = 2;

    public static final String EXTRA_URL = "url";

    private String mUrl;
    private ValueCallback<Uri[]> filePathCallbackLollipop;
    private ValueCallback<Uri> filePathCallbackNormal;

    private WebViewPresenterImpl mPresenter;
    private DownloadManager mDownloadManager;
    private long mLastDownloadId;

    // Toolbar
    private TextView mTvTitle;
    private TextView mTvUrl;

    private CoordinatorLayout mCoordinatorLayout;
    private ProgressBar mProgressBar;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private WebView mWebView;

    // PopupWindow
    private PopupWindow mPopupMenu;
    private RelativeLayout mLlControlButtons;
    private AppCompatImageButton mBtnMore;
    private AppCompatImageButton mBtnBack;
    private AppCompatImageButton mBtnFoward;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //noinspection ConstantConditions
        getSupportActionBar().hide();

        IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
        filter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);
        registerReceiver(mDownloadReceiver, filter);

        mUrl = getIntent().getStringExtra(EXTRA_URL);

        setContentView(R.layout.a_web_viewer);
        bindView();

        mPresenter = new WebViewPresenterImpl(this, this);
        mPresenter.validateUrl(mUrl);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        unregisterReceiver(mDownloadReceiver);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        WebView.HitTestResult result = mWebView.getHitTestResult();

        mPresenter.onLongClick(result);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (mUrl != null) {
            outState.putString(EXTRA_URL, mUrl);
        }
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        mUrl = savedInstanceState.getString(EXTRA_URL);
        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (RESULT_OK == resultCode) {
            switch (requestCode) {
            case REQUEST_FILE_CHOOSER: {
                if (filePathCallbackNormal == null) {
                    return;
                }
                Uri result = data == null ? null : data.getData();
                filePathCallbackNormal.onReceiveValue(result);
                filePathCallbackNormal = null;
                break;
            }
            case REQUEST_FILE_CHOOSER_FOR_LOLLIPOP: {
                if (filePathCallbackLollipop == null) {
                    return;
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    filePathCallbackLollipop
                            .onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                }
                filePathCallbackLollipop = null;
                break;
            }
            case REQUEST_PERMISSION_SETTING: {
                mLastDownloadId = FileUtils.downloadFile(this, mDownloadUrl, mDownloadMimetype);
                break;
            }
            }
        } else {
            switch (requestCode) {
            case REQUEST_PERMISSION_SETTING: {
                Toast.makeText(this, R.string.write_permission_denied_message, Toast.LENGTH_LONG).show();
                break;
            }
            }
        }
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void bindView() {
        // Toolbar
        mTvTitle = (TextView) findViewById(R.id.toolbar_tv_title);
        mTvUrl = (TextView) findViewById(R.id.toolbar_tv_url);

        mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.a_web_viewer_coordinatorlayout);
        mProgressBar = (ProgressBar) findViewById(R.id.a_web_viewer_pb);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.a_web_viewer_srl);
        mWebView = (WebView) findViewById(R.id.a_web_viewer_wv);
        mSwipeRefreshLayout.setOnRefreshListener(this);

        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            webSettings.setDisplayZoomControls(false);
        }
        webSettings.setBuiltInZoomControls(true);
        webSettings.setSupportZoom(true);
        webSettings.setDomStorageEnabled(true);

        mWebView.setWebChromeClient(new MyWebChromeClient());
        mWebView.setWebViewClient(new MyWebViewClient());
        mWebView.setDownloadListener(this);
        mWebView.setOnCreateContextMenuListener(this);

        mBtnMore = (AppCompatImageButton) findViewById(R.id.toolbar_btn_more);

        //noinspection ConstantConditions
        findViewById(R.id.toolbar_btn_close).setOnClickListener(this);
        //noinspection ConstantConditions
        mBtnMore.setOnClickListener(this);

        // PopupWindow
        initPopupMenu();
    }

    private void initPopupMenu() {
        @SuppressLint("InflateParams")
        View view = LayoutInflater.from(this).inflate(R.layout.popup_menu, null);

        mPopupMenu = new PopupWindow(this);

        mPopupMenu.setContentView(view);
        mPopupMenu.setOutsideTouchable(true);
        mPopupMenu.setFocusable(true);

        mLlControlButtons = (RelativeLayout) view.findViewById(R.id.popup_menu_rl_arrows);
        mBtnBack = (AppCompatImageButton) view.findViewById(R.id.popup_menu_btn_back);
        mBtnFoward = (AppCompatImageButton) view.findViewById(R.id.popup_menu_btn_forward);

        mBtnBack.setOnClickListener(this);
        mBtnFoward.setOnClickListener(this);
        view.findViewById(R.id.popup_menu_btn_refresh).setOnClickListener(this);
        view.findViewById(R.id.popup_menu_btn_copy_link).setOnClickListener(this);
        view.findViewById(R.id.popup_menu_btn_open_with_other_browser).setOnClickListener(this);
        view.findViewById(R.id.popup_menu_btn_share).setOnClickListener(this);
    }

    @Override
    public void loadUrl(String url) {
        mWebView.loadUrl(url);
        mPresenter.onReceivedTitle("", mUrl);
    }

    @Override
    public void close() {
        finish();
    }

    @Override
    public void closeMenu() {
        mPopupMenu.dismiss();
    }

    @Override
    public void openMenu() {
        mPopupMenu.showAsDropDown(mBtnMore);
    }

    @Override
    public void setEnabledGoBackAndGoFoward() {
        mLlControlButtons.setVisibility(View.VISIBLE);
    }

    @Override
    public void setDisabledGoBackAndGoFoward() {
        mLlControlButtons.setVisibility(View.GONE);
    }

    @Override
    public void setEnabledGoBack() {
        mBtnBack.setEnabled(true);
    }

    @Override
    public void setDisabledGoBack() {
        mBtnBack.setEnabled(false);
    }

    @Override
    public void setEnabledGoFoward() {
        mBtnFoward.setEnabled(true);
    }

    @Override
    public void setDisabledGoFoward() {
        mBtnFoward.setEnabled(false);
    }

    @Override
    public void goBack() {
        mWebView.goBack();
    }

    @Override
    public void goFoward() {
        mWebView.goForward();
    }

    @Override
    public void copyLink(String url) {
        ClipboardUtils.copyText(this, url);
    }

    @Override
    public void showToast(Toast toast) {
        toast.show();
    }

    @Override
    public void openBrowser(Uri uri) {
        startActivity(new Intent(Intent.ACTION_VIEW, uri));
    }

    @Override
    public void openShare(String url) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, mWebView.getUrl());
        intent.setType("text/plain");
        startActivity(Intent.createChooser(intent, getResources().getString(R.string.menu_share)));
    }

    @Override
    public void setToolbarTitle(String title) {
        mTvTitle.setText(title);
    }

    @Override
    public void setToolbarUrl(String url) {
        mTvUrl.setText(url);
    }

    @Override
    public void onDownloadStart(String url) {
        onDownloadStart(url, null, null, "image/jpeg", 0);
    }

    @Override
    public void setProgressBar(int progress) {
        mProgressBar.setProgress(progress);
    }

    @Override
    public void setRefreshing(boolean refreshing) {
        mSwipeRefreshLayout.setRefreshing(refreshing);
    }

    @Override
    public void openEmail(String email) {
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", email, null));
        startActivity(Intent.createChooser(intent, getString(R.string.email)));
    }

    @Override
    public void openPopup(String url) {
        Intent intent = new Intent(this, WebViewerActivity.class);
        intent.putExtra(WebViewerActivity.EXTRA_URL, url);
        startActivity(intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        if (PermissionUtils.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE == requestCode) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                mLastDownloadId = FileUtils.downloadFile(this, mDownloadUrl, mDownloadMimetype);
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (!shouldShowRequestPermissionRationale(permissions[0])) {
                        new AlertDialog.Builder(WebViewerActivity.this)
                                .setTitle(R.string.write_permission_denied_title)
                                .setMessage(R.string.write_permission_denied_message)
                                .setNegativeButton(R.string.dialog_dismiss, null)
                                .setPositiveButton(R.string.dialog_settings, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                        Uri uri = Uri.fromParts("package", getPackageName(), null);
                                        intent.setData(uri);
                                        startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
                                    }
                                }).show();
                    }
                }
            }
        }
    }

    private String mDownloadUrl;
    private String mDownloadMimetype;

    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType,
            long contentLength) {
        if (mDownloadManager == null) {
            mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        }
        Log.d(TAG, "onDownloadStart url: " + url);
        Log.d(TAG, "onDownloadStart userAgent: " + userAgent);
        Log.d(TAG, "onDownloadStart contentDisposition: " + contentDisposition);
        Log.d(TAG, "onDownloadStart mimeType: " + mimeType);

        mDownloadUrl = url;
        mDownloadMimetype = mimeType;

        boolean hasPermission = PermissionUtils.hasPermission(WebViewerActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                PermissionUtils.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE);

        if (hasPermission) {
            mLastDownloadId = FileUtils.downloadFile(this, url, mimeType);
        }
    }

    @Override
    public void onClick(View v) {
        mPresenter.onClick(v.getId(), mWebView.getUrl(), mPopupMenu);
    }

    @Override
    public void onRefresh() {
        mWebView.reload();
    }

    public class MyWebChromeClient extends WebChromeClient {

        // For Android < 3.0
        @SuppressWarnings("unused")
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            openFileChooser(uploadMsg, "");
        }

        // For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg,
                @SuppressWarnings("UnusedParameters") String acceptType) {
            filePathCallbackNormal = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, getString(R.string.select_image)), REQUEST_FILE_CHOOSER);
        }

        // For Android 5.0+
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                WebChromeClient.FileChooserParams fileChooserParams) {
            if (filePathCallbackLollipop != null) {
                filePathCallbackLollipop.onReceiveValue(null);
                filePathCallbackLollipop = null;
            }
            filePathCallbackLollipop = filePathCallback;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
                    REQUEST_FILE_CHOOSER_FOR_LOLLIPOP);

            return true;
        }

        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            AlertDialog dialog = new AlertDialog.Builder(WebViewerActivity.this).setMessage(message)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    }).create();
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

            return true;
        }

        @Override
        public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
            AlertDialog dialog = new AlertDialog.Builder(WebViewerActivity.this).setMessage(message)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                        }
                    }).create();
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

            return true;
        }

        @Override
        public void onProgressChanged(WebView view, int progress) {
            mPresenter.onProgressChanged(mSwipeRefreshLayout, progress);
        }

        @Override
        public void onReceivedTitle(WebView view, String title) {
            mPresenter.onReceivedTitle(title, view.getUrl());
        }
    }

    public class MyWebViewClient extends WebViewClient {

        @Override
        public void onPageFinished(WebView view, String url) {
            mPresenter.onReceivedTitle(view.getTitle(), url);
            mPresenter.setEnabledGoBackAndGoFoward(view.canGoBack(), view.canGoForward());
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.endsWith(".mp4")) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setDataAndType(Uri.parse(url), "video/*");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                view.getContext().startActivity(intent);

                return true;
            } else if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:")
                    || url.startsWith("mms:") || url.startsWith("mmsto:")) {
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                view.getContext().startActivity(intent);

                return true;
            } else {
                return super.shouldOverrideUrlLoading(view, url);
            }
        }
    }

    @Override
    public void onBackPressed() {
        mPresenter.onBackPressed(mPopupMenu, mWebView);
    }

    private BroadcastReceiver mDownloadReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
                if (mDownloadManager != null) {
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
                        Uri downloadedUri = mDownloadManager.getUriForDownloadedFile(mLastDownloadId);
                        String mimeType = mDownloadManager.getMimeTypeForDownloadedFile(mLastDownloadId);

                        new NotifyDownloadedTask().execute(downloadedUri.toString(), mimeType);
                    }
                }
            } else if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
                Intent notiIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
                notiIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(notiIntent);
            }
        }
    };

    private class NotifyDownloadedTask extends AsyncTask<String, Void, String[]> {

        @Override
        protected String[] doInBackground(String... params) {
            if (params == null || params.length != 2) {
                return null;
            }
            String uriStr = params[0];
            String mimeType = params[1];
            String fileName = "";

            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mLastDownloadId);
            Cursor c = mDownloadManager.query(query);

            if (c.moveToFirst()) {
                int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                if (DownloadManager.STATUS_SUCCESSFUL == status) {
                    fileName = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
                }
            }

            return new String[] { uriStr, fileName, mimeType };
        }

        @Override
        protected void onPostExecute(String[] results) {
            if (results != null && results.length == 3) {
                final String uriStr = results[0];
                final String fileName = results[1];
                final String mimeType = results[2];

                Snackbar.make(mCoordinatorLayout, fileName + getString(R.string.downloaded_message),
                        Snackbar.LENGTH_LONG).setDuration(getResources().getInteger(R.integer.snackbar_duration))
                        .setAction(getString(R.string.open), new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Intent viewIntent = new Intent(Intent.ACTION_VIEW);
                                viewIntent.setDataAndType(Uri.parse(uriStr), mimeType);
                                startActivity(viewIntent);
                            }
                        }).show();
            }
        }
    }
}