..._android13 dwebview打开相册">
当前位置:   article > 正文

【android】webview调用本地照相、图库_android13 dwebview打开相册

android13 dwebview打开相册

网上找了很多,看到这个兄弟写的能用,备份一份,照相的地方增加了存储权限,不然部分手机有问题,还有另一个问题,上传按扭点了授权后必须重新进入APP才能点击上传按扭,这个问题待解决后更新。

一、H5页面的标签

<input type="file" accept=".jpeg, .jpg, .png" name="upload_file" id="js-title-img-input">

二、AndroidManifest权限

  1. <uses-permission android:name="android.permission.INTERNET"/>
  2. <uses-permission android:name="android.permission.CAMERA"/>
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  4. <uses-feature android:name="android.hardware.camera" /> <!-- 使用照相机权限 -->
  5. <uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 自动聚焦权限 -->
  6. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

三、在Application的onCreate中

  1. class MyWebChromeClient extends WebChromeClient {
  2. 其他代码、、、
  3. // For Android < 3.0
  4. public void openFileChooser(ValueCallback<Uri> uploadMsg) {
  5. WebCameraHelper.getInstance().mUploadMessage = uploadMsg;
  6. WebCameraHelper.getInstance().showOptions(CubeAndroid.this);
  7. }
  8. // For Android > 4.1.1
  9. public void openFileChooser(ValueCallback<Uri> uploadMsg,
  10. String acceptType, String capture) {
  11. WebCameraHelper.getInstance().mUploadMessage = uploadMsg;
  12. WebCameraHelper.getInstance().showOptions(CubeAndroid.this);
  13. }
  14. // For Android > 5.0支持多张上传
  15. @Override
  16. public boolean onShowFileChooser(WebView webView,
  17. ValueCallback<Uri[]> uploadMsg,
  18. FileChooserParams fileChooserParams) {
  19. WebCameraHelper.getInstance().mUploadCallbackAboveL = uploadMsg;
  20. WebCameraHelper.getInstance().showOptions(CubeAndroid.this);
  21. return true;
  22. }
  23. }

