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);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在Javascript中直接调用安卓相机返回base64编码,需要使用Cordova或其他类似的移动应用开发框架。这些框架提供了访问设备硬件的API,以便从Javascript中调用原生代码。 以下是一些步骤来实现这个目标: 1. 安装Cordova并创建一个新项目。 2. 添加一个插件来访问相机API,例如cordova-plugin-camera。 3. 在Javascript代码中编写一个函数来打开相机并获取照片。这可以通过调用navigator.camera.getPicture()实现。您可以指定选项来配置相机行为,例如图像质量、旋转等等。 4. 在获取照片后,您可以使用window.atob()函数将图像数据从base64字符串解码为二进制数据。 5. 最后,您可以将二进制数据编码为base64字符串,以便在Javascript代码中进行处理。 以下是一个示例代码片段,演示了如何使用Cordova和cordova-plugin-camera插件来获取照片并将其编码为base64字符串: ```javascript // 点击按钮时调用此函数 function takePicture() { navigator.camera.getPicture( function(imageData) { // 将base64编码的图像数据解码为二进制数据 var binaryData = window.atob(imageData); // 创建一个Uint8Array以便访问二进制数据 var bytes = new Uint8Array(binaryData.length); for (var i = 0; i < binaryData.length; i++) { bytes[i] = binaryData.charCodeAt(i); } // 将二进制数据编码为base64字符串 var base64Data = btoa(String.fromCharCode.apply(null, bytes)); // 现在您可以在这里处理base64Data字符串 }, function(errorMessage) { console.log('获取照片失败: ' + errorMessage); }, { quality: 50, // 图像质量 destinationType: Camera.DestinationType.DATA_URL // 返回base64编码的图像数据 } ); } ``` 请注意,此代码假设您已经正确安装了Cordova和cordova-plugin-camera插件,并且已经在设备上进行了正确配置。 ### 回答2: 使用JavaScript调用Android相机返回Base64编码的步骤如下: 1. 首先,你需要创建一个HTML页面,并在其中引入JavaScript代码。你可以使用以下代码作为起始点: ```html <!DOCTYPE html> <html> <head> <title>调用Android相机返回Base64编码</title> </head> <body> <button id="capture-btn">拍照</button> <script> // JavaScript代码将在这里插入 </script> </body> </html> ``` 2. 在JavaScript代码部分,你需要使用JavaScript与Android原生代码进行通信。可以使用JavaScript的`Window`对象的`WebView`接口与安卓进行通信。 ```javascript <script> var captureBtn = document.getElementById('capture-btn'); // 在按钮被点击时调用Android相机 captureBtn.addEventListener('click', function() { window.android.capturePhoto(); // 调用Android的拍照方法 }); // 接收从Android返回Base64编码 window.receiveBase64 = function(base64) { // 在这里使用Base64编码 console.log(base64); }; </script> ``` 3. 在你的Android原生代码中,你需要通过WebView设置接口以便JavaScript代码可以调用它。以下是一个示例: ```java import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Base64; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebView; import android.webkit.WebViewClient; public class MainActivity extends Activity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); // 添加JavaScript接口 webView.addJavascriptInterface(this, "android"); // 设置WebViewClient以使WebView在应用内加载链接 webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } }); // 加载你的HTML页面 webView.loadUrl("file:///android_asset/index.html"); } // 用于从Android调用JavaScript方法的方法 @JavascriptInterface public void capturePhoto() { // 打开相机 Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, 0); } // 在拍照完成后返回结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && data != null) { Uri uri = data.getData(); // 将图像转换为Base64编码 String base64 = imageToBase64(uri); // 将Base64编码发送给JavaScript webView.loadUrl("javascript:receiveBase64('" + base64 + "')"); } } // 将图像转换为Base64编码的辅助方法 private String imageToBase64(Uri uri) { // 从URI中读取图像数据 // 将图像数据转换为Base64编码字符串 // 返回Base64编码字符串 } } ``` 这就是使用JavaScript调用Android相机返回Base64编码的基本步骤。你需要根据你的实际需求进行适当的调整和完善。请注意,上述代码仅供参考,并且可能需要根据你的项目进行额外的自定义和错误处理。 ### 回答3: 要使用JavaScript直接调用Android相机返回基于base64的编码,可以使用HTML5中的getUserMedia API和Canvas元素来实现。以下是一个简单的例子: 首先,在HTML中添加一个用于显示摄像头捕获图像的Canvas元素: ``` <canvas id="cameraOutput"></canvas> ``` 接下来,在JavaScript中获取用户媒体流并将其显示在Canvas上: ``` const canvas = document.getElementById('cameraOutput'); const context = canvas.getContext('2d'); navigator.mediaDevices.getUserMedia({ video: true }) .then(function(stream) { const video = document.createElement('video'); video.srcObject = stream; video.play(); // 每帧都将视频图像绘制到Canvas中 const drawFrame = function() { context.drawImage(video, 0, 0, canvas.width, canvas.height); requestAnimationFrame(drawFrame); }; drawFrame(); }) .catch(function(error) { console.error('无法访问相机:', error); }); ``` 现在,我们有了相机捕获的图像显示在Canvas上。然后,我们可以通过将Canvas上的图像转换为base64编码来获取图像数据: ``` const canvas = document.getElementById('cameraOutput'); const context = canvas.getContext('2d'); // 获取Canvas上的图像数据 const getImageData = function() { return canvas.toDataURL('image/jpeg', 1.0); }; // 调用此函数以获取基于base64的图像编码 const base64Image = getImageData(); console.log(base64Image); ``` 通过以上方法,我们可以直接在JavaScript中调用Android相机返回基于base64的图像编码。请注意,这仅适用于支持getUserMedia API的现代浏览器和设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值