• 华为机型cordova-plugin-image-picker读取图库闪退


    在测试cordova开发的安卓APP过程中,使用$cordovaImagePicker.getPictures(options)获取相册照片时,华为机型总是会闪退。

    config.xml已经添加了权限

     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.CAMERA" />

    如果先调用相机$cordovaCamera.getPicture(options)弹出权限申请,赋予权限后再调用$cordovaImagePicker.getPictures(options)就不会闪退。

    查看了一下调用相机插件cordova-plugin-camera源码org.apache.cordova.camera.CameraLauncher中的方法callTakePicture,可知其做了权限的检测,源码如下:

    /**
         * Take a picture with the camera.
         * When an image is captured or the camera view is cancelled, the result is returned
         * in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult.
         *
         * The image can either be returned as a base64 string or a URI that points to the file.
         * To display base64 string in an img tag, set the source to:
         *      img.src="data:image/jpeg;base64,"+result;
         * or to display URI in an img tag
         *      img.src=result;
         *
         * @param returnType        Set the type of image to return.
         * @param encodingType           Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
         */
        public void callTakePicture(int returnType, int encodingType) {
            boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
            boolean takePicturePermission = PermissionHelper.hasPermission(this, Manifest.permission.CAMERA);
    
            // CB-10120: The CAMERA permission does not need to be requested unless it is declared
            // in AndroidManifest.xml. This plugin does not declare it, but others may and so we must
            // check the package info to determine if the permission is present.
    
            if (!takePicturePermission) {
                takePicturePermission = true;
                try {
                    PackageManager packageManager = this.cordova.getActivity().getPackageManager();
                    String[] permissionsInPackage = packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
                    if (permissionsInPackage != null) {
                        for (String permission : permissionsInPackage) {
                            if (permission.equals(Manifest.permission.CAMERA)) {
                                takePicturePermission = false;
                                break;
                            }
                        }
                    }
                } catch (NameNotFoundException e) {
                    // We are requesting the info for our package, so this should
                    // never be caught
                }
            }
    
            if (takePicturePermission && saveAlbumPermission) {
                takePicture(returnType, encodingType);
            } else if (saveAlbumPermission && !takePicturePermission) {
                PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
            } else if (!saveAlbumPermission && takePicturePermission) {
                PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
            } else {
                PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions);
            }
        }

    然后又查看了一下cordova-plugin-image-picker插件com.synconset.ImagePicker.java的源码发现方法execute没有做权限检测直接执行this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0)方法,而这个方法最终调用的是android.app.Activity.java中的startActivityForResult(intent, requestCode)方法。

    android.app.Activity.java中startActivityForResult方法的源码:

    /**
         * Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
         * with no options.
         *
         * @param intent The intent to start.
         * @param requestCode If >= 0, this code will be returned in
         *                    onActivityResult() when the activity exits.
         *
         * @throws android.content.ActivityNotFoundException
         *
         * @see #startActivity
         */
        public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
            startActivityForResult(intent, requestCode, null);
        }

    可以看到这个方法加了@RequiresPermission,所以在没有权限的情况下直接调用可能会被拒绝。

    所以需要在调用前申请权限。

    解决:

    这是com.synconset.ImagePicker.java插件源码:

    /**
     * An Image Picker Plugin for Cordova/PhoneGap.
     */
    package com.synconset;
    
    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.CordovaPlugin;
    
    import org.apache.cordova.PermissionHelper;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.util.ArrayList;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.util.Log;
    
    public class ImagePicker extends CordovaPlugin {
        public static String TAG = "ImagePicker";
         
        private CallbackContext callbackContext;
        private JSONObject params;
         
        public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
             this.callbackContext = callbackContext;
             this.params = args.getJSONObject(0);
            if (action.equals("getPictures")) {
                Intent intent = new Intent(cordova.getActivity(), MultiImageChooserActivity.class);
                int max = 20;
                int desiredWidth = 0;
                int desiredHeight = 0;
                int quality = 100;
                if (this.params.has("maximumImagesCount")) {
                    max = this.params.getInt("maximumImagesCount");
                }
                if (this.params.has("width")) {
                    desiredWidth = this.params.getInt("width");
                }
                if (this.params.has("height")) {
                    desiredHeight = this.params.getInt("height");
                }
                if (this.params.has("quality")) {
                    quality = this.params.getInt("quality");
                }
                intent.putExtra("MAX_IMAGES", max);
                intent.putExtra("WIDTH", desiredWidth);
                intent.putExtra("HEIGHT", desiredHeight);
                intent.putExtra("QUALITY", quality);

           if (this.cordova != null) { this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0); } } return true; } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && data != null) { ArrayList<String> fileNames = data.getStringArrayListExtra("MULTIPLEFILENAMES"); JSONArray res = new JSONArray(fileNames); this.callbackContext.success(res); } else if (resultCode == Activity.RESULT_CANCELED && data != null) { String error = data.getStringExtra("ERRORMESSAGE"); this.callbackContext.error(error); } else if (resultCode == Activity.RESULT_CANCELED) { JSONArray res = new JSONArray(); this.callbackContext.success(res); } else { this.callbackContext.error("No images selected"); } } }

    这是我修改后添加了权限申请的代码:

    /**
     * An Image Picker Plugin for Cordova/PhoneGap.
     */
    package com.synconset;
    
    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.CordovaPlugin;
    
    import org.apache.cordova.PermissionHelper;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.util.ArrayList;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.util.Log;
    
    public class ImagePicker extends CordovaPlugin {
        public static String TAG = "ImagePicker";
         
        private CallbackContext callbackContext;
        private JSONObject params;
         
        public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
             this.callbackContext = callbackContext;
             this.params = args.getJSONObject(0);
            if (action.equals("getPictures")) {
                Intent intent = new Intent(cordova.getActivity(), MultiImageChooserActivity.class);
                int max = 20;
                int desiredWidth = 0;
                int desiredHeight = 0;
                int quality = 100;
                if (this.params.has("maximumImagesCount")) {
                    max = this.params.getInt("maximumImagesCount");
                }
                if (this.params.has("width")) {
                    desiredWidth = this.params.getInt("width");
                }
                if (this.params.has("height")) {
                    desiredHeight = this.params.getInt("height");
                }
                if (this.params.has("quality")) {
                    quality = this.params.getInt("quality");
                }
                intent.putExtra("MAX_IMAGES", max);
                intent.putExtra("WIDTH", desiredWidth);
                intent.putExtra("HEIGHT", desiredHeight);
                intent.putExtra("QUALITY", quality);
                //添加权限申请
                boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
                if(!saveAlbumPermission){
                    PermissionHelper.requestPermission(this, 0, Manifest.permission.READ_EXTERNAL_STORAGE);
                }else{
                    if (this.cordova != null) {
                        this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0);
                    }
                }
            }
            return true;
        }
        
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == Activity.RESULT_OK && data != null) {
                ArrayList<String> fileNames = data.getStringArrayListExtra("MULTIPLEFILENAMES");
                JSONArray res = new JSONArray(fileNames);
                this.callbackContext.success(res);
            } else if (resultCode == Activity.RESULT_CANCELED && data != null) {
                String error = data.getStringExtra("ERRORMESSAGE");
                this.callbackContext.error(error);
            } else if (resultCode == Activity.RESULT_CANCELED) {
                JSONArray res = new JSONArray();
                this.callbackContext.success(res);
            } else {
                this.callbackContext.error("No images selected");
            }
        }
    }

    这样问题就解决了。

  • 相关阅读:
    双十一脱单就靠它:创维小湃蓝牙音箱体验评测
    专注产品真正价值:iWALK真无线蓝牙耳机体验评测
    美好的童年伙伴:360 智能儿童手表 P1体验评测
    前端也要学系列:设计模式之装饰者模式
    前端也要学系列:设计模式之策略模式
    你不知道的Javascript:有趣的setTimeout
    接受”不完美“:分布式事务学习总结
    如何进行团队技术分享
    又是一年寒冬时
    mybatis ~ 批量更新(sql循环)update foreach
  • 原文地址:https://www.cnblogs.com/lyxy/p/6963928.html
Copyright © 2020-2023  润新知