五、最重要的核心类WebCameraHelper

  1. **
  2. * @desc web页面调用本地照相机、图库的相关助手
  3. * @auth 方毅超
  4. * @time 2017/12/8 16:25
  5. */
  6. public class WebCameraHelper {
  7. private static class SingletonHolder {
  8. static final WebCameraHelper INSTANCE = new WebCameraHelper();
  9. }
  10. public static WebCameraHelper getInstance() {
  11. return SingletonHolder.INSTANCE;
  12. }
  13. /**
  14. * 图片选择回调
  15. */
  16. public ValueCallback<Uri> mUploadMessage;
  17. public ValueCallback<Uri[]> mUploadCallbackAboveL;
  18. public Uri fileUri;
  19. public static final int TYPE_REQUEST_PERMISSION = 3;
  20. public static final int TYPE_CAMERA = 1;
  21. public static final int TYPE_GALLERY = 2;
  22. /**
  23. * 包含拍照和相册选择
  24. */
  25. public void showOptions(final Activity act) {
  26. AlertDialog.Builder alertDialog = new AlertDialog.Builder(act);
  27. alertDialog.setOnCancelListener(new ReOnCancelListener());
  28. alertDialog.setTitle("选择");
  29. alertDialog.setItems(new CharSequence[]{"相机", "相册"},
  30. new DialogInterface.OnClickListener() {
  31. @Override
  32. public void onClick(DialogInterface dialog, int which) {
  33. if (which == 0) {
  34. if (ContextCompat.checkSelfPermission(act,
  35. Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
  36. // 申请WRITE_EXTERNAL_STORAGE权限,这里转载的兄弟只写了相机权限,部分手机无法使用照相机上传,需要加存储权限
  37. ActivityCompat.requestPermissions(act, new String[]{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}, TYPE_REQUEST_PERMISSION);
  38. } else {
  39. toCamera(act);
  40. }
  41. } else {
  42. Intent i = new Intent(
  43. Intent.ACTION_PICK,
  44. MediaStore.Images.Media.EXTERNAL_CONTENT_URI);// 调用android的图库
  45. act.startActivityForResult(i,
  46. TYPE_GALLERY);
  47. }
  48. }
  49. });
  50. alertDialog.show();
  51. }
  52. /**
  53. * 点击取消的回调
  54. */
  55. private class ReOnCancelListener implements
  56. DialogInterface.OnCancelListener {
  57. @Override
  58. public void onCancel(DialogInterface dialogInterface) {
  59. if (mUploadMessage != null) {
  60. mUploadMessage.onReceiveValue(null);
  61. mUploadMessage = null;
  62. }
  63. if (mUploadCallbackAboveL != null) {
  64. mUploadCallbackAboveL.onReceiveValue(null);
  65. mUploadCallbackAboveL = null;
  66. }
  67. }
  68. }
  69. /**
  70. * 请求拍照
  71. * @param act
  72. */
  73. public void toCamera(Activity act) {
  74. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 调用android的相机
  75. // 创建一个文件保存图片
  76. fileUri = Uri.fromFile(FileManager.getImgFile(act.getApplicationContext()));
  77. intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
  78. act.startActivityForResult(intent, TYPE_CAMERA);
  79. }
  80. /**
  81. * startActivityForResult之后要做的处理
  82. * @param requestCode
  83. * @param resultCode
  84. * @param intent
  85. */
  86. public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  87. if (requestCode == TYPE_CAMERA) { // 相册选择
  88. if (resultCode == -1) {//RESULT_OK = -1,拍照成功
  89. if (mUploadCallbackAboveL != null) { //高版本SDK处理方法
  90. Uri[] uris = new Uri[]{fileUri};
  91. mUploadCallbackAboveL.onReceiveValue(uris);
  92. mUploadCallbackAboveL = null;
  93. } else if (mUploadMessage != null) { //低版本SDK 处理方法
  94. mUploadMessage.onReceiveValue(fileUri);
  95. mUploadMessage = null;
  96. } else {
  97. // Toast.makeText(CubeAndroid.this, "无法获取数据", Toast.LENGTH_LONG).show();
  98. }
  99. } else { //拍照不成功,或者什么也不做就返回了,以下的处理非常有必要,不然web页面不会有任何响应
  100. if (mUploadCallbackAboveL != null) {
  101. mUploadCallbackAboveL.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
  102. mUploadCallbackAboveL = null;
  103. } else if (mUploadMessage != null) {
  104. mUploadMessage.onReceiveValue(fileUri);
  105. mUploadMessage = null;
  106. } else {
  107. // Toast.makeText(CubeAndroid.this, "无法获取数据", Toast.LENGTH_LONG).show();
  108. }
  109. }
  110. } else if (requestCode == TYPE_GALLERY) {// 相册选择
  111. if (mUploadCallbackAboveL != null) {
  112. mUploadCallbackAboveL.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
  113. mUploadCallbackAboveL = null;
  114. } else if (mUploadMessage != null) {
  115. Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
  116. mUploadMessage.onReceiveValue(result);
  117. mUploadMessage = null;
  118. } else {
  119. // Toast.makeText(CubeAndroid.this, "无法获取数据", Toast.LENGTH_LONG).show();
  120. }
  121. }
  122. }
  123. }

