有時候我們需要在H5中調用Android的相機與相冊,前段時間項目中用到了,鼓搗了一波。
老樣子,拷貝代碼就好使!
首先整個工具類,先訪問一下相機權限:
public class Authority { private static final int MY_PERMISSION_REQUEST_CODE = 10000; //申請的權限,字符串模式 public static final String CALL_PHONE = Manifest.permission.CALL_PHONE;//打電話權限 public static final String CAMERA = Manifest.permission.CAMERA;//相機攝像頭權限 public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;//讀取內存卡權限 public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;//寫入內存卡權限 //申請的權限,數組模式 public static final String[] CALL_PHONE_ARR = {Manifest.permission.CALL_PHONE};//打電話權限 public static final String[] CAMERA_ARR = {Manifest.permission.CAMERA};//相機攝像頭權限 public static final String[] READ_EXTERNAL_STORAGE_ARR = {Manifest.permission.READ_EXTERNAL_STORAGE};//讀取內存卡權限 public static final String[] WRITE_EXTERNAL_STORAGE_ARR = {Manifest.permission.WRITE_EXTERNAL_STORAGE};//寫入內存卡權限 //權限數組 public static final String[] str = { Manifest.permission.CALL_PHONE,//打電話 Manifest.permission.CAMERA, //相機 // Manifest.permission.ACCESS_NETWORK_STATE,//網絡 // Manifest.permission.ACCESS_WIFI_STATE,//wifi // Manifest.permission.CHANGE_WIFI_STATE,//wifi // Manifest.permission.INTERNET,//網絡 Manifest.permission.READ_EXTERNAL_STORAGE,//獲取sd Manifest.permission.WRITE_EXTERNAL_STORAGE//寫入sd }; //申請權限,多項申請(Activity) public static void CallMobile(Activity mContext) { ActivityCompat.requestPermissions( mContext, str, MY_PERMISSION_REQUEST_CODE//回調的標識 ); } //申請權限,單項權限,(Activity) public static void CallMobileArr(Activity mContext, String[] str) { ActivityCompat.requestPermissions( mContext, str, MY_PERMISSION_REQUEST_CODE//回調的標識 ); } //申請權限(fragment) // requestPermissions(Authority.CAMERA_ARR, 10000);這種模式,不可以顯示申請權限彈框.如果禁止所申請的權限,可以顯示自定義彈框 //下面這種模式:可以顯示申請權限彈框.如果禁止所申請的權限,並且“下次不會再次提醒”已勾選,不會顯示彈框 @TargetApi(Build.VERSION_CODES.M) public static void CallMobileFragment(Activity mContext, String[] str) { mContext.requestPermissions(str, MY_PERMISSION_REQUEST_CODE); } //判斷權限是否申請通過 public static boolean lacksPermission(Context mContexts, String permission) { return ContextCompat.checkSelfPermission(mContexts, permission) == PackageManager.PERMISSION_DENIED; } /** * @param s 提示語 * @param applicationContext 上下文 * @param type 類型,是否關閉頁面 1關閉,0不關閉 */ public static void openAppDetails(String s, final Activity applicationContext, final int type) { final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(applicationContext); builder.setMessage(s); builder.setCancelable(false); builder.setPositiveButton("去手動授權", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse("package:" + applicationContext.getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); applicationContext.startActivity(intent); if (type == 1) { applicationContext.finish(); } } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); if (type == 1) { applicationContext.finish(); } } }); builder.show(); } //設置popu背景色 public static void setBackgroundAlpha(float bgAlpha, Activity mContext) { WindowManager.LayoutParams lp = mContext.getWindow() .getAttributes(); lp.alpha = bgAlpha; mContext.getWindow().setAttributes(lp); } }
然後是Activity部分,申請相機權限:
Authority.CallMobileArr(LiangFangActivity.this, new String[]{Manifest.permission.CAMERA});
相機權限的回調
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 10000) { int isClose = 0; for (int i = 0; i < permissions.length; i++) { if (permissions[i].equals(Manifest.permission.CAMERA) || permissions[i].equals(Manifest.permission.READ_EXTERNAL_STORAGE) || permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (grantResults[i] == -1) { isClose = 1; final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(LiangFangActivity.this); builder.setMessage("攝像頭權限和存儲權限爲必要的權限。\n由於您拒絕了,這導致您無法正常使用該應用。"); builder.setCancelable(false); builder.setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); LiangFangActivity.this.finish(); } }); builder.show(); } } } } }
下面正文部分
寫了個方法,在onCreat方法裏調用即可
private void setCheckImg() { mLiangFangWebView.setWebChromeClient(new WebChromeClient() { // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> valueCallback) { uploadMessage = valueCallback; openImageChooserActivity(); } // For Android >= 3.0 public void openFileChooser(ValueCallback valueCallback, String acceptType) { uploadMessage = valueCallback; openImageChooserActivity(); } //For Android >= 4.1 public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) { uploadMessage = valueCallback; openImageChooserActivity(); } // For Android >= 5.0 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { uploadMessageAboveL = filePathCallback; openImageChooserActivity(); return true; } }); }
然後選擇彈出了一個選擇框,相機還是相冊
private void openImageChooserActivity() { AlertDialog dialog = new AlertDialog.Builder(this) .setMessage("請選擇") .setPositiveButton("相機", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); time = Calendar.getInstance().getTimeInMillis(); // file = new File(Environment.getExternalStorageDirectory().getPath()+"/", time + ".jpg"); pathTakePhoto = Environment.getExternalStorageDirectory().getPath() + "/mbossclient/camera/temp/" + (System.currentTimeMillis() + ".jpg"); File vFile = new File(pathTakePhoto); if (!vFile.exists()) { File vDirPath = vFile.getParentFile(); vDirPath.mkdirs(); Log.e("alshdkash", "onClick: " + vFile.getPath()); } else { if (vFile.exists()) { vFile.delete(); } } photoURI = FileProvider.getUriForFile(LiangFangActivity.this, App.context.getApplicationContext().getPackageName() + ".provider", vFile); // uriTakePhoto = Uri.fromFile(vFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(intent, FILE_CHOOSER_RESULT_CODE1); } }).setNegativeButton("相冊", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE); } }).create(); dialog.show(); dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { cancelFilePathCallback(); } }); }
如果不選擇的話,調用此方法。需要一個返回值,沒有返回值會導致無法再次調起相機相冊,需要重新進入
private void cancelFilePathCallback() { if (uploadMessage != null) { uploadMessage.onReceiveValue(null); uploadMessage = null; } else if (uploadMessageAboveL != null) { uploadMessageAboveL.onReceiveValue(null); uploadMessageAboveL = null; } }
然後是相機,相冊的回調
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_CHOOSER_RESULT_CODE) { if (null == uploadMessage && null == uploadMessageAboveL) { return; } Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); if (uploadMessageAboveL != null) { onActivityResultAboveL(requestCode, resultCode, data); } else if (uploadMessage != null) { uploadMessage.onReceiveValue(result); uploadMessage = null; } } else if (requestCode == FILE_CHOOSER_RESULT_CODE1) { if (uploadMessageAboveL != null) { Uri[] results2 = {photoURI}; uploadMessageAboveL.onReceiveValue(results2); uploadMessageAboveL = null; // onActivityResultAboveL(requestCode, resultCode, data); } else if (uploadMessage != null) { uploadMessage.onReceiveValue(photoURI); uploadMessage = null; } } }
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) { if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null) return; Uri[] results = null; if (resultCode == Activity.RESULT_OK) { if (intent != null) { String dataString = intent.getDataString(); ClipData clipData = intent.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)}; } } uploadMessageAboveL.onReceiveValue(results); uploadMessageAboveL = null; }