content: package com.banrossyn.socialsaver.waweb;
  
  import androidx.annotation.RequiresApi;
  import androidx.appcompat.app.AppCompatActivity;
  import androidx.core.app.ActivityCompat;
  import androidx.core.content.ContextCompat;
  
  import android.Manifest;
  import android.app.Activity;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.graphics.Bitmap;
  import android.net.Uri;
  import android.os.Build;
  import android.os.Bundle;
  import android.os.Message;
  import android.util.Log;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.WindowManager;
  import android.webkit.ConsoleMessage;
  import android.webkit.DownloadListener;
  import android.webkit.PermissionRequest;
  import android.webkit.ValueCallback;
  import android.webkit.WebChromeClient;
  import android.webkit.WebResourceError;
  import android.webkit.WebResourceRequest;
  import android.webkit.WebSettings;
  import android.webkit.WebView;
  import android.webkit.WebViewClient;
  import android.widget.ImageView;
  import android.widget.Toast;
  
  import com.banrossyn.socialsaver.R;
  
  
  import java.util.Arrays;
  import java.util.Locale;
  
  public class WAWebActivity extends AppCompatActivity {
  
      private static final String CHROME_FULL = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36";
      private static final String USER_AGENT = CHROME_FULL;
  
      private static final String STORAGE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE; // "android.permission.WRITE_EXTERNAL_STORAGE"
      private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA; // "android.permission.CAMERA"
      private static final String AUDIO_PERMISSION = Manifest.permission.RECORD_AUDIO; // "android.permission.RECORD_AUDIO"
      private static final String[] VIDEO_PERMISSION = {CAMERA_PERMISSION, AUDIO_PERMISSION};
  
      private static final String WHATSAPP_HOMEPAGE_URL = "https://www.whatsapp.com/";
  
      private static final String WHATSAPP_WEB_BASE_URL = "web.whatsapp.com";
      private static final String WORLD_ICON = "\uD83C\uDF10";
      private static final String WHATSAPP_WEB_URL = "https://" + WHATSAPP_WEB_BASE_URL
              + "/" + WORLD_ICON + "/"
              + Locale.getDefault().getLanguage();
  
      private static final int FILECHOOSER_RESULTCODE = 200;
      private static final int CAMERA_PERMISSION_RESULTCODE = 201;
      private static final int AUDIO_PERMISSION_RESULTCODE = 202;
      private static final int VIDEO_PERMISSION_RESULTCODE = 203;
      private static final int STORAGE_PERMISSION_RESULTCODE = 204;
  
      public static final String DEBUG_TAG = "KESSI";
  
      private final Activity activity = this;
      private WebView mWebView;
  
      private long mLastBackClick = 0;
  
  
      private ValueCallback<Uri[]> mUploadMessage;
      private PermissionRequest mCurrentPermissionRequest;
      private String mCurrentDownloadRequest = null;
  
      ImageView back, refresh;
  
      @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_waweb);
  
          getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
  
          back = findViewById(R.id.back);
          back.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  onBackPressed();
              }
          });
  
  
  
          mWebView = findViewById(R.id.webview);
  
          mWebView.setDownloadListener(new DownloadListener() {
              @Override
              public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
                  mCurrentDownloadRequest = url;
                  if (checkPermission(STORAGE_PERMISSION)) {
                      mWebView.loadUrl(BlobDownloader.getBase64StringFromBlobUrl(url));
                      triggerDownload();
                  } else {
                      requestPermission(STORAGE_PERMISSION);
                  }
              }
          });
          mWebView.addJavascriptInterface(new BlobDownloader(getApplicationContext()), BlobDownloader.JsInstance);
  
          mWebView.getSettings().setJavaScriptEnabled(true); //for wa web
          mWebView.getSettings().setAllowContentAccess(true); // for camera
          mWebView.getSettings().setAllowFileAccess(true);
          mWebView.getSettings().setAllowFileAccessFromFileURLs(true);
          mWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);
          mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false); //for audio messages
  
          mWebView.getSettings().setDomStorageEnabled(true); //for html5 app
          mWebView.getSettings().setDatabaseEnabled(true);
  //        mWebView.getSettings().setAppCacheEnabled(false); // deprecated
          mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
  
          mWebView.getSettings().setLoadWithOverviewMode(true);
          mWebView.getSettings().setUseWideViewPort(true);
  
          mWebView.getSettings().setSupportZoom(true);
          mWebView.getSettings().setBuiltInZoomControls(true);
          mWebView.getSettings().setDisplayZoomControls(false);
  
          mWebView.getSettings().setSaveFormData(true);
          mWebView.getSettings().setLoadsImagesAutomatically(true);
          mWebView.getSettings().setBlockNetworkImage(false);
          mWebView.getSettings().setBlockNetworkLoads(false);
          mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
          mWebView.getSettings().setNeedInitialFocus(false);
          mWebView.getSettings().setGeolocationEnabled(true);
          mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
  
          mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
          mWebView.setScrollbarFadingEnabled(true);
  
          mWebView.setWebChromeClient(new WebChromeClient() {
  
              @Override
              public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg) {
                  Toast.makeText(getApplicationContext(), "OnCreateWindow", Toast.LENGTH_LONG).show();
                  return true;
              }
  
              @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
              @Override
              public void onPermissionRequest(final PermissionRequest request) {
                  if (request.getResources()[0].equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
                      if (ContextCompat.checkSelfPermission(activity, CAMERA_PERMISSION) == PackageManager.PERMISSION_DENIED
                              && ContextCompat.checkSelfPermission(activity, AUDIO_PERMISSION) == PackageManager.PERMISSION_DENIED) {
                          ActivityCompat.requestPermissions(activity, VIDEO_PERMISSION, VIDEO_PERMISSION_RESULTCODE);
                          mCurrentPermissionRequest = request;
                      } else if (ContextCompat.checkSelfPermission(activity, CAMERA_PERMISSION) == PackageManager.PERMISSION_DENIED) {
                          ActivityCompat.requestPermissions(activity, new String[]{CAMERA_PERMISSION}, CAMERA_PERMISSION_RESULTCODE);
                          mCurrentPermissionRequest = request;
                      } else if (ContextCompat.checkSelfPermission(activity, AUDIO_PERMISSION) == PackageManager.PERMISSION_DENIED) {
                          ActivityCompat.requestPermissions(activity, new String[]{AUDIO_PERMISSION}, AUDIO_PERMISSION_RESULTCODE);
                          mCurrentPermissionRequest = request;
                      } else {
                          request.grant(request.getResources());
                      }
                  } else if (request.getResources()[0].equals(PermissionRequest.RESOURCE_AUDIO_CAPTURE)) {
                      if (ContextCompat.checkSelfPermission(activity, AUDIO_PERMISSION) == PackageManager.PERMISSION_GRANTED) {
                          request.grant(request.getResources());
                      } else {
                          ActivityCompat.requestPermissions(activity, new String[]{AUDIO_PERMISSION}, AUDIO_PERMISSION_RESULTCODE);
                          mCurrentPermissionRequest = request;
                      }
                  } else {
                      try {
                          request.grant(request.getResources());
                      } catch (RuntimeException e) {
                          Log.d(DEBUG_TAG, "Granting permissions failed", e);
                      }
                  }
              }
  
              public boolean onConsoleMessage(ConsoleMessage cm) {
                  Log.d(DEBUG_TAG, "WebView console message: " + cm.message());
                  return super.onConsoleMessage(cm);
              }
  
              @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
              public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                  mUploadMessage = filePathCallback;
                  Intent chooserIntent = fileChooserParams.createIntent();
                  startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
                  return true;
              }
          });
  
          mWebView.setWebViewClient(new WebViewClient() {
  
              public void onPageStarted(WebView view, String url, Bitmap favicon) {
                  super.onPageStarted(view, url, favicon);
              }
  
              @Override
              public void onPageCommitVisible(WebView view, String url) {
                  super.onPageCommitVisible(view, url);
              }
  
              @Override
              public void onPageFinished(WebView view, String url) {
                  super.onPageFinished(view, url);
                  view.scrollTo(0, 0);
              }
  
              @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
              @Override
              public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                  Uri url = request.getUrl();
                  Log.d(DEBUG_TAG, url.toString());
  
                  if (url.toString().equals(WHATSAPP_HOMEPAGE_URL)) {
                      // when whatsapp somehow detects that waweb is running on a phone (e.g. trough
                      // the user agent, but apparently somehow else), it automatically redicts to the
                      // WHATSAPP_HOMEPAGE_URL. It's higly unlikely that a user wants to visit the
                      // WHATSAPP_HOMEPAGE_URL from within waweb.
                      // -> block the request and reload waweb
                      showToast("WA Web has to be reloaded to keep the app running");
                      loadWhatsapp();
                      return true;
                  } else if (url.getHost().equals(WHATSAPP_WEB_BASE_URL)) {
                      // whatsapp web request -> fine
                      return super.shouldOverrideUrlLoading(view, request);
                  } else {
                      Intent intent = new Intent(Intent.ACTION_VIEW, url);
                      startActivity(intent);
                      return true;
                  }
              }
  
              @RequiresApi(api = Build.VERSION_CODES.M)
              public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                  String msg = String.format("Error: %s - %s", error.getErrorCode(), error.getDescription());
                  Log.d(DEBUG_TAG, msg);
              }
  
              public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
                  Log.d(DEBUG_TAG, "Unhandled key event: " + event.toString());
              }
          });
  
          if (savedInstanceState == null) {
              loadWhatsapp();
          } else {
              Log.d(DEBUG_TAG, "savedInstanceState is present");
          }
  
          mWebView.getSettings().setUserAgentString(USER_AGENT);
  
          refresh = findViewById(R.id.refresh);
          refresh.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  showToast("reloading...");
                  loadWhatsapp();
              }
          });
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          mWebView.onResume();
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          mWebView.onPause();
      }
  
      private boolean checkPermission(String permission) {
          return PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(activity, permission);
      }
  
      private void requestPermission(String permission) {
          if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
              ActivityCompat.requestPermissions(activity, new String[]{permission}, STORAGE_PERMISSION_RESULTCODE);
          }
      }
  
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
      @Override
      public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          switch (requestCode) {
              case VIDEO_PERMISSION_RESULTCODE:
                  if (permissions.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                          grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                      try {
                          mCurrentPermissionRequest.grant(mCurrentPermissionRequest.getResources());
                      } catch (RuntimeException e) {
                          Log.e(DEBUG_TAG, "Granting permissions failed", e);
                      }
                  } else {
                      showToast("Permission not granted, can't use video.");
                      mCurrentPermissionRequest.deny();
                  }
                  break;
              case CAMERA_PERMISSION_RESULTCODE:
              case AUDIO_PERMISSION_RESULTCODE:
                  //same same
                  if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      try {
                          mCurrentPermissionRequest.grant(mCurrentPermissionRequest.getResources());
                      } catch (RuntimeException e) {
                          Log.e(DEBUG_TAG, "Granting permissions failed", e);
                      }
                  } else {
                      showToast("Permission not granted, can't use " +
                              (requestCode == CAMERA_PERMISSION_RESULTCODE ? "camera" : "microphone"));
                      mCurrentPermissionRequest.deny();
                  }
                  break;
              case STORAGE_PERMISSION_RESULTCODE:
                  if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      triggerDownload();
                  } else {
                      showToast("Permission not granted, can't download");
                      mCurrentDownloadRequest = null;
                  }
                  break;
              default:
                  Log.d(DEBUG_TAG, "Got permission result with unknown request code " +
                          requestCode + " - " + Arrays.asList(permissions).toString());
          }
          mCurrentPermissionRequest = null;
      }
  
      private void loadWhatsapp() {
          mWebView.getSettings().setUserAgentString(USER_AGENT);
          mWebView.loadUrl(WHATSAPP_WEB_URL);
      }
  
      private void triggerDownload() {
          if (null != mCurrentDownloadRequest) {
              mWebView.loadUrl(BlobDownloader.getBase64StringFromBlobUrl(mCurrentDownloadRequest));
          }
          mCurrentDownloadRequest = null;
      }
  
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
          mWebView.saveState(outState);
      }
  
      @Override
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
          super.onRestoreInstanceState(savedInstanceState);
          mWebView.restoreState(savedInstanceState);
      }
  
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
          switch (requestCode) {
              case FILECHOOSER_RESULTCODE:
                  if (resultCode == RESULT_CANCELED || data.getData() == null) {
                      mUploadMessage.onReceiveValue(null);
                  } else {
                      Uri result = data.getData();
                      Uri[] results = new Uri[1];
                      results[0] = result;
                      mUploadMessage.onReceiveValue(results);
                  }
                  break;
              default:
                  Log.d(DEBUG_TAG, "Got activity result with unknown request code " +
                          requestCode + " - " + data.toString());
          }
      }
  
      private void showToast(final String msg) {
          this.runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  Toast.makeText(WAWebActivity.this, msg, Toast.LENGTH_SHORT).show();
              }
          });
      }
  
      @Override
      public void onBackPressed() {
          if (System.currentTimeMillis() - mLastBackClick < 1100) {
              super.onBackPressed();
          }  else {
                  mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ESCAPE));
                  showToast("Click back again to close");
                  mLastBackClick = System.currentTimeMillis();
              }
          }
      }
  