uniapp nativejs无法处理byte字节
当前开发的功能是:
使用uniapp实现从本地设备选取证书文件,然后为设备安装证书
uniapp功能缺陷:
- uniapp自带的上传组件,无法上传除了图片视频以外的其他文件格式
- nativejs无法处理byte字节
初期解决思路
-
nativejs发起选择文件Intent(Intent.ACTION_GET_CONTENT),在startActivityForResult获取Uri,通过Url获取文件字节流,然后唤起证书安装Intent:KeyChain.createInstallIntent(),代码如下
// 获取宿主上下文 var main = plus.android.runtimeMainActivity(); // 通过反射获取Android的Intent对象 var Intent = plus.android.importClass("android.content.Intent"); var Uri = plus.android.importClass("android.net.Uri"); var KeyChain=plus.android.importClass("android.security.KeyChain"); // 通过宿主上下文创建 intent var intent =new Intent(Intent.ACTION_GET_CONTENT); // 设置要开启的Activitv包类路径 intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); var choose=Intent.createChooser(intent, "选择文件上传"); // 请求码保证了,开始的新界面和返回的是同一个操作 var CODE_REQUEST= 123; // 采用startActivityForResult开启新的界面,当界面关闭时可以处理返回结果,CODE REQUEST请求码是唯一标识 main.startActivityForResult(intent,CODE_REQUEST); // 设置原生界面返回后的回调操作 main.onActivityResult = function(requestCode,resultCode, data){ console.log(requestCode,resultCode, data); if (requestCode == 123) { if (resultCode == -1) { console.log(data.getData()) var uriString = data.getData().toString(); console.log(uriString) const uri = Uri.parse(uriString); // let outpp=readBytesFromInputStream(main,uri); // console.log("filePath",outpp) // // 把流写到文件夹。 readFileBytes(main,uri).then(res=>{ console.log("filePath",res) var bytes =res; // installCertificate(bytes,""); var cert = KeyChain.createInstallIntent(); cert.putExtra(KeyChain.EXTRA_CERTIFICATE, bytes); cert.putExtra(KeyChain.EXTRA_NAME, ""); cert.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); main.startActivity(cert); }).catch(e=>{ console.log(e) }); // that.getFile(uriString) Toast.makeText(this, "Ok DUDE", Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, "Oversmart Eh!!", Toast.LENGTH_LONG).show(); } } }
function readBytesFromInputStream(main,uri) { var main2 = plus.android.runtimeMainActivity(); const Byte = plus.android.importClass('java.lang.Byte'); var ByteArrayOutputStream = plus.android.importClass('java.io.ByteArrayOutputStream'); var InputStream = plus.android.importClass('java.io.InputStream'); const inputStream = main2.getContentResolver().openInputStream(uri); if (inputStream == null) { throw new IOException("Failed to open input stream for URI: " + uri); } var byteArrayOutputStream = new ByteArrayOutputStream(); var bufferSize = 4096; // 缓冲区大小 var buffer = plus.android.invoke('java.lang.reflect.Array', 'newInstance', Byte.class, 4096); var len; var totalLen = 0; try { while ((len = inputStream.read(buffer)) !== -1) { var javaByteArray = convertToJavaByteArray(buffer, len); byteArrayOutputStream.write(javaByteArray, 0, len); totalLen += len; } return plus.android.invoke(byteArrayOutputStream,"toByteArray"); } catch (e) { console.error("Error reading input stream: " + e); } finally { if (byteArrayOutputStream) { byteArrayOutputStream.close(); } if (inputStream) { inputStream.close(); } } } function convertToJavaByteArray(jsArray, len) { var byteArray = Array(len); // 创建一个普通的 JavaScript 数组 for (var i = 0; i < len; i++) { byteArray[i] = jsArray[i]; } var result = plus.android.invoke('java.lang.reflect.Array', 'newInstance', 'byte', len); for (var i = 0; i < len; i++) { plus.android.invoke(result, 'set', i, byteArray[i]); } return result; }
-
使用uniapp的原生插件uniplugin,完美解决问题,详细插件开发教程在这里~Uniapp: 原生Android插件开发调试打包详细历程
import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.net.Uri; import android.security.KeyChain; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.Toast; import com.alibaba.fastjson.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import io.dcloud.feature.uniapp.annotation.UniJSMethod; import io.dcloud.feature.uniapp.bridge.UniJSCallback; import io.dcloud.feature.uniapp.common.UniModule; public class CertModule extends UniModule { @UniJSMethod(uiThread = true) public void send(final JSONObject json) { if (mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); Intent choose=Intent.createChooser(intent, "选择文件上传"); choose.putExtra("alias","tsststs"); ((Activity) mUniSDKInstance.getContext()).startActivityForResult(choose, 123); System.out.println("选择文件上传"); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Activity activity=((Activity) mUniSDKInstance.getContext()); if (requestCode == 123) { if (resultCode == RESULT_OK) { Uri uri = data.getData(); System.out.println(uri.toString()); // 把流写到文件夹。 try { byte[] bytes = FileUtils.readFileBytesFromUri(activity,uri); installCertificate(bytes,""); } catch (IOException e) { e.printStackTrace(); Toast.makeText(activity, "证书上传失败", Toast.LENGTH_LONG).show(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(activity, "添加证书已取消", Toast.LENGTH_LONG).show(); } } } private void installCertificate(byte[] certificateBytes, String alias) { Intent intent = KeyChain.createInstallIntent(); intent.putExtra(KeyChain.EXTRA_CERTIFICATE, certificateBytes); intent.putExtra(KeyChain.EXTRA_NAME, alias); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ((Activity) mUniSDKInstance.getContext()).startActivity(intent); } }