Android图片上传(头像裁切+原图原样)

来源:互联网 发布:武汉mac口红专柜哪里有 编辑:程序博客网 时间:2024/05/21 08:45

还是那句话,最近项目比较忙哭拖了很久这篇文章终于完成了!转载自http://blog.csdn.net/geofferysun/article/details/42835669

先看一下效果图:

(一)头像裁切、上传服务器(效果图)

一般都是有圆形显示头像的,这里我自定义了一个ImageView,页面很干净但是看着很上档次吧!

点击头像从底部弹出一个对话框,提示用户头像来自相机或者相册,这都是常规流程。

上传完成后默认的“程序员头像”换成了萌妹子

(二)普通图片上传服务器(效果图)

模仿QQ空间发动态的布局随意捏造一个界面出来

点击添加图片从底部弹出一个对话框,提示用户图片来自相机或者相册,这也都是常规流程。

上传过程中,有可能图片很大,显示一个进度圈(其实头像上传也有,只是文件小,还没显示就上传完成了大笑

上传完成后把刚才的照片亮出来显示到按钮的地方,当然大家根据需要还可以自己扩展(比如长按抖动出现删除、继续添加N张等等)


下面简单铺一下代码:

(一)头像裁切、上传服务器(代码)


这里上边的按钮是头像的点击事件,弹出底部的头像选择框,下边的按钮跳到下个页面,进行原图上传。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void onClick(View v) {  
  3.     switch (v.getId()) {  
  4.     case R.id.avatarImg:// 更换头像点击事件  
  5.         menuWindow = new SelectPicPopupWindow(mContext, itemsOnClick);    
  6.         menuWindow.showAtLocation(findViewById(R.id.mainLayout),   
  7.                 Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 00);   
  8.         break;  
  9.     case R.id.loginBtn://登录按钮跳转事件  
  10.         startActivity(new Intent(mContext, UploadActivity.class));  
  11.         break;  
  12.   
  13.     default:  
  14.         break;  
  15.     }  
  16. }  
弹出窗绑定一个按钮事件
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //为弹出窗口实现监听类    
  2. private OnClickListener itemsOnClick = new OnClickListener() {  
  3.     @Override  
  4.     public void onClick(View v) {  
  5.         menuWindow.dismiss();  
  6.         switch (v.getId()) {  
  7.         // 拍照  
  8.         case R.id.takePhotoBtn:  
  9.             Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  10.             //下面这句指定调用相机拍照后的照片存储的路径  
  11.             takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,   
  12.                     Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)));  
  13.             startActivityForResult(takeIntent, REQUESTCODE_TAKE);  
  14.             break;  
  15.         // 相册选择图片  
  16.         case R.id.pickPhotoBtn:  
  17.             Intent pickIntent = new Intent(Intent.ACTION_PICK, null);  
  18.             // 如果朋友们要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"  
  19.             pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");  
  20.             startActivityForResult(pickIntent, REQUESTCODE_PICK);  
  21.             break;  
  22.         default:  
  23.             break;  
  24.         }  
  25.     }  
  26. };   
为图像选取返回的接收处理

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.       
  4.     switch (requestCode) {  
  5.     case REQUESTCODE_PICK:// 直接从相册获取  
  6.         try {  
  7.             startPhotoZoom(data.getData());  
  8.         } catch (NullPointerException e) {  
  9.             e.printStackTrace();// 用户点击取消操作  
  10.         }  
  11.         break;  
  12.     case REQUESTCODE_TAKE:// 调用相机拍照  
  13.         File temp = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_NAME);  
  14.         startPhotoZoom(Uri.fromFile(temp));  
  15.         break;  
  16.     case REQUESTCODE_CUTTING:// 取得裁剪后的图片  
  17.         if (data != null) {  
  18.             setPicToView(data);  
  19.         }  
  20.         break;  
  21.     }  
  22.     super.onActivityResult(requestCode, resultCode, data);  
  23. }  
