Cocos Creator 调用原生相册图片裁剪显示存储本地或者传到服务器(base64)

先讲一堆废话: 打包这里就不介绍了,这个可以直接根据 Cocos 官网操作,已经很详细了。我就不多说废话开干! (有问题加QQ群交流:891502641)

再讲讲思路:首先通过JS/TS 这边调用原生平台的相册资源 ,获取资源后再调用原生系统裁剪功能,获得的图片资源转成 base64 传递给JS/TS . 大概流程就是这样,下面看代码吧

参考文章:https://blog.csdn.net/u013121055/article/details/115498969

js/Ts 代码

  

 
// 类型,是否需要裁剪,裁剪尺寸,回调方法
PlatForm.pickImage = function(type,needClip,clipSize,callback){
    PlatForm.onChoosePhotoCallback = callback;
    if(needClip == undefined){
        needClip = false;
    }
    var clipX = 0;
    var clipY = 0;
    if(clipSize){
        clipX = clipSize.x;
        clipY = clipSize.y;
    }
    var dict ={
        needClip:needClip, //1是裁剪,2是不裁剪
        clipX:clipX, //裁剪x尺寸
        clipY:clipY, //裁剪y尺寸
    }
    if(cc.sys.os === cc.sys.OS_ANDROID){
        var className = "org/cocos2dx/javascript/AppActivity"
        var methodName = "pickImage";
        var methodSignature = "(Ljava/lang/String;)V";
        if(type == Config.ChoosephotoType.Album){
            methodName = "useSystemAlbum";
        }else if(type == Config.ChoosephotoType.Camera){
            methodName = "useSystemCamera";
        }
        var ret = jsb.reflection.callStaticMethod(className,methodName,methodSignature,JSON.stringify(dict));
        console.log("androidTakePhotoret:",ret)
        return ret;
    }else if(cc.sys.os === cc.sys.OS_IOS){
        console.log("js 请求相册");
        var ret = null;
        if(type == Config.ChoosephotoType.Album){
            ret = jsb.reflection.callStaticMethod("AppController","pickImage:",JSON.stringify(dict));
        }else if(type == Config.ChoosephotoType.Camera){
            ret = jsb.reflection.callStaticMethod("AppController","takePhoto:",JSON.stringify(dict));
        }
        return ret
    }
}

接下来就该写原生平台的一些调用代码了

IOS选取图片

AppController.h 实现UIImagePickerControllerDelegate接口

@interface AppController : NSObject <UIApplicationDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
{
}

选择相册 

 
// 选择图片
+(void) pickImage:(NSString*) dict{
    NSData *data = [dict dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSNumber *needClip = [dictionary objectForKey:@"needClip"];
    
    NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
    [defaults setObject:needClip forKey:@"needClip"];
    
    photoName = [dictionary objectForKey:@"name"];
    NSLog(@"takePhoto param = %@,%@",needClip,photoName);
    UIImagePickerController *pickerImage = [[UIImagePickerController alloc] init];
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        pickerImage.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        pickerImage.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:pickerImage.sourceType];
    }
    AppController *pApp = (AppController*)[[UIApplication sharedApplication] delegate];
    pickerImage.delegate = pApp;
    pickerImage.allowsEditing = ([needClip intValue] == 1?YES:NO); // 传入是否可以裁剪参数
    [pApp->_viewController  presentViewController:((UIImagePickerController *)pickerImage) animated:YES completion:nil];
}

选择相机

 
+(void) takePhoto:(NSString*) dict{
    NSData *data = [dict dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSNumber *needClip = [dictionary objectForKey:@"needClip"];
    photoName = [dictionary objectForKey:@"name"];
    
    NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
    [defaults setObject:needClip forKey:@"needClip"];
 
    NSLog(@"takePhoto param = %@,%@",needClip,photoName);
    UIImagePickerController *pickerImage = [[UIImagePickerController alloc] init];
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        pickerImage.sourceType = UIImagePickerControllerSourceTypeCamera;
        pickerImage.cameraDevice = UIImagePickerControllerCameraDeviceFront; //调用前置摄像头,后置摄像头为:UIImagePickerControllerCameraDeviceRear
    }
    AppController *pApp = (AppController*)[[UIApplication sharedApplication] delegate];
    pickerImage.delegate = pApp;
    pickerImage.allowsEditing = ([needClip intValue] == 1?YES:NO); // 传入是否可以裁剪参数
    [pApp->_viewController  presentViewController:((UIImagePickerController *)pickerImage) animated:YES completion:nil];
}

