RN調取Android原生相機並且把圖片轉化成base64的形式返回給RN 7.0權限跳轉intent問題

首先要特別提醒的地方就是版本問題,我就是因爲版本問題,剛開始搞得我的項目一直報錯。。。

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
android.os.FileUriExposedException: file:///storage/emulated/0/IDCardSDKCaller/card.jpg exposed beyond app through ClipData.Item.getUri()

主要就是因爲版本問題,剛開始百度的時候,告訴我說是因爲權限問題,讓我添加權限,後來多次嘗試無果,後來才知道,這因爲版本6.0前後的問題,首先看個比較簡單的就是選擇本地圖片,這個沒什麼問題

 /*選圖*/
  @ReactMethod
  public void RNCallSelectedPhotoAction(Callback callback) {
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
    intent.setType("image/*");// 相片類型
    getCurrentActivity().startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
    this.callback = callback;
  }

這個選擇圖片去網上搜索,一大把,都是通用的,當然也沒什麼問題,最主要的問題就是拍照,因爲權限問題,所以肯定就是要進行判斷了

/*拍照*/
  @ReactMethod
  private void RNCallStartCapture(Callback callback) {
    this.callback = callback;
    if (mTakePicPath == null) {
      mTakePicPath = DIR_ICR + "/" + System.currentTimeMillis() + ".jpg";
    }
    File dir = new File(mTakePicPath);
    if (!dir.exists()) {
      try {
        dir.createNewFile();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      uri = FileProvider.getUriForFile(MyContext,BuildConfig.APPLICATION_ID + ".provider",dir);
    }else {
      uri = Uri.fromFile(dir);
    }
    openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    getCurrentActivity().startActivityForResult(openCameraIntent, REQUEST_CAPTURE_PIC);
  }

這個方法就是給rn發送數據當然要注意上下文環境

/**
   * Native調用RN
   * 給rn發送數據
   * @param msg
   */
  public void nativeCallRn(String msg) {
    MyContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("nativeCallRn", msg);
    callback.invoke(msg);
  }

拍照和選擇圖片呢我主要是利用onActivityResult 來獲取數據結果的

if (requestCode == REQUEST_CODE_PICK_IMAGE) {
        // 選擇圖片
        if(null!=data){
          String imgPath = getPathFromUri(getCurrentActivity(), data.getData());
          imagePathCompression(imgPath);
        }
      }else if (requestCode == REQUEST_CAPTURE_PIC) {
        String photoPath;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
          photoPath = String.valueOf(mTakePicPath);
        } else {
          photoPath = uri.getEncodedPath();
        }
        imagePathCompression(photoPath);
      }

這個就是拍照和選擇圖片獲取到的數據,當然要注意權限的判斷,獲取的結果也是不一樣的,
imagePathCompression 這個方法是我自己根據魯班壓縮自己寫的一個簡單方法,(說到魯班,強烈建議使用,一款仿微信壓縮的,個人覺得寫的特別好)

  public void imagePathCompression(String imagePath) {
    File file = new File(imagePath);
    if(file.length()>1024*500){
      Log.e("zeng","壓縮"+imagePath);
      Luban.with(MyContext)
              .load(imagePath)
              .ignoreBy(100)
              .filter(new CompressionPredicate() {
                @Override
                public boolean apply(String path) {
                  return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif"));
                }
              })
              .setCompressListener(new OnCompressListener() {
                @Override
                public void onStart() {
                  // TODO 壓縮開始前調用,可以在方法內啓動 loading UI
                }

                @Override
                public void onSuccess(File file) {
                  // TODO 壓縮成功後調用,返回壓縮後的圖片文件
                  String s1 = fileToBase64(file);
                  nativeCallRn(s1);
                }

                @Override
                public void onError(Throwable e) {
                  // TODO 當壓縮過程出現問題時調用
                }
              }).launch();
    }else {
      String s = imageToBase64(imagePath);
      Log.e("zeng","不壓縮"+s);
      nativeCallRn(s);
    }
  }

這樣的話一個簡單的拍照,選擇圖片就做好了,當然還有轉化base64壓縮

 RNCallAndroidAction.compressImage( ( msg) => { })

這個是rn裏面寫的監聽方法

這個是跳轉到安裝頁面的權限判斷

private void installAPk(File apkFile) {
        Log.d("zengapkFile", "upgrade: 進來了"+apkFile);
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+以上版本
            Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", apkFile); //與manifest中定義的provider中的authorities="com.shawpoo.app.fileprovider"保持一致
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        }
        startActivity(intent);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章