把图片显示出来,然后上传
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 裁剪图片方法实现 
  3.  * @param uri 
  4.  */  
  5. public void startPhotoZoom(Uri uri) {  
  6.     Intent intent = new Intent("com.android.camera.action.CROP");  
  7.     intent.setDataAndType(uri, "image/*");  
  8.     // crop=true是设置在开启的Intent中设置显示的VIEW可裁剪  
  9.     intent.putExtra("crop""true");  
  10.     // aspectX aspectY 是宽高的比例  
  11.     intent.putExtra("aspectX"1);  
  12.     intent.putExtra("aspectY"1);  
  13.     // outputX outputY 是裁剪图片宽高  
  14.     intent.putExtra("outputX"300);  
  15.     intent.putExtra("outputY"300);  
  16.     intent.putExtra("return-data"true);  
  17.     startActivityForResult(intent, REQUESTCODE_CUTTING);  
  18. }  
  19.       
  20. /**  
  21.  * 保存裁剪之后的图片数据  
  22.  * @param picdata  
  23.  */  
  24. private void setPicToView(Intent picdata) {  
  25.     Bundle extras = picdata.getExtras();  
  26.     if (extras != null) {  
  27.         // 取得SDCard图片路径做显示  
  28.         Bitmap photo = extras.getParcelable("data");  
  29.         Drawable drawable = new BitmapDrawable(null, photo);  
  30.         urlpath = FileUtil.saveFile(mContext, "temphead.jpg", photo);  
  31.         avatarImg.setImageDrawable(drawable);  
  32.   
  33.         // 新线程后台上传服务端  
  34.         pd = ProgressDialog.show(mContext, null"正在上传图片,请稍候...");  
  35.         new Thread(uploadImageRunnable).start();  
  36.     }  
  37. }  
  38.   
  39. /** 
  40.  * 使用HttpUrlConnection模拟post表单进行文件 
  41.  * 上传平时很少使用,比较麻烦 
  42.  * 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。 
  43.  */  
  44. Runnable uploadImageRunnable = new Runnable() {  
  45.     @Override  
  46.     public void run() {  
  47.           
  48.         if(TextUtils.isEmpty(imgUrl)){  
  49.             Toast.makeText(mContext, "还没有设置上传服务器的路径!", Toast.LENGTH_SHORT).show();  
  50.             return;  
  51.         }  
  52.           
  53.         Map<String, String> textParams = new HashMap<String, String>();  
  54.         Map<String, File> fileparams = new HashMap<String, File>();  
  55.           
  56.         try {  
  57.             // 创建一个URL对象  
  58.             URL url = new URL(imgUrl);  
  59.             textParams = new HashMap<String, String>();  
  60.             fileparams = new HashMap<String, File>();  
  61.             // 要上传的图片文件  
  62.             File file = new File(urlpath);  
  63.             fileparams.put("image", file);  
  64.             // 利用HttpURLConnection对象从网络中获取网页数据  
  65.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  66.             // 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)  
  67.             conn.setConnectTimeout(5000);  
  68.             // 设置允许输出(发送POST请求必须设置允许输出)  
  69.             conn.setDoOutput(true);  
  70.             // 设置使用POST的方式发送  
  71.             conn.setRequestMethod("POST");  
  72.             // 设置不使用缓存(容易出现问题)  
  73.             conn.setUseCaches(false);  
  74.             conn.setRequestProperty("Charset""UTF-8");//设置编码     
  75.             // 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头  
  76.             conn.setRequestProperty("ser-Agent""Fiddler");  
  77.             // 设置contentType  
  78.             conn.setRequestProperty("Content-Type""multipart/form-data; boundary=" + NetUtil.BOUNDARY);  
  79.             OutputStream os = conn.getOutputStream();  
  80.             DataOutputStream ds = new DataOutputStream(os);  
  81.             NetUtil.writeStringParams(textParams, ds);  
  82.             NetUtil.writeFileParams(fileparams, ds);  
  83.             NetUtil.paramsEnd(ds);  
  84.             // 对文件流操作完,要记得及时关闭  
  85.             os.close();  
  86.             // 服务器返回的响应吗  
  87.             int code = conn.getResponseCode(); // 从Internet获取网页,发送请求,将网页以流的形式读回来  
  88.             // 对响应码进行判断  
  89.             if (code == 200) {// 返回的响应码200,是成功  
  90.                 // 得到网络返回的输入流  
  91.                 InputStream is = conn.getInputStream();  
  92.                 resultStr = NetUtil.readString(is);  
  93.             } else {  
  94.                 Toast.makeText(mContext, "请求URL失败!", Toast.LENGTH_SHORT).show();  
  95.             }  
  96.         } catch (Exception e) {  
  97.             e.printStackTrace();  
  98.         }  
  99.         handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler  
  100.     }  
  101. };  
  102.   
  103. Handler handler = new Handler(new Handler.Callback() {  
  104.       
  105.     @Override  
  106.     public boolean handleMessage(Message msg) {  
  107.         switch (msg.what) {  
  108.         case 0:  
  109.             pd.dismiss();  
  110.               
  111.             try {  
  112.                 // 返回数据示例,根据需求和后台数据灵活处理  
  113.                 // {"status":"1","statusMessage":"上传成功","imageUrl":"http://120.24.219.49/726287_temphead.jpg"}  
  114.                 JSONObject jsonObject = new JSONObject(resultStr);  
  115.                   
  116.                 // 服务端以字符串“1”作为操作成功标记  
  117.                 if (jsonObject.optString("status").equals("1")) {  
  118.                     BitmapFactory.Options option = new BitmapFactory.Options();  
  119.                     // 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图,3为三分之一  
  120.                     option.inSampleSize = 1;  
  121.                       
  122.                     // 服务端返回的JsonObject对象中提取到图片的网络URL路径  
  123.                     String imageUrl = jsonObject.optString("imageUrl");  
  124.                     Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();  
  125.                 }else{  
  126.                     Toast.makeText(mContext, jsonObject.optString("statusMessage"), Toast.LENGTH_SHORT).show();  
  127.                 }  
  128.                   
  129.             } catch (JSONException e) {  
  130.                 e.printStackTrace();  
  131.             }  
  132.               
  133.             break;  
  134.               
  135.         default:  
  136.             break;  
  137.         }  
  138.         return false;  
  139.     }  
  140. });  

