Android Cordova项目中Js如何调用系统相机和相册
最近做Cordova项目遇到一个问题,js无法调用系统相机相册,自己也是经过了一番折腾才解决了这个问题,现在把它记录下来,方便以后查看,如果有需要的,希望这篇文章能够帮助到你。
话不多说,直接上代码:
public class WebActivity extends CordovaActivity{
public int thisWeb;
private SystemWebView mWebView;
private ValueCallback<Uri> mUploadMessage;// 表单的数据信息
private ValueCallback<Uri[]> mUploadCallbackAboveL;
private Uri imageUri;
private final static int FILECHOOSER_RESULTCODE = 1;// 表单的结果回调</span>
@Override
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
mWebView = findViewById(R.id.webview);
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(this);//这里会解析res/xml/config.xml配置文件
CordovaWebView cordovaWebView = new CordovaWebViewImpl(new SystemWebViewEngine(mWebView));//创建一个cordovawebview
cordovaWebView.init(new CordovaInterfaceImpl(this), parser.getPluginEntries(), parser.getPreferences());//初始化
Intent intent=getIntent();
String url=intent.getStringExtra("url");
if(url.contains("..")){
url=url.replace("..","");
}
if(url.trim().toLowerCase().contains("http://") ||url.trim() .toLowerCase().contains("https://")){
mWebView.loadUrl(url);
}else{
MyApplication.webNumber++;
String path = getFilesDir().getAbsolutePath() + "/files/www/pages"+url;
mWebView.loadUrl("file:///" + path);
}
mWebView.setWebChromeClient(new SystemWebChromeClient((SystemWebViewEngine) mWebView.getCordovaWebView().getEngine()){
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage=uploadMsg;
checkAppPermission();
}
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg,String acceptType) {
mUploadMessage=uploadMsg;
checkAppPermission();
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg,String acceptType, String capture) {
mUploadMessage=uploadMsg;
checkAppPermission();
}
// For Android 5.0+
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
mUploadCallbackAboveL=filePathCallback;
checkAppPermission();
return true;
}
});
}
@Override
protected void onResume ()
{
super.onResume();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (mUploadCallbackAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
} else if (mUploadMessage != null) {
if (result != null) {
String path = getPath(getApplicationContext(), result);
Uri uri = Uri.fromFile(new File(path));
mUploadMessage
.onReceiveValue(uri);
} else {
mUploadMessage.onReceiveValue(imageUri);
}
mUploadMessage = null;
}
}
}
@SuppressLint("NewApi")
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} // TODO handle non-primary volumes
} else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null) cursor.close();
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
//这里检查了存储权限,如果有需要,可以先检查下相机权限。 此方法用户对权限禁止或允许 未做判断,需要进一步完善
private void checkAppPermission(){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
// boolean isCamera = checkSelfPermission( Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
boolean isReadExternalStorage = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if( !isReadExternalStorage){
requestPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1004);
}else{
take();
}
}else{
take();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1004:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
checkAppPermission();
}else {
Toast.makeText(this,"未获取相册权限,请到权限中心手动设置!",Toast.LENGTH_SHORT).show();
}
break;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void take() {
File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp"); // Create the storage directory if it does not exist
if (!imageStorageDir.exists()) {
imageStorageDir.mkdirs();
}
File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
if (Build.VERSION.SDK_INT >= 24) {//android7.0 + 要通过FileProvider获取文件路径
imageUri = FileProvider.getUriForFile(WebActivity.this, BuildConfig.APPLICATION_ID+".provider", file);
} else {
imageUri = Uri.fromFile(file);
}
final List<Intent> cameraIntents = new ArrayList();
//如果需要打开相机,需要加上以下代码
// final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// final PackageManager packageManager = getPackageManager();
// final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
// for (ResolveInfo res : listCam) {
// final String packageName = res.activityInfo.packageName;
// final Intent i = new Intent(captureIntent);
// i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
// i.setPackage(packageName);
// i.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
// cameraIntents.add(i);
//
// }
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
@SuppressWarnings("null")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
if (requestCode != FILECHOOSER_RESULTCODE
|| mUploadCallbackAboveL == null) {
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
results = new Uri[]{imageUri};
} else {
String dataString = data.getDataString();
ClipData clipData = data.getClipData();
if (clipData != null) {
results = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null)
results = new Uri[]{Uri.parse(dataString)};
}
} else {
mUploadCallbackAboveL.onReceiveValue(results);
mUploadCallbackAboveL = null;
return;
}
if (results != null) {
mUploadCallbackAboveL.onReceiveValue(results);
mUploadCallbackAboveL = null;
} else {
results = new Uri[]{imageUri};
mUploadCallbackAboveL.onReceiveValue(results);
mUploadCallbackAboveL = null;
}
return;
}
}
activity_web.xml代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layerType="hardware"
tools:context="com.szkingdom.jros.cordova.activity.WebActivity">
<org.apache.cordova.engine.SystemWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layerType="software"/>
</android.support.constraint.ConstraintLayout>
当然还有另外一个办法,就是通过插件方式,原生来调用系统相机和相册,但是相对麻烦一点,这儿不做过多介绍,有兴趣的同学可以去了解一下。
参考链接:https://blog.csdn.net/angel20082008/article/details/20689229