国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

詳解Android WebView的input上傳照片的兼容問題

2019-12-12 02:15:14
字體:
來源:轉載
供稿:網友

問題

前幾天接到的一個需求,是關于第三方理財產品的H5上傳照片問題。

對方說他們的新的需求,需要接入方配合上傳資產照片的需求,測試之后發現我們這邊的app端,IOS端上傳沒有問題,而Android端則點擊沒有任何反應。

對方H5調用的方式是通過<input type='file' accept='image/*'/>的方式調用,本來以為這個問題很簡單,就是app端沒有設置相機權限,造成的點擊無反應情況,而實際上加了之后發現,并非簡單的權限問題。

解決問題

因為Android的版本碎片問題,很多版本的WebView都對喚起函數有不同的支持。

我們需要重寫WebChromeClient下的openFileChooser()(5.0及以上系統回調onShowFileChooser())。我們通過Intent在openFileChooser()中喚起系統相機和支持Intent的相關app。

在系統相機或者相關app中一頓操作之后,當返回app的時候,我們在onActivityResult()中將選擇好的圖片通過ValueCallback的onReceiveValue方法返回給WebView。

附上代碼:

1、首先是重寫各個版本的WebChromeClient的支持

webView.setWebChromeClient(new WebChromeClient() { //For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg) {   selectImage();   mUM = uploadMsg;   Intent i = new Intent(Intent.ACTION_GET_CONTENT);   i.addCategory(Intent.CATEGORY_OPENABLE);   i.setType("*/*");   MyBaseWebViewActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FCR); } // For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this public void openFileChooser(ValueCallback uploadMsg, String acceptType) {   selectImage();   mUM = uploadMsg;   Intent i = new Intent(Intent.ACTION_GET_CONTENT);   i.addCategory(Intent.CATEGORY_OPENABLE);   i.setType("*/*");   MyBaseWebViewActivity.this.startActivityForResult(       Intent.createChooser(i, "File Browser"),       FCR); } //For Android 4.1+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {   selectImage();   mUM = uploadMsg;   Intent i = new Intent(Intent.ACTION_GET_CONTENT);   i.addCategory(Intent.CATEGORY_OPENABLE);   i.setType("*/*");   MyBaseWebViewActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), MyBaseWebViewActivity.FCR); } //For Android 5.0+ public boolean onShowFileChooser(     WebView webView, ValueCallback<Uri[]> filePathCallback,     WebChromeClient.FileChooserParams fileChooserParams) {   selectImage();   if (mUMA != null) {     mUMA.onReceiveValue(null);   }   mUMA = filePathCallback;   Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);   if (takePictureIntent.resolveActivity(MyBaseWebViewActivity.this.getPackageManager()) != null) {     File photoFile = null;     try {       photoFile = createImageFile();       takePictureIntent.putExtra("PhotoPath", mCM);     } catch (IOException ex) {       Log.e(TAG, "Image file creation failed", ex);     }     if (photoFile != null) {       mCM = "file:" + photoFile.getAbsolutePath();       filePath = photoFile.getAbsolutePath();       takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));     } else {       takePictureIntent = null;     }   }   Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);   contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);   contentSelectionIntent.setType("*/*");   Intent[] intentArray;   if (takePictureIntent != null) {     intentArray = new Intent[]{takePictureIntent};   } else {     intentArray = new Intent[0];   }   Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);   chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);   chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");   chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);   startActivityForResult(chooserIntent, FCR);   return true; }});

2、選完照片之后

/*** 打開圖庫,同時處理圖片*/private void selectImage() {  compressPath = Environment.getExternalStorageDirectory().getPath() + "/QWB/temp";  File file = new File(compressPath);  if (!file.exists()) {    file.mkdirs();  }  compressPath = compressPath + File.separator + "compress.png";  File image = new File(compressPath);  if (image.exists()) {    image.delete();  }}// Create an image fileprivate File createImageFile() throws IOException {  @SuppressLint("SimpleDateFormat") String timeStamp = DateUtils.nowTimeDetail();  String imageFileName = "img_" + timeStamp + "_";  File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);  return File.createTempFile(imageFileName, ".jpg", storageDir);}private String mCM;private String filePath = "";private ValueCallback<Uri> mUM;private ValueCallback<Uri[]> mUMA;private final static int FCR = 1;String compressPath = "";@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) {  super.onActivityResult(requestCode, resultCode, intent);  if (Build.VERSION.SDK_INT >= 21) {    Uri[] results = null;    //Check if response is positive    if (resultCode == Activity.RESULT_OK) {      if (requestCode == FCR) {        if (null == mUMA) {          return;        }        if (intent == null) {          //Capture Photo if no image available          if (mCM != null) {            // results = new Uri[]{Uri.parse(mCM)};            results = new Uri[]{afterChosePic(filePath, compressPath)};          }        } else {          String dataString = intent.getDataString();          if (dataString != null) {            results = new Uri[]{Uri.parse(dataString)};            LogUtil.d("tag", intent.toString());//              String realFilePath = getRealFilePath(Uri.parse(dataString));//              results = new Uri[]{afterChosePic(realFilePath, compressPath)};          }        }      }    }    mUMA.onReceiveValue(results);    mUMA = null;  } else {    if (requestCode == FCR) {      if (null == mUM) return;      Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();      mUM.onReceiveValue(result);      mUM = null;    }  }}/*** 選擇照片后結束*/private Uri afterChosePic(String oldPath, String newPath) {  File newFile;  try {    newFile = FileUtils.compressFile(oldPath, newPath);  } catch (Exception e) {    e.printStackTrace();    newFile = null;  }  return Uri.fromFile(newFile);}

3、工具類

public class FileUtils {  /**   * 把圖片壓縮到200K   *   * @param oldpath   *      壓縮前的圖片路徑   * @param newPath   *      壓縮后的圖片路徑   * @return   */  public static File compressFile(String oldpath, String newPath) {    Bitmap compressBitmap = FileUtils.decodeFile(oldpath);    Bitmap newBitmap = ratingImage(oldpath, compressBitmap);    ByteArrayOutputStream os = new ByteArrayOutputStream();    newBitmap.compress(Bitmap.CompressFormat.PNG, 100, os);    byte[] bytes = os.toByteArray();    File file = null ;    try {      file = FileUtils.getFileFromBytes(bytes, newPath);    } catch (Exception e) {      e.printStackTrace();    }finally{      if(newBitmap != null ){        if(!newBitmap.isRecycled()){          newBitmap.recycle();        }        newBitmap = null;      }      if(compressBitmap != null ){        if(!compressBitmap.isRecycled()){          compressBitmap.recycle();        }        compressBitmap = null;      }    }    return file;  }  private static Bitmap ratingImage(String filePath,Bitmap bitmap){    int degree = readPictureDegree(filePath);    return rotaingImageView(degree, bitmap);  }  /**   * 旋轉圖片   * @param angle   * @param bitmap   * @return Bitmap   */  public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {    //旋轉圖片 動作    Matrix matrix = new Matrix();;    matrix.postRotate(angle);    System.out.println("angle2=" + angle);    // 創建新的圖片    Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,        bitmap.getWidth(), bitmap.getHeight(), matrix, true);    return resizedBitmap;  }  /**   * 讀取圖片屬性:旋轉的角度   * @param path 圖片絕對路徑   * @return degree旋轉的角度   */  public static int readPictureDegree(String path) {    int degree = 0;    try {      ExifInterface exifInterface = new ExifInterface(path);      int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);      switch (orientation) {        case ExifInterface.ORIENTATION_ROTATE_90:          degree = 90;          break;        case ExifInterface.ORIENTATION_ROTATE_180:          degree = 180;          break;        case ExifInterface.ORIENTATION_ROTATE_270:          degree = 270;          break;      }    } catch (IOException e) {      e.printStackTrace();    }    return degree;  }  /**   * 把字節數組保存為一個文件   *   * @param b   * @param outputFile   * @return   */  public static File getFileFromBytes(byte[] b, String outputFile) {    File ret = null;    BufferedOutputStream stream = null;    try {      ret = new File(outputFile);      FileOutputStream fstream = new FileOutputStream(ret);      stream = new BufferedOutputStream(fstream);      stream.write(b);    } catch (Exception e) {      // log.error("helper:get file from byte process error!");      e.printStackTrace();    } finally {      if (stream != null) {        try {          stream.close();        } catch (IOException e) {          // log.error("helper:get file from byte process error!");          e.printStackTrace();        }      }    }    return ret;  }  /**   * 圖片壓縮   *   * @param fPath   * @return   */  public static Bitmap decodeFile(String fPath) {    BitmapFactory.Options opts = new BitmapFactory.Options();    opts.inJustDecodeBounds = true;    opts.inDither = false; // Disable Dithering mode    opts.inPurgeable = true; // Tell to gc that whether it needs free    opts.inInputShareable = true; // Which kind of reference will be used to    BitmapFactory.decodeFile(fPath, opts);    final int REQUIRED_SIZE = 400;    int scale = 1;    if (opts.outHeight > REQUIRED_SIZE || opts.outWidth > REQUIRED_SIZE) {      final int heightRatio = Math.round((float) opts.outHeight          / (float) REQUIRED_SIZE);      final int widthRatio = Math.round((float) opts.outWidth          / (float) REQUIRED_SIZE);      scale = heightRatio < widthRatio ? heightRatio : widthRatio;//    }    Log.i("scale", "scal ="+ scale);    opts.inJustDecodeBounds = false;    opts.inSampleSize = scale;    Bitmap bm = BitmapFactory.decodeFile(fPath, opts).copy(Bitmap.Config.ARGB_8888, false);    return bm;  }   /**   * 創建目錄   * @param path   */  public static void setMkdir(String path)  {    File file = new File(path);    if(!file.exists())    {      file.mkdirs();      Log.e("file", "目錄不存在 創建目錄  ");    }else{      Log.e("file", "目錄存在");    }  }  /**   * 獲取目錄名稱   * @param url   * @return FileName   */  public static String getFileName(String url)  {    int lastIndexStart = url.lastIndexOf("/");    if(lastIndexStart!=-1)    {      return url.substring(lastIndexStart+1, url.length());    }else{      return null;    }  }  /**   * 刪除該目錄下的文件   *   * @param path   */  public static void delFile(String path) {    if (!TextUtils.isEmpty(path)) {      File file = new File(path);      if (file.exists()) {        file.delete();      }    }  }}

4、需要注意的問題

在打release包的時候,因為混淆的問題,點擊又會沒有反應,這是因為openFileChooser()是系統api,所以需要在混淆是不混淆該方法。

-keepclassmembers class * extends android.webkit.WebChromeClient{public void openFileChooser(...);}

當點擊拍照之后,如果相機是橫屏拍照的話,當拍照結束之后跳回app的時候,會導致app端當前的webView頁面銷毀并重新打開,需要在androidManifest.xml中當前Activity添加:

android:configChanges="orientation|keyboardHidden|screenSize"

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 莎车县| 上林县| 云霄县| 阜新市| 仙居县| 太保市| 顺昌县| 湘潭县| 大足县| 文安县| 石阡县| 双辽市| 汤原县| 陆河县| 株洲市| 利川市| 虞城县| 合江县| 台东市| 绥化市| 田林县| 虎林市| 棋牌| 沂水县| 环江| 甘孜| 皮山县| 万荣县| 大同市| 哈密市| 定日县| 巫山县| 绥化市| 弥渡县| 永川市| 泗洪县| 建宁县| 庐江县| 万宁市| 汉寿县| 宁夏|