六、还需要一个小小的文件管理类FileManager

  1. /**
  2. * @desc
  3. * @auth 方毅超
  4. * @time 2017/12/8 14:41
  5. */
  6. public class FileManager {
  7. public static final String ROOT_NAME = "RongYifu";
  8. public static final String LOG_NAME = "UserLog";
  9. public static final String CACHE_NAME = "Cache";
  10. public static final String IMAGE_NAME = "Image";
  11. public static final String RECORD_NAME = "Voice";
  12. public static final String ROOT_PATH = File.separator + ROOT_NAME
  13. + File.separator;
  14. public static final String LOG_PATH_NAME = File.separator + LOG_NAME
  15. + File.separator;
  16. public static final String CACHE_PATH_NAME = File.separator + CACHE_NAME
  17. + File.separator;
  18. public static final String IMAGE_PATH_NAME = File.separator + IMAGE_NAME
  19. + File.separator;
  20. public static final String RECORD_PATH_NAME = File.separator + RECORD_NAME
  21. + File.separator;
  22. public static final String ACTION_DEL_ALL_IMAGE_CACHE = "com.citic21.user_delImageCache";
  23. public static final String CODE_ENCODING = "utf-8";
  24. public static String getRootPath(Context appContext) {
  25. String rootPath = null;
  26. if (checkMounted()) {
  27. rootPath = getRootPathOnSdcard();
  28. } else {
  29. rootPath = getRootPathOnPhone(appContext);
  30. }
  31. return rootPath;
  32. }
  33. public static String getRootPathOnSdcard() {
  34. File sdcard = Environment.getExternalStorageDirectory();
  35. String rootPath = sdcard.getAbsolutePath() + ROOT_PATH;
  36. return rootPath;
  37. }
  38. public static String getRootPathOnPhone(Context appContext) {
  39. File phoneFiles = appContext.getFilesDir();
  40. String rootPath = phoneFiles.getAbsolutePath() + ROOT_PATH;
  41. return rootPath;
  42. }
  43. public static String getSdcardPath() {
  44. File sdDir = null;
  45. boolean sdCardExist = checkMounted(); // 判断sd卡是否存在
  46. if (sdCardExist) {
  47. sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
  48. return sdDir.getPath();
  49. }
  50. return "/";
  51. }
  52. // SD卡剩余空间
  53. public long getSDFreeSize() {
  54. // 取得SD卡文件路径
  55. File path = Environment.getExternalStorageDirectory();
  56. StatFs sf = new StatFs(path.getPath());
  57. // 获取单个数据块的大小(Byte)
  58. long blockSize = sf.getBlockSize();
  59. // 空闲的数据块的数量
  60. long freeBlocks = sf.getAvailableBlocks();
  61. // 返回SD卡空闲大小
  62. // return freeBlocks * blockSize; //单位Byte
  63. // return (freeBlocks * blockSize)/1024; //单位KB
  64. return (freeBlocks * blockSize) / 1024 / 1024; // 单位MB
  65. }
  66. public static boolean checkMounted() {
  67. return Environment.MEDIA_MOUNTED.equals(Environment
  68. .getExternalStorageState());
  69. }
  70. public static String getUserLogDirPath(Context appContext) {
  71. String logPath = getRootPath(appContext) + LOG_PATH_NAME;
  72. return logPath;
  73. }
  74. // 缓存整体路径
  75. public static String getCacheDirPath(Context appContext) {
  76. String imagePath = getRootPath(appContext) + CACHE_PATH_NAME;
  77. return imagePath;
  78. }
  79. // 图片缓存路径
  80. public static String getImageCacheDirPath(Context appContext) {
  81. String imagePath = getCacheDirPath(appContext) + IMAGE_PATH_NAME;
  82. return imagePath;
  83. }
  84. // 创建一个图片文件
  85. public static File getImgFile(Context context) {
  86. File file = new File(getImageCacheDirPath(context));
  87. if (!file.exists()) {
  88. file.mkdirs();
  89. }
  90. String imgName = new SimpleDateFormat("yyyyMMdd_HHmmss")
  91. .format(new Date());
  92. File imgFile = new File(file.getAbsolutePath() + File.separator
  93. + "IMG_" + imgName + ".jpg");
  94. return imgFile;
  95. }
  96. // 创建拍照处方单路径
  97. public static File initCreatImageCacheDir(Context appContext) {
  98. String rootPath = getImageCacheDirPath(appContext);
  99. File dir = new File(rootPath);
  100. if (!dir.exists()) {
  101. dir.mkdirs();
  102. }
  103. return dir;
  104. }
  105. public static final String getFileSize(File file) {
  106. String fileSize = "0.00K";
  107. if (file.exists()) {
  108. fileSize = FormetFileSize(file.length());
  109. return fileSize;
  110. }
  111. return fileSize;
  112. }
  113. public static String FormetFileSize(long fileS) {// 转换文件大小
  114. DecimalFormat df = new DecimalFormat("0.00");
  115. String fileSizeString = "";
  116. if (fileS < 1024) {
  117. fileSizeString = df.format((double) fileS) + "B";
  118. } else if (fileS < 1048576) {
  119. fileSizeString = df.format((double) fileS / 1024) + "K";
  120. } else if (fileS < 1073741824) {
  121. fileSizeString = df.format((double) fileS / 1048576) + "M";
  122. } else {
  123. fileSizeString = df.format((double) fileS / 1073741824) + "G";
  124. }
  125. return fileSizeString;
  126. }
  127. public static boolean writeStringToFile(String text, File file) {
  128. try {
  129. return writeStringToFile(text.getBytes(CODE_ENCODING), file);
  130. } catch (UnsupportedEncodingException e1) {
  131. e1.printStackTrace();
  132. return false;
  133. }
  134. }
  135. static void close(Closeable c) {
  136. if (c != null) {
  137. try {
  138. c.close();
  139. } catch (IOException e) {
  140. e.printStackTrace();
  141. }
  142. }
  143. }
  144. public static boolean writeStringToFile(byte[] datas, File file) {
  145. FileOutputStream fos = null;
  146. try {
  147. fos = new FileOutputStream(file);
  148. fos.write(datas);
  149. fos.flush();
  150. return true;
  151. } catch (FileNotFoundException e) {
  152. e.printStackTrace();
  153. } catch (UnsupportedEncodingException e) {
  154. e.printStackTrace();
  155. } catch (IOException e) {
  156. e.printStackTrace();
  157. } finally {
  158. close(fos);
  159. }
  160. return false;
  161. }
  162. /**
  163. * @param oldpath URL 的 md5+"_tmp"
  164. * @param newpath URL 的 md5+
  165. * @return
  166. */
  167. public static boolean renameFileName(String oldpath, String newpath) {
  168. try {
  169. File file = new File(oldpath);
  170. if (file.exists()) {
  171. file.renameTo(new File(newpath));
  172. }
  173. return true;
  174. } catch (Exception e) {
  175. // TODO Auto-generated catch block
  176. e.printStackTrace();
  177. }
  178. return false;
  179. }
  180. public static final boolean isFileExists(File file) {
  181. if (file.exists()) {
  182. return true;
  183. }
  184. return false;
  185. }
  186. public static final long getFileSizeByByte(File file) {
  187. long fileSize = 0l;
  188. if (file.exists()) {
  189. fileSize = file.length();
  190. return fileSize;
  191. }
  192. return fileSize;
  193. }
  194. public static boolean checkCachePath(Context appContext) {
  195. String path = getCacheDirPath(appContext);
  196. File file = new File(path);
  197. if (!file.exists()) {
  198. return false;
  199. }
  200. return true;
  201. }
  202. public static String getUrlFileName(String resurlt) {
  203. if (!TextUtils.isEmpty(resurlt)) {
  204. int nameIndex = resurlt.lastIndexOf("/");
  205. String loacalname = "";
  206. if (nameIndex != -1) {
  207. loacalname = resurlt.substring(nameIndex + 1);
  208. }
  209. int index = loacalname.indexOf("?");
  210. if (index != -1) {
  211. loacalname = loacalname.substring(0, index);
  212. }
  213. return loacalname;
  214. } else {
  215. return resurlt;
  216. }
  217. }
  218. // 存储map类型数据 转换为Base64进行存储
  219. public static String SceneList2String(Map<String, String> SceneList)
  220. throws IOException {
  221. ByteArrayOutputStream toByte = new ByteArrayOutputStream();
  222. ObjectOutputStream oos = null;
  223. try {
  224. oos = new ObjectOutputStream(toByte);
  225. } catch (IOException e) {
  226. // TODO Auto-generated catch block
  227. e.printStackTrace();
  228. }
  229. try {
  230. oos.writeObject(SceneList);
  231. } catch (IOException e) {
  232. // TODO Auto-generated catch block
  233. e.printStackTrace();
  234. }
  235. // 对byte[]进行Base64编码
  236. String SceneListString = new String(Base64.encode(toByte.toByteArray(),
  237. Base64.DEFAULT));
  238. return SceneListString;
  239. }
  240. }

至此,所有角色介绍完毕,以下看看大概怎么用吧!可以在Activity或Fragment中。只要设置一下WebChromeClient,然后在onActivityResult中做返回处理:

 

  1. webView.setWebChromeClient(new MyWebChromeClient());//设置WebChromeClient
  2. @Override
  3. protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
  4. super.onActivityResult(requestCode, resultCode, intent);
  5. WebCameraHelper.getInstance().onActivityResult(requestCode, resultCode, intent);
  6. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/105068?site
推荐阅读
相关标签
  

闽ICP备14008679号