今天来整理一下android和h5交互实现拍照,相册选图片进行显示,适配了7.0。6.0的网络权限顺便也简单说下。

PackageManager pkgManager = getPackageManager();
// 读写 sd card 权限非常重要, android6.0默认禁止的, 建议初始化之前就弹窗让用户赋予该权限
boolean sdCardWritePermission =pkgManager.checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, getPackageName()) == PackageManager.PERMISSION_GRANTED;
// read phone state用于获取 imei 设备信息
boolean phoneSatePermission =pkgManager.checkPermission(Manifest.permission.READ_PHONE_STATE, getPackageName()) == PackageManager.PERMISSION_GRANTED;
boolean cameraPermission =pkgManager.checkPermission(Manifest.permission.CAMERA, getPackageName()) == PackageManager.PERMISSION_GRANTED;
if (Build.VERSION.SDK_INT >= 23 && !sdCardWritePermission || !phoneSatePermission || !cameraPermission) {
//没有权限,去申请requestPermission();
} else {//有权限了
}

通过上面的代码,我们可以看到,我写的简单的申请权限,写的不太好,你们可以去找些比较好的来使用,我们这里主要讲的还是与H5交互拍照,申请权限的话就是下面的代码:

private void requestPermission() {ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.READ_PHONE_STATE,Manifest.permission.CAMERA},REQUEST_PERMISSION);
}