(二)普通图片上传服务器(代码)

    直接从这里开始,和头像那里基本没什么区别,我把拍照什么的单独抽出了方法,思路更清晰
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //为弹出窗口实现监听类    
  2. private OnClickListener itemsOnClick = new OnClickListener() {  
  3.     @Override  
  4.     public void onClick(View v) {  
  5.         // 隐藏弹出窗口  
  6.         menuWindow.dismiss();  
  7.           
  8.         switch (v.getId()) {  
  9.         case R.id.takePhotoBtn:// 拍照  
  10.             takePhoto();  
  11.             break;  
  12.         case R.id.pickPhotoBtn:// 相册选择图片  
  13.             pickPhoto();  
  14.             break;  
  15.         case R.id.cancelBtn:// 取消  
  16.             break;  
  17.         default:  
  18.             break;  
  19.         }  
  20.     }  
  21. };   
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 拍照获取图片 
  3.  */  
  4. private void takePhoto() {  
  5.     // 执行拍照前,应该先判断SD卡是否存在  
  6.     String SDState = Environment.getExternalStorageState();  
  7.     if (SDState.equals(Environment.MEDIA_MOUNTED)) {  
  8.   
  9.         Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  10.         /*** 
  11.          * 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的  
  12.          * 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图 
  13.          * 如果不使用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰 
  14.          */  
  15.         ContentValues values = new ContentValues();  
  16.         photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);  
  17.         intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);  
  18.         startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);  
  19.     } else {  
  20.         Toast.makeText(this"内存卡不存在", Toast.LENGTH_LONG).show();  
  21.     }  
  22. }  
  23.   
  24. /*** 
  25.  * 从相册中取图片 
  26.  */  
  27. private void pickPhoto() {  
  28.     Intent intent = new Intent();  
  29.     // 如果要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"  
  30.     intent.setType("image/*");  
  31.     intent.setAction(Intent.ACTION_GET_CONTENT);  
  32.     startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);  
  33. }  
