调用系统相册上传头像到服务器
2016-12-01 14:23
399 查看
调用系统相册上传头像到服务器
现在越来越多的app都需要上传图片到服务器中,包括我们公司刚开发的一款app,想实现的功能是调用系统相册,上传头像到服务器,为用户设置头像,在经过努力之下,终于完成了。写下博客,巩固一下这方面的知识点,同时也希望可以帮助大家;好了废话不多说,直接上代码先看一下MainActivity的布局文件把,很简单,就一个Button和一个ImageView,点击Button之后,会弹出一个对话框,可以选择相机、相册或者取消,ImageView用于显示你选择的照片
<RelativeLayout 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" tools:context="com.example.uploadimagetoserver.MainActivity" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="调用相册" /> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/ic_launcher" /> </RelativeLayout>
接下来看一下MainActivity的代码吧
private Button btn; private PopupWindow pop; private LinearLayout llPopup; private ImageView ivImage; /** * 请求裁剪码 */ public static final int REQUEST_CODE_GETIMAGE_BYCROP = 1; /** * 请求相机码 */ public static final int REQUEST_CODE_GETIMAGE_BYCAMERA = 2; /** * 请求相册 */ public static final int REQUEST_CODE_GETIMAGE_BYSDCARD = 3; /** * 去上传文件 */ protected static final int TO_UPLOAD_FILE = 4; /** * 上传文件响应 */ protected static final int UPLOAD_FILE_DONE = 5; // private Uri origUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); creatPopupwindows(); ivImage = (ImageView) findViewById(R.id.image); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { llPopup.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.activity_slide_enter_bottom)); pop.showAtLocation(parent, Gravity.BOTTOM, 0, 0); } }); } /** * 创建对话框 */ protected void creatPopupwindows() { pop = new PopupWindow(this); View popupView = getLayoutInflater().inflate(R.layout.item_popupwindows, null); llPopup = (LinearLayout) popupView.findViewById(R.id.ll_popup); pop.setWidth(LayoutParams.MATCH_PARENT); pop.setHeight(LayoutParams.WRAP_CONTENT); pop.setBackgroundDrawable(new BitmapDrawable()); pop.setFocusable(true); pop.setOutsideTouchable(true); pop.setContentView(popupView); parent = (RelativeLayout) popupView.findViewById(R.id.parent); Button bt1 = (Button) popupView .findViewById(R.id.item_popupwindows_camera);//照相 Button bt2 = (Button) popupView .findViewById(R.id.item_popupwindows_Photo);//相册 Button bt3 = (Button) popupView .findViewById(R.id.item_popupwindows_cancel);//取消 bt1.setOnClickListener(new OnClickListener() { public void onClick(View v) { //照相 photo(); pop.dismiss(); llPopup.clearAnimation(); } }); bt2.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent; // Android6.0以上,要动态申请读写权限 if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //申请读写权限 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_GETIMAGE_BYCROP); } else{ if (Build.VERSION.SDK_INT < 19) { intent = new Intent(); intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent, "选择图片"), REQUEST_CODE_GETIMAGE_BYCROP); } else { intent = new Intent(Intent.ACTION_PICK, Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent, "选择图片"), REQUEST_CODE_GETIMAGE_BYCROP); } } pop.dismiss(); //清除动画 llPopup.clearAnimation(); } }); bt3.setOnClickListener(new OnClickListener() { public void onClick(View v) { pop.dismiss(); llPopup.clearAnimation(); } }); } /** * 照相 */ protected void photo() { String savePath =""; if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //SD卡处于挂载状态,创建图片保存的文件夹路径 savePath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/image/"; File saveDir = new File(savePath); if(!saveDir.exists()){ //文件夹不存在,创建文件夹 saveDir.mkdirs(); } }else{ Toast.makeText(this, "无法保存照片,请检查SD卡是否挂载", Toast.LENGTH_SHORT).show(); return; } //创建图片名称 String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()); String fileName = "zhicuo_" + timeStamp + ".jpg";// 照片命名 //自定义图片保存路径 File out = new File(savePath, fileName); Uri uri = Uri.fromFile(out); origUri = uri; // 动态申请照相权限和读写权限 if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_GETIMAGE_BYCAMERA); } else{ Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Log.i("MainActivity", uri.toString()); openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(openCameraIntent, REQUEST_CODE_GETIMAGE_BYCAMERA); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent imageReturnIntent) { //回调处理结果 if (resultCode != Activity.RESULT_OK) return; switch (requestCode) { case REQUEST_CODE_GETIMAGE_BYCAMERA : startActionCrop(origUri);// 拍照后裁剪 break; case REQUEST_CODE_GETIMAGE_BYCROP: startActionCrop(imageReturnIntent.getData());// 选图后裁剪 break; case REQUEST_CODE_GETIMAGE_BYSDCARD : //发送上传头像的消息 handler.sendEmptyMessage(TO_UPLOAD_FILE); Bitmap bitmap = BitmapFactory.decodeFile(portraitFile.getAbsolutePath()); if(bitmap != null){ ivImage.setImageBitmap(bitmap); } break; } } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what) { case TO_UPLOAD_FILE: toUploadFile(); break; case UPLOAD_FILE_DONE: //响应返回的结果 if(msg.arg1 == UploadUtil.UPLOAD_SUCCESS_CODE ){ String result = (String) msg.obj; try { //上传成功之后,服务端返回的数据 JSONObject obj = new JSONObject(result); //获取服务端返回的头像地址 String portrait = obj.getString("portrait"); //根据自己业务做后续处理 } catch (JSONException e) { e.printStackTrace(); } }else if(msg.arg1 == UploadUtil.UPLOAD_SERVER_ERROR_CODE){ Toast.makeText(MainActivity.this, "上传失败", Toast.LENGTH_SHORT).show(); } break; default: break; } super.handleMessage(msg); } }; /** * 请求裁剪 * @param origUri */ private void startActionCrop(Uri data) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(data, "image/*"); intent.putExtra("output", this.getUploadTempFile(data)); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1);// 裁剪框比例 intent.putExtra("aspectY", 1); intent.putExtra("outputX", 200);// 输出图片大小 intent.putExtra("outputY", 200); intent.putExtra("scale", true);// 去黑边 intent.putExtra("scaleUpIfNeeded", true);// 去黑边 startActivityForResult(intent, REQUEST_CODE_GETIMAGE_BYSDCARD); } /** * 上传头像到服务器 */ protected void toUploadFile() { String fileKey = "img"; UploadUtil uploadUtil = UploadUtil.getInstance(); uploadUtil.setOnUploadProcessListener(this); //设置监听器监听上传状态 //定义一个Map集合,封装请求服务端时需要的参数 Map<String, String> params = new HashMap<String, String>(); //在这里根据服务端接口需要的参数来定,我们公司上传头像的接口,需要传入的参数是用户的 //userId,用户tocken,图片类型 // params.put("userId", user.getUserId()); // params.put("tocken", user.getTocken()); // params.put("picType", "1"); if(portraitFile.exists()){ //参数三:请求的url,这里我用到了公司的url uploadUtil.uploadFile(portraitFile.getAbsolutePath() ,fileKey, "http://www.megabes.com/zhicuo/v1/UploadPics.do",params); } } //获取保存头像地址的Uri private Uri getUploadTempFile(Uri uri) { String portraitPath = ""; if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //保存图像的文件夹路径 portraitPath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/image/Portrait"; File saveDir = new File(portraitPath); if(!saveDir.exists()){ saveDir.mkdirs(); } }else { Toast.makeText(this, "无法保存照片,请检查SD卡是否挂载", Toast.LENGTH_SHORT).show();; return null; } String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss") .format(new Date()); String thePath = getAbsolutePathFromNoStandardUri(uri); if (thePath.isEmpty()) { thePath = getAbsoluteImagePath(uri); } //获取图片路径的扩展名 String ext = thePath.substring(thePath.lastIndexOf('.') + 1); ext = ext.isEmpty() ? "jpg" : ext; // 照片命名 String cropFileName = "crop_" + timeStamp + "." + ext; portraitFile = new File(portraitPath, cropFileName); cropUri = Uri.fromFile(portraitFile); return cropUri; } private String SDCARD_MNT = "/mnt/sdcard"; private String SDCARD = "/sdcard"; private Uri cropUri; private File portraitFile; private RelativeLayout parent; /** * 判断当前Url是否标准的content://样式,如果不是,则返回绝对路径 * @param uri * @return */ private String getAbsolutePathFromNoStandardUri(Uri mUri) { String filePath = ""; String mUriString = mUri.toString(); mUriString = Uri.decode(mUriString); String pre1 = "file://" + SDCARD + File.separator; String pre2 = "file://" + SDCARD_MNT + File.separator; if (mUriString.startsWith(pre1)) { filePath = Environment.getExternalStorageDirectory().getPath() + File.separator + mUriString.substring(pre1.length()); } else if (mUriString.startsWith(pre2)) { filePath = Environment.getExternalStorageDirectory().getPath() + File.separator + mUriString.substring(pre2.length()); } return filePath; } /** * 通过uri获取文件的绝对路径 * @param uri * @return */ @SuppressWarnings("deprecation") private String getAbsoluteImagePath(Uri uri) { String imagePath = ""; String[] proj = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, proj, // Which columns to // return null, // WHERE clause; which rows to return (all rows) null, // WHERE clause selection arguments (none) null); // Order-by clause (ascending by name) if (cursor != null) { int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (cursor.getCount() > 0 && cursor.moveToFirst()) { imagePath = cursor.getString(column_index); } } return imagePath; } @Override public void onUploadDone(int responseCode, String message) { Message msg = Message.obtain(); msg.what = UPLOAD_FILE_DONE; msg.arg1 = responseCode; msg.obj = message; handler.sendMessage(msg); }
再来看一下UploadUtil工具类的代码吧
private static UploadUtil uploadUtil; private static final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成 private static final String PREFIX = "--"; private static final String LINE_END = "\r\n"; private static final String CONTENT_TYPE = "multipart/form-data"; // 内容类型 String result = null; private UploadUtil() { } /** * 单例模式获取上传工具类 * @return */ public static UploadUtil getInstance() { if (null == uploadUtil) { uploadUtil = new UploadUtil(); } return uploadUtil; } private static final String TAG = "UploadUtil"; private int readTimeOut = 10 * 1000; // 读取超时 private int connectTimeout = 10 * 1000; // 超时时间 /*** * 请求使用多长时间 */ private static int requestTime = 0; private static final String CHARSET = "utf-8"; // 设置编码 /*** * 上传成功 */ public static final int UPLOAD_SUCCESS_CODE = 1; /** * 文件不存在 */ public static final int UPLOAD_FILE_NOT_EXISTS_CODE = 2; /** * 服务器出错 */ public static final int UPLOAD_SERVER_ERROR_CODE = 3; protected static final int WHAT_TO_UPLOAD = 1; protected static final int WHAT_UPLOAD_DONE = 2; /** * android上传文件到服务器 * * @param filePath * 需要上传的文件的路径 * @param fileKey * 在网页上<input type=file name=xxx/> xxx就是这里的fileKey * @param RequestURL * 请求的URL */ public void uploadFile(String filePath, String fileKey, String RequestURL, Map<String, String> param) { if (filePath == null) { sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在"); return; } try { File file = new File(filePath); uploadFile(file, fileKey, RequestURL, param); } catch (Exception e) { sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在"); e.printStackTrace(); return; } } /** * android上传文件到服务器 * * @param file * 需要上传的文件 * @param fileKey * 在网页上<input type=file name=xxx/> xxx就是这里的fileKey * @param RequestURL * 请求的URL */ public void uploadFile(final File file, final String fileKey, final String RequestURL, final Map<String, String> param) { //开启线程上传文件 new Thread(){ @Override public void run() { toUploadFile(file, fileKey, RequestURL, param); } }; } private void toUploadFile(File file, String fileKey, String RequestURL, Map<String, String> param) { requestTime= 0; long requestTime = System.currentTimeMillis(); long responseTime = 0; try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(readTimeOut); conn.setConnectTimeout(connectTimeout); conn.setDoInput(true); // 允许输入流 conn.setDoOutput(true); // 允许输出流 conn.setUseCaches(false); // 不允许使用缓存 conn.setRequestMethod("POST"); // 请求方式 conn.setRequestProperty("Charset", CHARSET); // 设置编码 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); /** * 当文件不为空,把文件包装并且上传 */ DataOutputStream dos = new DataOutputStream(conn.getOutputStream()); StringBuffer sb = null; String params = ""; /*** * 以下是用于上传参数 */ if (param != null && param.size() > 0) { Iterator<String> it = param.keySet().iterator(); while (it.hasNext()) { sb = null; sb = new StringBuffer(); String key = it.next(); String value = param.get(key); sb.append(PREFIX).append(BOUNDARY).append(LINE_END); sb.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(LINE_END).append(LINE_END); sb.append(value).append(LINE_END); params = sb.toString(); Log.i(TAG, key+"="+params+"##"); dos.write(params.getBytes()); } } sb = null; params = null; sb = new StringBuffer(); /** * 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ sb.append(PREFIX).append(BOUNDARY).append(LINE_END); sb.append("Content-Disposition:form-data; name=\"" + fileKey + "\"; filename=\"" + file.getName() + "\"" + LINE_END); sb.append("Content-Type:image/pjpeg" + LINE_END); // 这里配置的Content-type很重要的 ,用于服务器端辨别文件的类型的 sb.append(LINE_END); params = sb.toString(); sb = null; Log.i(TAG, file.getName()+"=" + params+"##"); dos.write(params.getBytes()); /**上传文件*/ InputStream is = new FileInputStream(file); // //文件大小 // onUploadProcessListener.initUpload((int)file.length()); // byte[] bytes = new byte[1024]; int len = 0; while ((len = is.read(bytes)) != -1) { dos.write(bytes, 0, len); } is.close(); dos.write(LINE_END.getBytes()); byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes(); dos.write(end_data); dos.flush(); /** * 获取响应码 200=成功 当响应成功,获取响应的流 */ int res = conn.getResponseCode(); responseTime = System.currentTimeMillis(); this.requestTime = (int) ((responseTime-requestTime)/1000); Log.e(TAG, "response code:" + res); if (res == 200) { Log.e(TAG, "request success"); InputStream input = conn.getInputStream(); StringBuffer sb1 = new StringBuffer(); int ss; while ((ss = input.read()) != -1) { sb1.append((char) ss); } result = sb1.toString(); Log.i(TAG, "result : " + result); sendMessage(UPLOAD_SUCCESS_CODE, result); return; } else { Log.e(TAG, "request error"); sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:code=" + res); return; } } catch (MalformedURLException e) { sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error=" + e.getMessage()); e.printStackTrace(); return; } catch (IOException e) { sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error=" + e.getMessage()); e.printStackTrace(); return; } } /** * 发送上传结果 * @param responseCode * @param responseMessage */ private void sendMessage(int responseCode,String responseMessage) { onUploadProcessListener.onUploadDone(responseCode, responseMessage); } /** * 下面是一个自定义的回调函数,用到回调上传文件是否完成 * */ public interface OnUploadProcessListener { /** * 上传响应 * @param responseCode * @param message */ void onUploadDone(int responseCode, String message); } private OnUploadProcessListener onUploadProcessListener; public void setOnUploadProcessListener( OnUploadProcessListener onUploadProcessListener) { this.onUploadProcessListener = onUploadProcessListener; } public int getReadTimeOut() { return readTimeOut; } public void setReadTimeOut(int readTimeOut) { this.readTimeOut = readTimeOut; } public int getConnectTimeout() { return connectTimeout; } public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } /** * 获取上传使用的时间 * @return */ public static int getRequestTime() { return requestTime; }
最后别忘了在AndroidManifest.xml文件中添加如下权限哦
<!-- 访问internet权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
注意:Android6.0之后,需要在代码中动态的申请权限
完整代码下载
相关文章推荐
- 调用系统相机、相册、剪裁图片并上传(常用于上传头像,兼容Android7.0)
- h5 app开发使用cordova调用相册、相机、文件系统或录音录视频,并上传到服务器
- Android开发中调用系统相册上传图片到服务器OPPO等部分手机上出现短暂的显示桌面问题的解决方法
- iOS 相机调用相册打开及图片头像的上传到服务器详解
- 调用系统相机、相册、剪裁图片并上传(常用于上传头像,兼容Android7.0)
- 调用系统相册上传图片到服务器--OPPO等部分手机上出现短暂的显示桌面问题
- 个人界面 < 头像 > 图片选择(相册,拍照)--如何调用系统的相册,裁剪并且上传
- Android从系统调用相册OkHttp上传到服务器(activity数据传递)
- 调用系统相机相册上传头像
- Android头像上传(本地相册和调用系统相机)
- 调用手机照相和相册来显示个人信心头像并上传至服务器
- 调用系统相机、相册、剪裁图片并上传(常用于上传头像,兼容Android7.0)
- iOS调用系统相册,相机上传头像的基本技巧
- Android菜鸟练习第一课 调用系统裁剪功能裁剪图片上传服务器
- Android调取系统相册和相机照片设置到ImageView并上传到服务器
- iOS调用相机,相册,上传头像
- 从UIWebView中调用iOS相册,并选择图片上传到Linux Web服务器。
- 音频录制上传服务器,调用系统相机
- WebView中调用系统相册或拍照上传
- 安卓开发小米4,酷派 手机适配和调用系统相机相册做图片上传的问题