CocosCreator 调用安卓相册选择图片裁剪并传Base64到ts层

java代码 。CommonUtils.java

package com.cocos.common;

import android.Manifest;
import android.content.ClipData;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import org.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.cocos.game.AppActivity;
import com.cocos.lib.CocosHelper;
import com.cocos.lib.CocosJavascriptJavaBridge;

public class CommonUtils {

    static CommonUtils s_common = null;

    public static CommonUtils getInstance() {
        if (s_common == null) {
            s_common = new CommonUtils();
        }
        return s_common;
    }

    public static final int REQUEST_CODE_CAMERA = 110;
    public static final int REQUEST_CODE_ALBUM = 111;
    public static final int REQUEST_CODE_CROP = 112;

    public static Integer clipX = 0;
    public static Integer clipY = 0;
    public static Integer needClip = 0;

    public static Integer photoType = 1;

    public static Uri uriClipUri = null;
    public static Uri mCameraUri = null;

    private static AppActivity instance = null;

    public static void selectPhoto(String path, String info) {
        s_common.useSystemAlbum(info);
    }

    public static void initComUtils(AppActivity context) {
        s_common.instance = context;
    }

    /**
     * 调用系统相册和裁剪
     * @param info
     */
    public static void useSystemAlbum(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();
        }
 
        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 (ActivityCompat.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);
    }

    // 处理图片路径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(instance, 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 = instance.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;
    }

     
    /**
     * 图片裁剪的方法
     * @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);//裁剪完成的标识
    }

     
    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;
    }

     
//    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
//        instance.onActivityResult(requestCode, resultCode, data);
        // FaceBookLogin.callbackManager.onActivityResult(requestCode, resultCode, data);
        // SDKWrapper.getInstance().onActivityResult(requestCode, resultCode, data);
        if(requestCode == REQUEST_CODE_ALBUM && resultCode == instance.RESULT_OK){
            Log.i("pickImg ","调用相册回调");
            if(data != null){
                if(needClip == 1){
                    startPhotoZoom(data.getData());
                    return;
                }
                String filePath = null;
                if (resultCode == instance.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 = compressImage(BitmapFactory.decodeFile(filePath));
        
                String base64Bitmap = bitmapToBase64(bitmap);

                this.send2JsCommonUtils(String.format("G.eventMgr.emit('CAMERA_PICK_MESSAGE_ARRIVE', '%s', '%s')", filePath, base64Bitmap));

//                final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
//                CocosHelper.runOnGameThread(new Runnable() {
//                    @Override
//                    public void run() {
//                        CocosJavascriptJavaBridge.evalString(callJsFunc);
//                        Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
//                    }
//                });
            }
        }
//        else if(requestCode == REQUEST_CODE_CAMERA && resultCode == instance.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 == instance.RESULT_OK){
            Log.i("pickImg","裁剪完成"+data.getData());
            if(data != null){
                if(photoType == 1){
                    String filePath = null;
                    if (resultCode == instance.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);
                    Bitmap bitmap = compressImage(BitmapFactory.decodeFile(filePath));
                    String base64Bitmap = bitmapToBase64(bitmap);

                    this.send2JsCommonUtils(String.format("G.eventMgr.emit('CAMERA_MESSAGE_ARRIVE', '%s', '%s')", filePath, base64Bitmap));

//                    final String callJsFunc = String.format("PlatForm.onPickImageResult(\'%s\',\'%s\');",filePath,base64Bitmap);
//                    CocosHelper.runOnGameThread(new Runnable() {
//                        @Override
//                        public void run() {
//                            CocosJavascriptJavaBridge.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);
//                        CocosHelper.runOnGameThread(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);
//                        CocosHelper.runOnGameThread(new Runnable() {
//                            @Override
//                            public void run() {
//                                Cocos2dxJavascriptJavaBridge.evalString(callJsFunc);
//                                Log.i("pickImg","返回path,base64,callFuncStr = "+callJsFunc);
//                            }
//                        });
//                    }
 
                }
            }
        }
 
    }
    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;
    }

    private void send2JsCommonUtils(String callJsFunc) {
        CocosHelper.runOnGameThread(new Runnable() {
            @Override
            public void run() {
                CocosJavascriptJavaBridge.evalString(callJsFunc);
                Log.i("pickImg","crop返回path,base64,callFuncStr = "+callJsFunc);
            }
        });
    }

    public static void onNewIntent(Intent intent) {
        Log.d("RtmSdk", "=========== onNewIntent ");
    }

}

java代码  AppActivity
 

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        CommonUtils.getInstance().onActivityResult(requestCode, resultCode, data);
//        SDKWrapper.shared().onActivityResult(requestCode, resultCode, data);
    }
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        CommonUtils.getInstance().initComUtils(this);
    }

js代码

const commonPath = 'com/cocos/common/CommonUtils';
//选择相册图片    
    public selectPhoto(clipSize: Size = new Size(150, 150), needClip = 1) {
        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尺寸
        }
 
        let tmpPath = jsb.fileUtils.getWritablePath() + 'tmpPhoto.jpg';
        if (sys.os == sys.OS.ANDROID) {
            jsb.reflection.callStaticMethod(
                commonPath,
                "selectPhoto",
                "(Ljava/lang/String;Ljava/lang/String;)V",
                tmpPath,
                JSON.stringify(dict));
        } else if (sys.os == sys.OS.IOS) {
            jsb.reflection.callStaticMethod("DeviceModule", "selectPhoto", tmpPath, JSON.stringify(dict));
        } else {
            let path = jsb.fileUtils.getWritablePath() + 'tmpPhoto.jpg';
            // cc.director.emit("SelectPhotoCallback", path);
        }
    }

js回调

    {
        G.eventMgr.on(EventConst.CAMERA_PICK_MESSAGE_ARRIVE, this.onPickImageArrive, this);
        G.eventMgr.on(EventConst.CAMERA_MESSAGE_ARRIVE, this.onImageArrive, this);
    }
    public onPickImageArrive(filePath: string, filedata) {
        console.error(`onPickImageArrive filePath: ${filePath}`);
        console.error(filedata)
    }
    public onImageArrive(filePath: string, filedata) {
        console.error(`onImageArrive filePath: ${filePath}`);
        console.error(filedata)
    }
    

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

在AndoridMainfest里添加

 <!-- 相册权限 -->
    <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" />


<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>

然后再res下面创建xml/file_path.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="." name="camera_photos" />
</paths>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Cocos2d-x中使用Lua进行文件上,你可以使用HttpClient类来实现。下面是一个简单的示例代码: ``` lua local xhr = cc.XMLHttpRequest:new() xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_STRING xhr:setRequestHeader("Content-Type", "multipart/form-data;") local url = "http://your.upload.url" local filePath = "path/to/your/file" local boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW" local content = "" content = content .. "--" .. boundary .. "\r\n" content = content .. "Content-Disposition: form-data; name=\"file\"; filename=\"" .. filePath .. "\"\r\n" content = content .. "Content-Type: image/png\r\n\r\n" local fileData = cc.FileUtils:getInstance():getDataFromFile(filePath) content = content .. fileData:getBytes() content = content .. "\r\n--" .. boundary .. "--\r\n" local body = string.len(content) xhr:open("POST", url) xhr:setRequestHeader("Content-Length", tostring(body)) xhr:registerScriptHandler(function(event) if event.name == "completed" then -- 文件上成功 print(xhr.response) end end) xhr:send(content) ``` 在上面的代码中,我们首先创建一个XMLHttpRequest对象,并设置响应类型为字符串。然后设置请求头,包括Content-Type和boundary。接下来,我们读取文件并将其添加到请求正文中。最后,我们设置请求正文的长度,并发送请求。 在请求完成时,我们可以在回调函数中处理响应。在这个例子中,我们只是简单地打印响应内容。你可以根据自己的需要来处理响应数据。 需要注意的是,这里使用的是multipart/form-data格式上文件。如果你需要上其他类型的文件,或者需要上多个文件,可以根据需要修改请求头和请求正文。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值