content: package com.alextam.uploadimage;
  
  import android.Manifest;
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.database.Cursor;
  import android.net.Uri;
  import android.net.http.SslError;
  import android.os.Build;
  import android.os.Bundle;
  import android.provider.OpenableColumns;
  import android.text.TextUtils;
  import android.util.Log;
  import android.view.View;
  import android.webkit.CookieManager;
  import android.webkit.CookieSyncManager;
  import android.webkit.SslErrorHandler;
  import android.webkit.ValueCallback;
  import android.webkit.WebChromeClient;
  import android.webkit.WebSettings;
  import android.webkit.WebView;
  import android.webkit.WebViewClient;
  import android.widget.ProgressBar;
  import android.widget.Toast;
  
  import java.io.File;
  import java.util.ArrayList;
  import java.util.List;
  
  
  /**
   * WebView invokes the camera to take pictures, upload pictures, or select pictures from the album for uploading.
   * This version is updated to include AI-driven secure file processing and uploading.
   *
   * @author AlexTam
   * created at 2016/10/14 9:58
   */
  public class MainActivity extends Activity
          implements MyWebChomeClient.OpenFileChooserCallBack {
  
      private static final String TAG = "MainActivity";
      private WebView mWebView;
      private ProgressBar mProgressBar; // Add a progress bar to the layout
  
      private static final int REQUEST_CODE_PICK_IMAGE = 0;
      private static final int REQUEST_CODE_IMAGE_CAPTURE = 1;
  
      private Intent mSourceIntent;
      private ValueCallback<Uri> mUploadMsg;
      public ValueCallback<Uri[]> mUploadMsgForAndroid5;
  
      // permission Code
      private static final int P_CODE_PERMISSIONS = 101;
  
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          // Make sure you have a ProgressBar with id 'progressBar' in your activity_main.xml
          mProgressBar = findViewById(R.id.progressBar);
  
          requestPermissionsAndroidM();
  
          mWebView = (WebView) findViewById(R.id.webview);
  
          WebSettings webSettings = mWebView.getSettings();
          webSettings.setJavaScriptEnabled(true);
          webSettings.setAllowFileAccess(true);
          webSettings.setAllowContentAccess(true);
          webSettings.setBuiltInZoomControls(false);
  
          mWebView.setWebChromeClient(new MyWebChomeClient(MainActivity.this));
  
          mWebView.setWebViewClient(new WebViewClient() {
              @Override
              public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                  handler.proceed();
              }
  
              @Override
              public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  view.loadUrl(url);
                  return true;
              }
  
              @Override
              public void onPageFinished(WebView view, String url) {
                  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                      CookieSyncManager.getInstance().sync();
                  } else {
                      CookieManager.getInstance().flush();
                  }
              }
          });
  
          fixDirPath();
  
          // target your url here.
          mWebView.loadUrl("https://upload.test.com/");
      }
  
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
          if (resultCode != Activity.RESULT_OK) {
              // User cancelled the file selection, so restore the callback to WebView
              restoreUploadMsg();
              return;
          }
  
          switch (requestCode) {
              case REQUEST_CODE_IMAGE_CAPTURE:
              case REQUEST_CODE_PICK_IMAGE: {
                  try {
                      // This part is now different. We get the URI but don't give it back to WebView.
                      // Instead, we pass it to our AiProcessor.
  
                      Uri resultUri = null;
                      if (data != null && data.getData() != null) {
                          resultUri = data.getData();
                      } else if (mSourceIntent != null) {
                          // For camera capture, the URI is in the source intent
                          String sourcePath = ImageUtil.retrievePath(this, mSourceIntent, data);
                          if (sourcePath != null) {
                              resultUri = Uri.fromFile(new File(sourcePath));
                          }
                      }
  
                      if (resultUri != null) {
                          handleFileUpload(resultUri);
                      } else {
                          Toast.makeText(this, "Failed to get file URI.", Toast.LENGTH_SHORT).show();
                          restoreUploadMsg();
                      }
  
                  } catch (Exception e) {
                      e.printStackTrace();
                      Toast.makeText(this, "An error occurred.", Toast.LENGTH_SHORT).show();
                      restoreUploadMsg();
                  }
                  break;
              }
          }
      }
  
      private void handleFileUpload(Uri fileUri) {
          // Show a progress bar to the user
          mProgressBar.setVisibility(View.VISIBLE);
  
          // Get the original filename from the URI
          String fileName = getFileName(fileUri);
  
          // The original callbacks to WebView are now cancelled because we are handling the upload natively.
          // We call restoreUploadMsg() inside the AiProcessor's callback.
          if (mUploadMsg == null && mUploadMsgForAndroid5 == null) {
              mProgressBar.setVisibility(View.GONE);
              return;
          }
  
          AiProcessor.processAndUploadFile(this, fileUri, fileName, new AiProcessor.AiProcessorCallback() {
              @Override
              public void onSuccess(String message) {
                  // On success, show a message and restore the WebView callback with null.
                  Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
                  mProgressBar.setVisibility(View.GONE);
                  restoreUploadMsg(); // This tells the WebView the process is complete.
              }
  
              @Override
              public void onFailure(String errorMessage) {
                  // On failure, show an error and restore the WebView callback with null.
                  Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
                  mProgressBar.setVisibility(View.GONE);
                  restoreUploadMsg(); // This tells the WebView the process is complete.
              }
          });
      }
  
      /**
       * Helper method to get filename from a content URI.
       * @param uri The URI to query.
       * @return The file name.
       */
      private String getFileName(Uri uri) {
          String result = null;
          if (uri.getScheme().equals("content")) {
              try (Cursor cursor = getContentResolver().query(uri, null, null, null, null)) {
                  if (cursor != null && cursor.moveToFirst()) {
                      int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                      if (index != -1) {
                          result = cursor.getString(index);
                      }
                  }
              }
          }
          if (result == null) {
              result = uri.getPath();
              int cut = result.lastIndexOf('/');
              if (cut != -1) {
                  result = result.substring(cut + 1);
              }
          }
          return result;
      }
  
  
      @Override
      public void openFileChooserCallBack(ValueCallback<Uri> uploadMsg, String acceptType) {
          mUploadMsg = uploadMsg;
          showOptions();
      }
  
      @Override
      public boolean openFileChooserCallBackAndroid5
              (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
          mUploadMsgForAndroid5 = filePathCallback;
          showOptions();
  
          return true;
      }
  
      public void showOptions() {
          AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
          alertDialog.setOnCancelListener(new DialogOnCancelListener());
  
          alertDialog.setTitle("请选择操作");
          // gallery, camera.
          String[] options = {"相册", "拍照"};
  
          alertDialog.setItems(options, new DialogInterface.OnClickListener() {
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                          if (which == 0) {
                              if (PermissionUtil.isOverMarshmallow()) {
                                  if (!PermissionUtil.isPermissionValid(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                                      Toast.makeText(MainActivity.this,
                                              "请去\"设置\"中开启本应用的图片媒体访问权限",
                                              Toast.LENGTH_SHORT).show();
  
                                      restoreUploadMsg();
                                      requestPermissionsAndroidM();
                                      return;
                                  }
  
                              }
  
                              try {
                                  mSourceIntent = ImageUtil.choosePicture();
                                  startActivityForResult(mSourceIntent, REQUEST_CODE_PICK_IMAGE);
                              } catch (Exception e) {
                                  e.printStackTrace();
                                  Toast.makeText(MainActivity.this,
                                          "请去\"设置\"中开启本应用的图片媒体访问权限",
                                          Toast.LENGTH_SHORT).show();
                                  restoreUploadMsg();
                              }
  
                          } else {
                              if (PermissionUtil.isOverMarshmallow()) {
                                  if (!PermissionUtil.isPermissionValid(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                                      Toast.makeText(MainActivity.this,
                                              "请去\"设置\"中开启本应用的图片媒体访问权限",
                                              Toast.LENGTH_SHORT).show();
  
                                      restoreUploadMsg();
                                      requestPermissionsAndroidM();
                                      return;
                                  }
  
                                  if (!PermissionUtil.isPermissionValid(MainActivity.this, Manifest.permission.CAMERA)) {
                                      Toast.makeText(MainActivity.this,
                                              "请去\"设置\"中开启本应用的相机权限",
                                              Toast.LENGTH_SHORT).show();
  
                                      restoreUploadMsg();
                                      requestPermissionsAndroidM();
                                      return;
                                  }
                              }
  
                              try {
                                  mSourceIntent = ImageUtil.takeBigPicture();
                                  startActivityForResult(mSourceIntent, REQUEST_CODE_IMAGE_CAPTURE);
  
                              } catch (Exception e) {
                                  e.printStackTrace();
                                  Toast.makeText(MainActivity.this,
                                          "请去\"设置\"中开启本应用的相机和图片媒体访问权限",
                                          Toast.LENGTH_SHORT).show();
  
                                  restoreUploadMsg();
                              }
                          }
                      }
                  }
          );
  
          alertDialog.show();
      }
  
      private void fixDirPath() {
          String path = ImageUtil.getDirPath();
          File file = new File(path);
          if (!file.exists()) {
              file.mkdirs();
          }
      }
  
      private class DialogOnCancelListener implements DialogInterface.OnCancelListener {
          @Override
          public void onCancel(DialogInterface dialogInterface) {
              restoreUploadMsg();
          }
      }
  
      private void restoreUploadMsg() {
          if (mUploadMsg != null) {
              mUploadMsg.onReceiveValue(null);
              mUploadMsg = null;
  
          } else if (mUploadMsgForAndroid5 != null) {
              mUploadMsgForAndroid5.onReceiveValue(null);
              mUploadMsgForAndroid5 = null;
          }
      }
  
      @Override
      public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
          switch (requestCode) {
              case P_CODE_PERMISSIONS:
                  requestResult(permissions, grantResults);
                  // Don't restore upload message here anymore, as the flow might continue
                  // restoreUploadMsg(); 
                  break;
  
              default:
                  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          }
      }
  
      private void requestPermissionsAndroidM() {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
              List<String> needPermissionList = new ArrayList<>();
              needPermissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
              needPermissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
              needPermissionList.add(Manifest.permission.CAMERA);
  
              PermissionUtil.requestPermissions(MainActivity.this, P_CODE_PERMISSIONS, needPermissionList);
  
          } else {
              return;
          }
      }
  
      public void requestResult(String[] permissions, int[] grantResults) {
          ArrayList<String> needPermissions = new ArrayList<String>();
  
          for (int i = 0; i < grantResults.length; i++) {
              if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                  if (PermissionUtil.isOverMarshmallow()) {
  
                      needPermissions.add(permissions[i]);
                  }
              }
          }
  
          if (needPermissions.size() > 0) {
              StringBuilder permissionsMsg = new StringBuilder();
  
              for (int i = 0; i < needPermissions.size(); i++) {
                  String strPermissons = needPermissions.get(i);
  
                  if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(strPermissons)) {
                      permissionsMsg.append("," + getString(R.string.permission_storage));
  
                  } else if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(strPermissons)) {
                      permissionsMsg.append("," + getString(R.string.permission_storage));
  
                  } else if (Manifest.permission.CAMERA.equals(strPermissons)) {
                      permissionsMsg.append("," + getString(R.string.permission_camera));
  
                  }
              }
              
              // Avoid NullPointerException if no R.string resources are found, by checking the length
              if (permissionsMsg.length() > 0) {
                  String strMessage = "请允许使用\"" + permissionsMsg.substring(1).toString() + "\"权限, 以正常使用APP的所有功能.";
                  Toast.makeText(MainActivity.this, strMessage, Toast.LENGTH_SHORT).show();
              }
  
          } else {
              return;
          }
      }
  
  }
  