权限申请好了就是申请权限的回调了:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {if (requestCode == REQUEST_PERMISSION) {if ((grantResults.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED&& grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
//这是我推送的代码PushManager.getInstance().initialize(this.getApplicationContext(), userPushService);} else {Logs.e("tag2", "We highly recommend that you need to grant the special permissions before initializing the SDK, otherwise some "+ "functions will not work");PushManager.getInstance().initialize(this.getApplicationContext(), userPushService);}} else {super.onRequestPermissionsResult(requestCode, permissions, grantResults);}
}

好了,简单的权限就申请好了,下面就是主要的交互了,(一定要在有读写权限拍照权限的基础上来写):

首先我们和H5商量一个方法来调用:

因为我的项目和H5交互比较多,所以我就将所有的交互写在了一个类中调用。

private Activity act = null;
//调用 照相机
@JavascriptInterface
public void imagePickerWithID(String json) {((MainActivity) act).imagePickerWithID(json);
}

然后在我们需要调用的类中调用一下

private String  photoCallback =null;
//调用照相机传照片
public void  imagePickerWithID(final String json) {mHandlerHelper.sendMessage(json, new MPCallBack() {@Overridepublic void callBack(int what, Object obj) {showActionSheet();photoCallback = json;}});
}

然后我们将拍照后或者去相册选了图片后通过callBack来回调给H5去显示一下:

这里需要注意的是,不要按照我的样式写,因为,我封装了代码,你们写的话,就正常和H5进行交互,回传给H5数据就行。核心代码在下面

上面的方法中的showActionSheet就是去调用客户端的相机或者相册了,接下来就是实际代码:

//拍照START
public static final int PHOTOZOOM = 0; // 相册/拍照
public static final int PHOTOTAKE = 1; // 相册/拍照
private String photoSavePath =Environment.getExternalStorageDirectory().getAbsolutePath()+ "/ClipHeadPhoto/cache/";// 保存路径
private String photoSaveName;// 图pian名
private String path;// 图片全路径
private File file;
//拍照END
//点击更多弹出  ActionSheet
private void showActionSheet() {this.setTheme(R.style.ActionSheetStyleIOS7);  //右边baritem 点击事件ActionSheet menuView = new ActionSheet(this);menuView.setCancelButtonTitle("取消");  // before add itemsList<String> list = new ArrayList<>();list.add("从相册中选择");list.add("现在拍照");menuView.addItems(list);menuView.setItemClickListener(new ActionSheet.MenuItemClickListener() {@Overridepublic void onItemClick(int itemPosition) {if (itemPosition == 0) {/*** 相册*/Intent openAlbumIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);//Intent.ACTION_PICKopenAlbumIntent.setType("image/*");startActivityForResult(openAlbumIntent, PHOTOZOOM);} else {/*** 相机适配7.0*/photoSaveName = String.valueOf(System.currentTimeMillis())+ ".png";Uri imageUri = null;Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// 这里用时间命名是发现用固定名命名后第二次裁剪图片任然是第一次的图,没有覆盖上一次图片资源;7.0之前固定名会替换file = new File(photoSavePath, photoSaveName);if (!file.getParentFile().exists()) file.getParentFile().mkdirs();// 通过FileProvider创建一个content类型的UriimageUri = FileProvider.getUriForFile(MainActivity.this, "com.aegiscard.airport.fileprovider", file);openCameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 将拍取的照片保存到指定URIopenCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_GALLERYstartActivityForResult(openCameraIntent,PHOTOTAKE);}//7.0以下的拍照方式else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {file = new File(photoSavePath, photoSaveName);if (!file.getParentFile().exists()) file.getParentFile().mkdirs();// 加载拍好的照片imageUri = Uri.fromFile(file);openCameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION,0);openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(openCameraIntent, PHOTOTAKE);}}}});menuView.setCancelableOnTouchMenuOutside(true);menuView.showMenu();
}

这个注释还是写的比较清楚的,我就不啰嗦了,

photoSavePath图片的路径的话,这个可以自己去设置的,不一定非得来用我的路径。

还有需要注意的就是7.0的创建文件夹的权限问题,上面已经写了怎么使用了,下面就看一些配置文件:

首先,我们需要在res下创建一个文件夹xml然后创建一个文件file_paths.xml

这个文件里面写

<?xml version="1.0" encoding="utf-8"?>
<resources><paths><external-pathname="camera_photos"path="" /></paths>
</resources>

这些就行,下面就说下他们是什么意思:

标签说明

<paths>为顶层标签,它下面可添加任意个(0,1或多个)上面出现的标签

<paths>子标签解释

可以看到上面每个标签都含有一个name和path属性

name:这个可以随意写(用于隐藏真实的目录,后面再演示)

path:要共享的目录,只能是目录,不能是某个具体的文件

<files-path> 代表Context.getFilesDir()所指向的目录

<cache-path>代表Context.getCacheDir()所指向的目录

<external-path>代表Environment.getExternalStorageDirectory()所指向的目录

<external-files-path>代表Context.getExternalFilesDir()所指向的目录

<external-cache-path>代表Context.getExternalCacheDir()所指向的目录

<external-media-path>代表Context.getExternalMediaDirs()所指向的目录(API21+设备才能使用,所以一般不用)

这个创建好了需要在mainfest里面写:

<!-- &lt;!&ndash;7.0相机权限&ndash;&gt; -->
<providerandroid:name="android.support.v4.content.FileProvider"
//com.aegiscard.airport.fileprovider这个名字随便写,需要注意的是需要和我们上面的使用保持一致!android:authorities="com.aegiscard.airport.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" />
</provider>

这样的话,我们的7.0适配就ok了。

我们就可以正常的创建文件夹,保存图片了,然后我们还需要回调:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, final Intent data) {// TODO Auto-generated method stubUri uri = null;switch (requestCode) {case PHOTOZOOM:// 相册{if (data == null) {return;}uri = data.getData();String[] proj = {MediaStore.Images.Media.DATA};Cursor cursor = managedQuery(uri, proj, null, null, null);if (cursor != null) {int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);cursor.moveToFirst();path = cursor.getString(column_index);// 图片在的路径} else {String uRl = uri.toString();path = uRl.substring(7);}Handler handler = new Handler();handler.post(new Runnable() {@Overridepublic void run() {try {Bimp bimp = new Bimp();bimp.clean();bimp.addSelectBitmap(path, 300, 300);String imag = "{\"imgUrl\": \"" + ImageUtil.bitmapToBase64(bimp.bmp.get(0)) + "\"}";String a = "javascript:newTools.native.set(\'" + photoCallback + "\',\'" + imag + "\');";Logs.v("javascript:newTools=", a);mHandlerHelper.loadUrl(a);//                            bimp.cleanbitmp();} catch (Exception e) {e.printStackTrace();}}});}break;case PHOTOTAKE:// 拍照{path = photoSavePath + photoSaveName;Logs.v("javascript:newTools=111", path);uri = Uri.fromFile(new File(path));Handler handler =    new Handler();handler.post(new Runnable() {@Overridepublic void run() {try {Bimp bimp = new Bimp();bimp.clean();bimp.addSelectBitmap(path, 300, 300);String imag = "{\"imgUrl\": \"" + ImageUtil.bitmapToBase64(bimp.bmp.get(0)) + "\"}";String a = "javascript:newTools.native.set(\'" + photoCallback + "\',\'" + imag + "\');";Logs.v("javascript:newTools=111", a);Logs.v("javascript:newTools=111", imag);mHandlerHelper.loadUrl(a);//bimp.cleanbitmp();} catch (Exception e) {e.printStackTrace();}}});}break;}super.onActivityResult(requestCode, resultCode, data);}

这个里面主要的就是loadUrl,mHandlerHelper是我的webview帮助类,你们不用管,就webview.loadurl就行。

中间涉及到了转换:

// bitmap转车base64
public static String bitmapToBase64(Bitmap bitmap) {String result = null;ByteArrayOutputStream baos = null;try {if (bitmap != null) {baos = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG,80, baos);baos.flush();baos.close();byte[] bitmapBytes = baos.toByteArray();result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);}} catch (IOException e) {e.printStackTrace();} finally {try {if (baos != null) {baos.flush();baos.close();}} catch (IOException e) {e.printStackTrace();}}return result;
}

下面是Bimp的类,这个是用来处理图片的,你们也可以自己写,用自己的就行,不一定要用我的。主要就是上面的转换。

public class Bimp {public static int max = 0;public static boolean act_bool = true;public List<Bitmap> bmp = new ArrayList<Bitmap>();// 图片sd地址 上传服务器时把图片调用下面方法压缩后 保存到临时文件夹 图片压缩后小于100KB,失真度不明显public  List<String> drr = new ArrayList<String>();public  void clean() {max = 0;act_bool = true;bmp.clear();drr.clear();}/*** 将图片压缩后存入** @param bitmap*/public  void addSelectBitmap(Bitmap bitmap) {//图片允许最大空间   单位:KBdouble maxSize =40.00;//将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)ByteArrayOutputStream baos = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baos);byte[] b = baos.toByteArray();//将字节换成KBdouble mid = b.length/1024;//判断bitmap占用空间是否大于允许最大空间  如果大于则压缩 小于则不压缩if (mid > maxSize) {//获取bitmap大小 是允许最大大小的多少倍double i = mid / maxSize;//开始压缩  此处用到平方根 将宽带和高度压缩掉对应的平方根倍 (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小)bitmap = zoomImage(bitmap, bitmap.getWidth() / Math.sqrt(i),bitmap.getHeight() / Math.sqrt(i));}bmp.add(bitmap);}public void addSelectBitmap(String path,int w,int h) {BitmapFactory.Options opts = new BitmapFactory.Options();//    FileInputStream is = new FileInputStream(path);opts.inJustDecodeBounds=true;BitmapFactory.decodeFile(path,opts);opts.inPreferredConfig= Bitmap.Config.RGB_565;int width = opts.outWidth;int height = opts.outHeight;float scaleWidth = 0.f, scaleHeight = 0.f;if (width > w || height > h) {scaleWidth = ((float) width) / w;scaleHeight = ((float) height) / h;}opts.inJustDecodeBounds = false;float scale = Math.max(scaleWidth, scaleHeight);opts.inSampleSize = (int) scale;Bitmap mbitmap = BitmapFactory.decodeFile(path, opts);//    mbitmap = BitmapFactory.decodeFile(path,opts);addSelectBitmap(mbitmap);}public int calculateInSampleSize(BitmapFactory.Options op, int reqWidth,int reqheight) {int originalWidth = op.outWidth;int originalHeight = op.outHeight;int inSampleSize = 1;if (originalWidth > reqWidth || originalHeight > reqheight) {int halfWidth = originalWidth / 2;int halfHeight = originalHeight / 2;while ((halfWidth / inSampleSize > reqWidth)&&(halfHeight / inSampleSize > reqheight)) {inSampleSize *= 2;}}return inSampleSize;}public  void cleanbitmp(){/*mbitmap.recycle();mbitmap=null;*/bmp=null;System.gc();}public Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {// 获取这个图片的宽和高float width = bgimage.getWidth();float height = bgimage.getHeight();// 创建操作图片用的matrix对象Matrix matrix = new Matrix();// 计算宽高缩放率float scaleWidth = ((float) newWidth) / width;float scaleHeight = ((float) newHeight) / height;// 缩放图片动作matrix.postScale(scaleWidth, scaleHeight);Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true);return bitmap;}// public static Bitmap revitionImageSize(String path) throws IOException {
//    BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(path)));
//    BitmapFactory.Options options = new BitmapFactory.Options();
//    options.inJustDecodeBounds = true;
//    BitmapFactory.decodeStream(in, null, options);
//    in.close();
//    int i = 0;
//    Bitmap bitmap = null;
//    while (true) {
//       if ((options.outWidth >> i <= 1000) && (options.outHeight >> i <= 1000)) {
//          in = new BufferedInputStream(new FileInputStream(new File(path)));
//          options.inSampleSize = (int) Math.pow(2.0D, i);
//          options.inJustDecodeBounds = false;
//          bitmap = BitmapFactory.decodeStream(in, null, options);
//          break;
//       }
//       i += 1;
//    }
//    return bitmap;
// }public static void saveBitmap(Bitmap bm, String path) {File f = new File(path);if (f.exists()) {f.delete();}try {FileOutputStream out = new FileOutputStream(f);bm.compress(Bitmap.CompressFormat.JPEG, 90, out);out.flush();out.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

好了,上面就是所有的交互了,客户端就不需要做其它操作了,我们把图片传给前端,前端展示就行了。谢谢观看!

Android H5交互实现拍照显示相关推荐

  1. html 如何实现一条竖线边上有 刻度_Android H5交互Webview实现localStorage数据存储

    先看看效果图吧-- 实现比较简单,但是第一次用可能会遇到一些坑 首先得有Webview控件: 有人问我是不是需要写布局文件,不写行不行,现在我就告诉你们,不写没问题,需要写就写不写直接创建New一个也 ...

  2. 客户端相关知识学习(三)之Android原生与H5交互的实现

    Android原生与H5交互的实现 H5调用原生的方式 方式可能有多种,根据开发经验,接触过两种方式. 方法一:Android向H5注入全局js对象,也就是H5调Android 1.首先对WebVie ...

  3. Android 系统(229)---Android与h5交互专题

    [Android开发进阶系列]Android与h5交互专题 1 交互原理 1.1 webview如何加载H5页面 我们都知道在Android中是通过webView来加载html页面的,根据HTML文件 ...

  4. Android 和 H5 交互-框架篇

    Android 和 H5 交互-框架篇 2017-08-01 YouJZ code小生 作者 | YouJZ 地址 | http://www.jianshu.com/p/02afb387b6b4 声明 ...

  5. Android原生app与H5交互

    1.开发背景. 随着当前开发迭代要求速度更快,改动更灵活,不需要发布版本就能实时更新app的内容,故当前H5制作界面越来越受到科技公司和开发者的欢迎. 2.实现交互 今天记录一下开发过程中用到的H5交 ...

  6. 关于原生android与H5交互的方法

    文章目录 原生android与H5交互 android调用H5方法 H5调用android 原生android与H5交互 前面讲解方法,结尾放代码 android调用H5方法 首先需要一个WebVie ...

  7. Android与H5交互探索之旅

    周一清早,某技术(对接我司业务SDK的技术)在有我司boss的微信群火急火燎地艾特我说为什么H5的回调 SDK 这边收不到?看到消息的我内心瞬间那是焦虑的一P,飞奔公司打开电脑双击IDE,心想别人用的 ...

  8. Android 与 H5 交互基础普及

    文章目录 前言 创建一个WebView页面 WebView 与 H5交互 H5 调用 WebView 中的方法 WebView 调用 H5 中的方法 另外一些重要操作 处理页面导航 处理页面历史 总结 ...

  9. Java乔晓松-android中调用系统拍照功能并显示拍照的图片

    android中调用系统拍照功能并显示拍照的图片 如果你是拍照完,利用onActivityResult获取data数据,把data数据转换成Bitmap数据,这样获取到的图片,是拍照的照片的缩略图 代 ...

  10. Android和H5交互-基础篇

    hybrid App开发也不是什么新鲜事了,其中native和h5之间的交互则是必不可少的.Android中是如何和H5交互的? 1.webView加载页面 我们都知道在Android中是通过webV ...

最新文章

  1. Jquery Mobile --小知识
  2. edHat linux光盘引导,Red Hat Linux 9光盘启动安装过程
  3. binary search tree python_二叉查找树(binary search tree)——python实现
  4. 内存颗粒位宽和容量_SDRAM的逻辑Bank与芯片容量表示方法
  5. 如何给微软提反馈建议以及bug
  6. 聚类算法 距离矩阵_谱聚类
  7. (19)VHDL实现流水灯
  8. SVN:retrieval of mergeinfo unsupported by
  9. 深圳能耗管理系统_综合能源管理平台
  10. VS连接SQL Server 2008,并实现登录和注册功能
  11. HGAME2020 签到题ProPlus
  12. 【ESP32-IDF】02-2 外设-触摸传感器
  13. flutter ScrollController attached to multiple scroll views
  14. 微信公众号页面开发记录
  15. 黑白图片复原为彩色Picture Colorizer(图片着色器)
  16. 暴雪将终止与网易合作:《魔兽世界》面临在大陆暂停服务
  17. AngularJS 概述
  18. 视频太大怎么传给对方微信?视频传微信太大怎么办?
  19. windows10桌面崩溃问题
  20. 酷比魔方i7手写版linux网卡驱动,酷比魔方i7手写板,Ubuntu 18.04,RTL8723BU wifi驱动安装...

热门文章

  1. 中国农村统计年鉴下载链接
  2. m126a linux驱动下载,hpm126a驱动下载
  3. 自己做量化交易软件(28)小白量化实战2--变红买入变绿卖出
  4. 打开计算机后无法缩小怎么办,电脑打开窗口小怎么办
  5. ILdasm 的使用
  6. Ilasm And Ildasm Practice
  7. 神经网络的BP算法推导详解
  8. AGND和GND_SIGNAL之间的隔离_PCB
  9. python 趋势跟踪算法_Dual Thrust 区间突破策略 Python 版
  10. 三星升级助手无法连接服务器,三星S 换机助手不能连接手机怎么办?