获取图片后回调

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)editingInfo
{
    NSLog(@"imagePickerController info = %@",editingInfo);
    NSString * fileName = [self getFormatTimeInterval:@".jpg"];
    NSLog(@"fileName = %@",fileName);
    NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
    NSNumber *needClip = [defaults objectForKey:@"needClip"];//根据键值取出是否需要裁剪
    NSLog(@"保存的needClip==%@",needClip);
    if([needClip intValue] == 1){
        [self saveImage:editingInfo[UIImagePickerControllerEditedImage] WithName:fileName];
    }else{
        [self saveImage:editingInfo[UIImagePickerControllerOriginalImage] WithName:fileName];
    }
    [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
    [picker release];
}
 
//使用时间戳作为图片名称
-(NSString*)getFormatTimeInterval:(NSString *) fileType{
    UInt64 recordTime = [[NSDate date] timeIntervalSince1970] *1000 *1000;
    NSString * systemCurTime = [NSString stringWithFormat:@"%qu%@",recordTime,fileType];
    return systemCurTime;
}

保存照片并转化为base64字符串,这里是上传头像,避免照片过大,压缩为0.3倍,其他场景可酌情修改倍数。最后调用js代码传递保存图片路径和base64字符串。

- (void)saveImage:(UIImage *)tempImage WithName:(NSString *)imageName
{
    NSData* imageData = UIImagePNGRepresentation(tempImage);
    NSString* documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* totalPath = [documentPath stringByAppendingPathComponent:imageName];
    
    //保存到 document
    [imageData writeToFile:totalPath atomically:NO];
    
    NSString *base64Image = [self imageToString:tempImage];
    
    NSLog(@"保存图片完整路径=%@",totalPath);
    NSLog(@"保存图片document路径=%@",documentPath);
    NSLog(@"图片转化为base64:%@",base64Image);
    NSString *execStr = [NSString stringWithFormat:@"%@('%@','%@')", @"PlatForm.onPickImageResult",totalPath,base64Image];
    NSLog(@"调用js语句::%@",execStr);
    se::ScriptEngine::getInstance()->evalString([execStr UTF8String]);
}
 
 
//图片转base64
- (NSString *)imageToString:(UIImage *)image {
    NSData *imagedata = UIImageJPEGRepresentation(image,0.3); //压缩到0.3倍
    NSString *image64 = [imagedata base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    return image64;
}

最后,不要忘记在info.plist添加调用相册相机权限

 --------------------------------------------------------------------------------------------------------------------------------------------以上都IOS系统的操作 ————————————————————————————————————

本文章若有侵权,请联系删除 QQ:946692837 (只想让相关知识让更多的人知道)

下面就是android获取相册图片等操作(本人亲身遇到了一个问题就是裁剪之后 的图片资源转base64的时候为null,具体什么原因,经过反复调试,发现是文件系统刷新的一个问题,在生成图片资源想要立即用请手动调用一下代码刷新相册。废话不多说,上代码)

Android选取图片


1.首先在AndroidManifest.xml添加读写权限

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

 

2.AppActivity实现js调用Java接口

调用相册,动态获取权限

    /**
     * 调用系统相册和裁剪
     * @param info
     */
    public static void useSystemAlbum(String info){
        clipX = 0;
        clipY = 0;
        try{
       //反序列化我们从JS/TS传到JAVA的参数 JSONObject jsonObject
= new JSONObject(info); needClip = jsonObject.getInt("needClip"); clipX = jsonObject.getInt("clipX"); clipY = jsonObject.getInt("clipY"); }catch(Exception e){ e.printStackTrace(); } pickImage(); } /** * 选择相册上传图片 */ public static void pickImage(){ photoType = 1; String[] needPermissions = new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}; List<String> permissionList = new ArrayList<>(); for (String permission : needPermissions) { if (ContextCompat.checkSelfPermission(instance, permission) != PackageManager.PERMISSION_GRANTED) permissionList.add(permission); } if (permissionList.size() == 0) { // Log.i("pickImg","已经获取到所有权限"); goPhotoAlbum(); }else{ String[] requestPermissions = permissionList.toArray(new String[permissionList.size()]); ActivityCompat.requestPermissions(instance,requestPermissions, 1001); } } public static void goPhotoAlbum(){ Intent intentAlbum= new Intent(Intent.ACTION_PICK, null); //其中External为sdcard下的多媒体文件,Internal为system下的多媒体文件。 //使用INTERNAL_CONTENT_URI只能显示存储在内部的照片 intentAlbum.setDataAndType( MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*"); //返回结果和标识 instance.startActivityForResult(intentAlbum, REQUEST_CODE_ALBUM); }

调用相机,动态获取权    /**

     * 调用系统相机和裁剪
     * @param info
     */
    public static void useSystemCamera(String info){
        clipX = 0;
        clipY = 0;
        try{
            JSONObject jsonObject = new JSONObject(info);
            needClip = jsonObject.getInt("needClip");
            clipX = jsonObject.getInt("clipX");
            clipY = jsonObject.getInt("clipY");
        }catch(Exception e){
            e.printStackTrace();
        }
 
        takePhoto();
    }
 
 
 /**
     * 选择相机上传图片
     */
    public static void takePhoto(){
        photoType = 2;
//        Log.i("pickImg","takePhoto调用");
        String[] needPermissions = new String[] {
                Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA};
        List<String> permissionList = new ArrayList<>();
        for (String permission : needPermissions) {
            if (ContextCompat.checkSelfPermission(instance, permission) != PackageManager.PERMISSION_GRANTED)
                permissionList.add(permission);
        }
        if (permissionList.size() == 0) {
//            Log.i("pickImg","已经获取到所有权限");
            callCamera();
 
        }else{
            String[] requestPermissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(instance,requestPermissions, 1002);
        }
    }
 
public static void callCamera(){ Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 判断是否有相机 if (captureIntent.resolveActivity(instance.getPackageManager()) != null) { File photoFile = null; Uri photoUri = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 适配android 10 photoUri = createImageUri(); } else { try { photoFile = createImageFile(); } catch (IOException e) { e.printStackTrace(); } if (photoFile != null) { mCameraImagePath = photoFile.getAbsolutePath(); // System.out.println("path = "+mCameraImagePath); if (/*Build.VERSION.SDK_INT >= Build.VERSION_CODES.N*/true) {//7.0到9.0 //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri 如:content:// photoUri = FileProvider.getUriForFile(instance, "com.heart.LudoMatePro.fileprovider", photoFile); } else {//7.0以下, 如:file:// photoUri = Uri.fromFile(photoFile); } } } System.out.println("photoUri = "+photoUri); mCameraUri = photoUri; if (photoUri != null) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { List<ResolveInfo> resInfoList = instance.getPackageManager() .queryIntentActivities(captureIntent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; instance.grantUriPermission(packageName, photoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } } captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); instance.startActivityForResult(captureIntent, REQUEST_CODE_CAMERA); } } } /** * 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法 * @return 图片的uri */ private static Uri createImageUri() { //设置保存参数到ContentValues中 ContentValues contentValues = new ContentValues(); //设置文件名 contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis()+""); //兼容Android Q和以下版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //android Q中不再使用DATA字段,而用RELATIVE_PATH代替 //TODO RELATIVE_PATH是相对路径不是绝对路径;照片存储的地方为:内部存储/Pictures/preventpro contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/preventpro"); } //设置文件类型 contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/JPEG"); //执行insert操作,向系统文件夹中添加文件 //EXTERNAL_CONTENT_URI代表外部存储器,该值不变 Uri uri = instance.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); return uri; } /** * 创建保存图片的文件 * @return * @throws IOException */ private static File createImageFile() throws IOException { String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()) +".jpg"; File storageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +File.separator+"Pictures"+File.separator+"abc"); if (!storageDir.exists()) storageDir.mkdirs(); File tempFile = new File(storageDir, imageName); if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) { return null; } return tempFile; }

接下来

下面就是处理 startActivityForResult() 打开相册界面获取图片结果后的回调 onActivityResult()

 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        FaceBookLogin.callbackManager.onActivityResult(requestCode, resultCode, data);
        SDKWrapper.getInstance().onActivityResult(requestCode, resultCode, data);
        if(requestCode == REQUEST_CODE_ALBUM && resultCode == RESULT_OK){
            Log.i("pickImg ","调用相册回调");
            if(data != null){
                if(needClip == 1){
                    startPhotoZoom(data.getData());
                    return;
                }
                String filePath = null;
                if (resultCode == RESULT_OK) {
                    //判断手机的系统版本号
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                        //4.4系统的及以上用此方法处理照片
                        filePath =  handleImageOnKitkat(data);
                    } else {
                        // 4.4以下的使用这个方法处理照片
                        filePath =  handleImageBeforeKitkat(data);
                    }
                }
                File file = new File(filePath);
                Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                String base64Bitmap = bitmapToBase64(bitmap);
                final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
                instance.runOnGLThread(new Runnable() {
                    @Override
                    public void run() {
                        Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                        Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
                    }
                });
            }
        }else if(requestCode == REQUEST_CODE_CAMERA && resultCode == RESULT_OK){
            Bitmap bitmap = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 
 
 
                if(needClip == 1){
                    startPhotoZoom(mCameraUri);
                    return;
                }
                String filePath = changeUriToPath(mCameraUri);
                bitmap = BitmapFactory.decodeFile(filePath);
                String base64Bitmap = bitmapToBase64(bitmap);
                final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
                instance.runOnGLThread(new Runnable() {
                    @Override
                    public void run() {
                        Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                        Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
                    }
                });
            } else {
                bitmap = BitmapFactory.decodeFile(mCameraImagePath);
                String base64Bitmap = bitmapToBase64(bitmap);
                Log.i("pickImg ","base64Image222 = "+base64Bitmap);
                final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",mCameraImagePath,base64Bitmap);
                instance.runOnGLThread(new Runnable() {
                    @Override
                    public void run() {
                        Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                        Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
                    }
                });
            }
 
        }else if(requestCode == REQUEST_CODE_CROP && resultCode == RESULT_OK){
            Log.i("pickImg","裁剪完成"+data.getData());
            if(data != null){
                if(photoType == 1){
                    String filePath = null;
                    if (resultCode == RESULT_OK) {
                        //判断手机的系统版本号
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            //4.4系统的及以上用此方法处理照片
//                            filePath =  handleImageOnKitkat(data);
                            filePath  = changeUriToPath(uriClipUri);
                        } else {
                            // 4.4以下的使用这个方法处理照片
//                            filePath =  handleImageBeforeKitkat(data);
                            filePath = getImagePath(uriClipUri, null);
                        }
 
                    }
            
             File file = new File(filePath);
            // 这里可能就会通过filePath找不到裁剪后的图片资源,所以需要手动去刷新相册
            //扫描保存的照片文件、刷新相册
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            Uri uri = Uri.fromFile(new File(imagePath));
            intent.setData(uri);
            instance.sendBroadcast(intent);
            

            // 这里还可以写个延时执行代码,因为创建文件还需要点时间
            //Timer timer = new Timer();
            //timer.schedule(new TimerTask() {
         //@Override
         //public void run() {
             // Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                     // String base64Bitmap = bitmapToBase64(bitmap);
                      //final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
                      //instance.runOnGLThread(new Runnable() {
                         // @Override
                          //public void run() {
                             // Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                              //Log.i("pickImg","crop返回path,base64,callFuncStr = "+callJsFunc);
                          //}
                      //});

          //}}, 500);
            
              Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                      String base64Bitmap = bitmapToBase64(bitmap);
                      final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
                      instance.runOnGLThread(new Runnable() {
                          @Override
                          public void run() {
                              Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                              Log.i("pickImg","crop返回path,base64,callFuncStr = "+callJsFunc);
                          }
                      });

}else if(photoType == 2){
                    Bitmap bitmap = null;
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        String filePath = changeUriToPath(mCameraUri);
                        bitmap = BitmapFactory.decodeFile(filePath);
                        String base64Bitmap = bitmapToBase64(bitmap);
                        final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
                        instance.runOnGLThread(new Runnable() {
                            @Override
                            public void run() {
                                Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                                Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
                            }
                        });
                    } else {
                        bitmap = BitmapFactory.decodeFile(mCameraImagePath);
                        String base64Bitmap = bitmapToBase64(bitmap);
                        final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",mCameraImagePath,base64Bitmap);
                        instance.runOnGLThread(new Runnable() {
                            @Override
                            public void run() {
                                Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
                                Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
                            }
                        });
                    }
 
                }
            }
        }
 
    }

由于上面获取了相册图片之后,还没裁剪,所以这是就需要调用 裁剪方法

 
    /**
     * 图片裁剪的方法
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
//        Log.i("pickImg uri=====", "" + uri);
        //com.android.camera.action.CROP,这个action是调用系统自带的图片裁切功能
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");//裁剪的图片uri和图片类型
        intent.putExtra("crop", true);//设置允许裁剪,如果不设置,就会跳过裁剪的过程,还可以设置putExtra("crop", "circle")
        intent.putExtra("aspectX", 1);//裁剪框的 X 方向的比例,需要为整数
        intent.putExtra("aspectY", 1);//裁剪框的 Y 方向的比例,需要为整数
//        intent.putExtra("outputX", 60);//返回数据的时候的X像素大小。
//        intent.putExtra("outputY", 60);//返回数据的时候的Y像素大小。
        if(clipX != 0 && clipY != 0){
            intent.putExtra("OutputX", clipX);// 设置最终裁剪的宽和高
            intent.putExtra("OutputY", clipY);// 设置最终裁剪的宽和高
//            Log.i("pickImg","设置裁剪输出宽和高="+clipX+"-"+clipY);
        }
        //uriClipUri为Uri类变量,实例化uriClipUri
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (photoType == 2) {//如果是7.0的拍照
                //开启临时访问的读和写权限
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                //针对7.0以上的操作
                intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uri));
                uriClipUri = uri;
            } else if(photoType == 1) {//如果是7.0的相册
                //设置裁剪的图片地址Uri
                uriClipUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" +"clip.jpg");
//                Log.i("pickImg","android 7.0调用相册= "+uriClipUri);
            }
 
        } else {
            uriClipUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "clip.jpg");
        }
//        Log.i("pickImg uriClipUri=====", "" + uriClipUri);
        //Android 对Intent中所包含数据的大小是有限制的,一般不能超过 1M,否则会使用缩略图 ,所以我们要指定输出裁剪的图片路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uriClipUri);
        intent.putExtra("return-data", false);//是否将数据保留在Bitmap中返回
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//输出格式,一般设为Bitmap格式及图片类型
        intent.putExtra("noFaceDetection", true);//人脸识别功能
        instance.startActivityForResult(intent, REQUEST_CODE_CROP);//裁剪完成的标识
    }

上面的代码就来到裁剪界面,这是startActivityForResult()会将才裁剪后的数据再次传入到 onActivityResult()中,此时请求的参数 REQUEST_CODE_CROP (REQUEST_CODE_CROP 自己定义静态变量,不要在文中可能代码片段中可能不会出现)。

在onActivityResult()中,根据相关的文件uri拿到图片资源

 

接下来是处理图片路径4.4之后

 
    private String handleImageOnKitkat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        imagePath = changeUriToPath(uri);
        return imagePath;
    }
 
    private String changeUriToPath(Uri uri){
        String imagePath = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (DocumentsContract.isDocumentUri(this, uri)) {
                //如果是document类型的uri,则通过document id 处理
                String docId = DocumentsContract.getDocumentId(uri);
                if("com.android.providers.media.documents".equals(uri.getAuthority())) {
                    //解析出数字格式的id
                    String id  = docId.split(":")[1];
                    String selection = MediaStore.Images.Media._ID+ "=" +id;
                    imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection );
                } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                    Uri contentUri = ContentUris.withAppendedId(Uri.parse
                            ("content://downloads/public_downloads"),Long.valueOf(docId));
                    imagePath = getImagePath(contentUri, null);
                }
            } else if ("content".equalsIgnoreCase(uri.getScheme())) {
                //如果是content类型的uri,则用普通方式处理
                imagePath = getImagePath(uri, null);
            } else if ("file".equalsIgnoreCase(uri.getScheme())) {
                //如果是file类型的uri,直接获取图片路径
                imagePath = uri.getPath();
            }
        }
        return imagePath;
    }

处理图片路径4.4之前

 
    private String handleImageBeforeKitkat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        return imagePath;
    }
 
 
    private String getImagePath(Uri uri,String selection) {
        String path = null;
        //通过uri 和 selection 获取真实的图片路径
        Cursor cursor = getContentResolver().query(uri,null,selection,null,null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images
                        .Media.DATA));
            }
            cursor.close();
        }
        return path;
    }

Bitmap转base64字符串,30位压缩质量为原来的30%

 
    public static String bitmapToBase64(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);
                baos.flush();
                baos.close();
 
                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.NO_WRAP);
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.i("pickImg","io exception111");
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                Log.i("pickImg","io exception222");
                e.printStackTrace();
            }
        }
        return result;
    }

AndroidManifest.xml里面增加FileProvider配置

 <provider
      android:name="androidx.core.content.FileProvider"
      android:authorities="你的包名.fileprovider"
      android:grantUriPermissions="true"
      android:exported="false">
      <meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/file_paths" />
 </provider>

另外,上面定义了xml/file_paths,需要在res目录下面创建xml文件加和file_paths.xml文件

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The Android Open Source Project
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
          http://www.apache.org/licenses/LICENSE-2.0
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
 
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Offer access to files under Context.getCacheDir() -->
    <cache-path name="my_cache" />
    <files-path name="my_files" path = "." />
    <external-path name="my_external" path = "." />
    <external-path path="xxxx" name="camera_photos" />
</paths>

java层还需要修改: 在gradle.properrties 里添加
android.useAndroidX=true
android.enableJetifier=true

 

接下来在加一个 compressImage() 图片压缩方法  本方法借鉴来自文章: https://blog.csdn.net/W_han__/article/details/126747094 

private Bitmap compressImage(Bitmap beforeBitmap) {
  // 可以捕获内存缓冲区的数据,转换成字节数组。
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  if (beforeBitmap != null) {
    // 第一个参数:图片压缩的格式;第二个参数:压缩的比率;第三个参数:压缩的数据存放到bos中
    beforeBitmap.compress(Bitmap.CompressFormat.JPEG, 30, bos);
    // 循环判断压缩后的图片大小是否满足要求,这里限制100kb,若不满足则继续压缩,每次递减10%压缩
    int options = 100;
    while (bos.toByteArray().length / 1024 > 100) {
      bos.reset();// 置为空
      beforeBitmap.compress(Bitmap.CompressFormat.JPEG, options, bos);
      options -= 10;
    }

    // 从bos中将数据读出来 转换成图片
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    Bitmap afterBitmap = BitmapFactory.decodeStream(bis);
    return afterBitmap;
  }
  return null;
}

 JS接收base64数据之后的通过SpriteFrame组件显示出来

onPickImageResult(base64:string){
    let image = new Image();
    image.onload = function(){
        let img = new ImageAsset(image)
        var texture = new Texture2D()
        texture.image = img
        let spriteFrame = new SpriteFrame()
        spriteFrame.texture = texture
        let s = sprite?.getComponent(Sprite)
        if(s != null)
        {
            s.spriteFrame =  spriteFrame
        }
    }
    image.src = "data:image/png;base64," + base64

}

 

posted on 2023-07-12 16:18  LinnYoung  阅读(2031)  评论(0)    收藏  举报