Native和H5两种情况的头像上传
来源:互联网 发布:剑三成男脸型数据网盘 编辑:程序博客网 时间:2024/04/30 13:15
最近的工作中接触了一个小的功能,上传头像。上传头像是很多应用中的东西,描述下自己的应用。上传头像应用的地方:1.最开始进入app的时候会提示注册,然后就会调用。2.成功的注册完毕以后,可以在个人信息里面修改头像。3.在H5(某个WebView)中也可以修改这个头像。4.分为上传成功,上传失败和取消上传的功能。
先想想自己的这个功能,实现1和2只需要将上传的逻辑写在一个公共的类就行(例如:LoadUtil.java),要实现3的功能,首先想到也是在一个WebViewActivity中实现上传,不是直接跟在某个NativeActivity中上传的逻辑一样?仔细想想,发现其实不是这样的,一个WebViewActivity对应的会是很多的H5的界面(例如:http://wwww.baidu.com 和 http://www.google.com 可能都是在同一个WebViewAcitivity)。这样就会导致我需要在公用的WebViewActivity中加上图片剪切加上图片上传借口的调用。同样的,我实现1和2的时候也是需要在两个不同的Activity中去实现图片的裁剪和调用上传接口。又或者说来个更直接的,如果我图片的裁剪是系统自带的,那么我们还需要在onActivityResult中来取得最后裁剪的数据。根据自己的需求,想了一个代码量比较少的做法。可以自己写一个BaseActivity,将图片的截取、图片的获得、调用图片上传的接口都写在里面。然后再写一个工具类来实现图片的上传接口,最后在根据每种不同的情况来处理上传成功,失败以及取消的操作。
这篇文章主要涉及到知识:
- 图片的截取和Bitmap的生成
- 上传文件的协议以及实现
- Native和H5复用
图片的截取和Bitmap的生成
对于系统的图片的截取
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);intent.setType("image/*"); //打开的是系统的相册intent.putExtra("crop", "true"); //使用系统自带的裁剪intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); //两行表示裁剪宽高比为1:1intent.putExtra("outputX", WIDTH);intent.putExtra("outputY", HEIGTH); //裁剪以后输出的宽高值intent.putExtra("return-data", true); // 返回得到的数据startActivityForResult(intent, REQUSET_CODE);
然后就可以在onActivityResult(int requestCode,int responseCode,Intent data)中调用了。现在需要的是得到Bitmap的值。
if (data != null){ Bitmap bitmap = null; if (data.hasExtra("data")) // 首先会判断data中是否存在"data"值 { bitmap = data.getParcelableExtra("data"); // 存在就可以直接取了 } else // 不存在的时候则是可以通过BitmapFactory来获取bitmap的值 { BitmapFactory.Options options = new BitmapFactory.Options(); InputStream is = null; try { is = getContentResolver().openInputStream(data.getData()); bitmap = BitmapFactory.decodeStream(is, null, options); } catch (Exception e) { } finally { try { is.close(); } catch (Exception e) { } }}
上传文件的协议以及实现
分为两个部分,请求头和请求的正文。
Headers(请求标头):
会有一个Content-Type字段
Content-Type:multipart/form-data;boundary=一串每次请求不一样的字符串
TextView(请求正文):
请求正文里面的信息就复杂一点了。
第一行:
两个减号+与请求头一样的字符串+回车符号 (markdown中不支持写减号)
第二行:
Content-Disposition: form-data; name=\”file\”+; filename=\” + filename + \” + 回车符号(这里面的file的值根据你的后台的接口而写,filename则是你的上传的图像所在的位置)
第三行:
Content-Type: image/jpeg+两个回车符号(注意是两个回车符号)
第四行:
将图片转化为流写入。
第五行:
回车符号+与请求头一样的字符串+两个减号+回车符号
这样所有的信息写好以后,就完成了图片上传的协议。接下来就是读取后台返回来的信息解析出来就行。
使用HttpURLConnection实现。
URL url = new URL(uploadUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); // 允许input,output conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); // 设置请求头的信息 conn.setRequestProperty("Connection", "Keep-Alive"); // conn.setRequestProperty("Charset", "UTF-8"); // conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Accept-Charset", "utf-8"); conn.setRequestProperty("contentType", "utf-8"); conn.setRequestProperty("Content-Transfer-Encoding", "binary"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); // 上传的信息,ds就是上传文件的流 DataOutputStream ds = new DataOutputStream(conn.getOutputStream()); // twoHyphens="--",boundary是前面请求头中的相同的信息,end="\r\n" // 第一行 ds.writeBytes(twoHyphens + boundary + end); // 第二行 ds.writeBytes("Content-Disposition: form-data; name=\"upload\"; filename=\"" + filename + "\"" + end); // 第三行 ds.writeBytes("Content-Type: image/jpeg" + end + end); // 第四行,将Bitmap写入输出流,相当于将Bitmap上传 bitmap.compress(CompressFormat.JPEG, 100, ds); // 第五行 ds.writeBytes(end+twoHyphens + boundary + twoHyphens + end); ds.flush(); // 得到输入流,即得到服务器返回的数据 InputStream is = conn.getInputStream(); StringBuffer sb = new StringBuffer(); String s = null; BufferedReader reader = new BufferedReader(new InputStreamReader(is)); while ((s = reader.readLine()) != null) { sb.append(s); } String result = sb.toString();
这样就按照上面的协议完成了一个头像的上传。
Native和H5复用
现在的应用确实越来越多的APP跟H5紧密相连,因此也有越来越多的功能需要结合H5一起来实现。上传头像是一个很常见的功能。前面得到的结论是做一个公共的BaseActivity提供给NativeActivity和WebViewActivity来使用。然后在BaseActivity里面写上我们的图片的截取以及onActivityResult。
public class BaseActivity extends Activity{ public void pickUpPic() { // 上面操作中的系统的图片的截取 } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // 上面操作中的得到Bitmap的操作 }}
大概的框架就是这样,只需要在NativeActivity和WebViewActivity相应的位置调用pickUpPic()就行了。
这样就结束了?No.对于只是上传头像来说这样或许是结束了,但是还有很多的问题还没有考虑到。
1.请求的参数?
2.返回的结果,成功或失败提示有差别吗?
3.用户在网速慢的情况下取消上传的操作?
4.友好的提示用户上传的信息?
请求参数
pickUpPic()作为唯一的入口,因此需要将所有的参数(例如:请求的头像的宽高比、返回的大小、入口的类型等等)。因此需要全部写在pickUpPic()里面。
public void pickUpPic(Params parama){ // 将带入的参数设置一些信息 // 带入的参数设置截取的图像大小等等信息}
这样就能满足所有很多不同的需求了。设置的信息也可以带入onActivityResult中,在里面调用上传头像接口时使用。
提示信息
注意在UI线程中是无法处理网络操作的,我们现在的成功,失败以及用户的取消操作都是在子线程中操作的(也就是上传的时候才知道成功失败等等)。所以最先想到了使用一个Handler来操作,这样的话,还需要在BaseActivity中加一个handler来处理我们返回来的信息,同时主要到我们可能会有中不同的结果,success,fail,cancle。还有我们的NativeActivity个WebViewActivity两个不同的Activity的操作也应该有很大的不同的。大概可以写一个这样的Handler。
private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what) { case SUCCESS: // do somenthing listener.onSuccess(msg.obj); break; case FAIL: // do something listener.onFail(msg.obj); break; case CANCLE: // do something listener.onCancle(msg.obj); break; default: break; } }}
只需要分别在NativeActivity和WebViewActivity中去实现不同的操作就行了。
然后,大概就是这样了。
- Native和H5两种情况的头像上传
- Android--实现H5与Native交互的两种方式
- 两种上传头像的方式(file文件)
- native 和 H5 的交互
- native 和 H5 的交互
- 移动端h5头像上传、头像裁切、上传图片
- 安卓 native 和 H5 的交互
- android native 和 H5 的交互
- H5 头像上传(支持裁切)
- 头像截图上传两种方式(SWFUpload、一个简单易用的flash插件)
- iOS和H5交互的两种方式
- react-native-image-picker在Android上闪退的解决办法(上传头像base64,压缩上传图片)
- 头像上传的过程!~
- 简单的头像上传
- 实现头像的上传
- 头像的上传02
- 上传头像的处理
- iOS: JS和Native交互的两种方法
- SVN服务器搭建和使用(二) (转载)
- HashMap与hashCode以及equals
- 文章标题
- Java泛型应用示例
- MVC 从View像Controller中传值
- Native和H5两种情况的头像上传
- 数字证书校验过程
- nginx简单使用
- OJ刷题---填写乘法算式
- [已解决] jquery只能取得表格的第一行的第一个单元格数值
- elisp url库简要说明
- Linux命令:head,tail命令使用方法
- CentOS7 安装boost
- UVa 1586 Molar Mass