处理一下图片选取的页面回调
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         // 点击取消按钮  
  4.         if(resultCode == RESULT_CANCELED){  
  5.             return;  
  6.         }  
  7.           
  8.         // 可以使用同一个方法,这里分开写为了防止以后扩展不同的需求  
  9.         switch (requestCode) {  
  10.         case SELECT_PIC_BY_PICK_PHOTO:// 如果是直接从相册获取  
  11.             doPhoto(requestCode, data);  
  12.             break;  
  13.         case SELECT_PIC_BY_TACK_PHOTO:// 如果是调用相机拍照时  
  14.             doPhoto(requestCode, data);  
  15.             break;  
  16.         }  
  17.         super.onActivityResult(requestCode, resultCode, data);  
  18.     }  
接下来就是显示图片和上传服务器了,上传和头像是同一个流程,只是不进行裁切
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 选择图片后,获取图片的路径 
  3.  *  
  4.  * @param requestCode 
  5.  * @param data 
  6.  */  
  7. private void doPhoto(int requestCode, Intent data) {  
  8.       
  9.     // 从相册取图片,有些手机有异常情况,请注意  
  10.     if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {  
  11.         if (data == null) {  
  12.             Toast.makeText(this"选择图片文件出错", Toast.LENGTH_LONG).show();  
  13.             return;  
  14.         }  
  15.         photoUri = data.getData();  
  16.         if (photoUri == null) {  
  17.             Toast.makeText(this"选择图片文件出错", Toast.LENGTH_LONG).show();  
  18.             return;  
  19.         }  
  20.     }  
  21.       
  22.     String[] pojo = { MediaColumns.DATA };  
  23.     // The method managedQuery() from the type Activity is deprecated  
  24.     //Cursor cursor = managedQuery(photoUri, pojo, null, null, null);  
  25.     Cursor cursor = mContext.getContentResolver().query(photoUri, pojo, nullnullnull);  
  26.     if (cursor != null) {  
  27.         int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);  
  28.         cursor.moveToFirst();  
  29.         picPath = cursor.getString(columnIndex);  
  30.           
  31.         // 4.0以上的版本会自动关闭 (4.0--14;; 4.0.3--15)  
  32.         if (Integer.parseInt(Build.VERSION.SDK) < 14) {  
  33.             cursor.close();  
  34.         }  
  35.     }  
  36.       
  37.     // 如果图片符合要求将其上传到服务器  
  38.     if (picPath != null && (    picPath.endsWith(".png") ||   
  39.                                 picPath.endsWith(".PNG") ||   
  40.                                 picPath.endsWith(".jpg") ||   
  41.                                 picPath.endsWith(".JPG"))) {  
  42.   
  43.           
  44.         BitmapFactory.Options option = new BitmapFactory.Options();  
  45.         // 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图  
  46.         option.inSampleSize = 1;  
  47.         // 根据图片的SDCard路径读出Bitmap  
  48.         Bitmap bm = BitmapFactory.decodeFile(picPath, option);  
  49.         // 显示在图片控件上  
  50.         picImg.setImageBitmap(bm);  
  51.           
  52.         pd = ProgressDialog.show(mContext, null"正在上传图片,请稍候...");  
  53.         new Thread(uploadImageRunnable).start();  
  54.     } else {  
  55.         Toast.makeText(this"选择图片文件不正确", Toast.LENGTH_LONG).show();  
  56.     }  
  57.   
  58. }  
  59.   
  60. /** 
  61.  * 使用HttpUrlConnection模拟post表单进行文件 
  62.  * 上传平时很少使用,比较麻烦 
  63.  * 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。 
  64.  */  
  65. Runnable uploadImageRunnable = new Runnable() {  
  66.     @Override  
  67.     public void run() {  
  68.           
  69.         if(TextUtils.isEmpty(imgUrl)){  
  70.             Toast.makeText(mContext, "还没有设置上传服务器的路径!", Toast.LENGTH_SHORT).show();  
  71.             return;  
  72.         }  
  73.           
  74.         Map<String, String> textParams = new HashMap<String, String>();  
  75.         Map<String, File> fileparams = new HashMap<String, File>();  
  76.           
  77.         try {  
  78.             // 创建一个URL对象  
  79.             URL url = new URL(imgUrl);  
  80.             textParams = new HashMap<String, String>();  
  81.             fileparams = new HashMap<String, File>();  
  82.             // 要上传的图片文件  
  83.             File file = new File(picPath);  
  84.             fileparams.put("image", file);  
  85.             // 利用HttpURLConnection对象从网络中获取网页数据  
  86.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  87.             // 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)  
  88.             conn.setConnectTimeout(5000);  
  89.             // 设置允许输出(发送POST请求必须设置允许输出)  
  90.             conn.setDoOutput(true);  
  91.             // 设置使用POST的方式发送  
  92.             conn.setRequestMethod("POST");  
  93.             // 设置不使用缓存(容易出现问题)  
  94.             conn.setUseCaches(false);  
  95.             // 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头  
  96.             conn.setRequestProperty("ser-Agent""Fiddler");  
  97.             // 设置contentType  
  98.             conn.setRequestProperty("Content-Type""multipart/form-data; boundary=" + NetUtil.BOUNDARY);  
  99.             OutputStream os = conn.getOutputStream();  
  100.             DataOutputStream ds = new DataOutputStream(os);  
  101.             NetUtil.writeStringParams(textParams, ds);  
  102.             NetUtil.writeFileParams(fileparams, ds);  
  103.             NetUtil.paramsEnd(ds);  
  104.             // 对文件流操作完,要记得及时关闭  
  105.             os.close();  
  106.             // 服务器返回的响应吗  
  107.             int code = conn.getResponseCode(); // 从Internet获取网页,发送请求,将网页以流的形式读回来  
  108.             // 对响应码进行判断  
  109.             if (code == 200) {// 返回的响应码200,是成功  
  110.                 // 得到网络返回的输入流  
  111.                 InputStream is = conn.getInputStream();  
  112.                 resultStr = NetUtil.readString(is);  
  113.             } else {  
  114.                 Toast.makeText(mContext, "请求URL失败!", Toast.LENGTH_SHORT).show();  
  115.             }  
  116.         } catch (Exception e) {  
  117.             e.printStackTrace();  
  118.         }  
  119.         handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler  
  120.     }  
  121. };  
  122.   
  123. Handler handler = new Handler(new Handler.Callback() {  
  124.   
  125.     @Override  
  126.     public boolean handleMessage(Message msg) {  
  127.         switch (msg.what) {  
  128.         case 0:  
  129.             pd.dismiss();  
  130.               
  131.             try {  
  132.                 JSONObject jsonObject = new JSONObject(resultStr);  
  133.                 // 服务端以字符串“1”作为操作成功标记  
  134.                 if (jsonObject.optString("status").equals("1")) {  
  135.   
  136.                     // 用于拼接发布说说时用到的图片路径  
  137.                     // 服务端返回的JsonObject对象中提取到图片的网络URL路径  
  138.                     String imageUrl = jsonObject.optString("imageUrl");  
  139.                     // 获取缓存中的图片路径  
  140.                     Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();  
  141.                 } else {  
  142.                     Toast.makeText(mContext, jsonObject.optString("statusMessage"), Toast.LENGTH_SHORT).show();  
  143.                 }  
  144.                   
  145.             } catch (JSONException e) {  
  146.                 e.printStackTrace();  
  147.             }  
  148.             break;  
  149.         default:  
  150.             break;  
  151.         }  
  152.         return false;  
  153.     }  
  154. });  


最后放上完整的代码!大家上传路径自己搭建啊!
0 0
原创粉丝点击