android处理拍照与选择相册并可动态设置是否可裁剪上传解决方案 并且真机测试通过(小米\魔族\htc)sdk2.1-4.x系统

  1. package org.wavefar.lib.utils;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.File;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8.   
  9. import org.wavefar.lib.Config;  
  10. import org.wavefar.lib.R;  
  11. import org.wavefar.lib.utils.imagecrop.CropImage;  
  12.   
  13. import android.app.Activity;  
  14. import android.app.AlertDialog;  
  15. import android.content.Context;  
  16. import android.content.Intent;  
  17. import android.database.Cursor;  
  18. import android.graphics.Bitmap;  
  19. import android.graphics.BitmapFactory;  
  20. import android.graphics.Matrix;  
  21. import android.net.Uri;  
  22. import android.os.AsyncTask;  
  23. import android.os.Environment;  
  24. import android.provider.MediaStore;  
  25. import android.view.Gravity;  
  26. import android.view.View;  
  27. import android.view.View.OnClickListener;  
  28. import android.view.ViewGroup.LayoutParams;  
  29. import android.view.Window;  
  30. import android.widget.Toast;  
  31.   
  32. /** 
  33.  * 拍照工具类 
  34.  * <p>方法:initCutSize裁剪设置(可选)</p> 
  35.  * <p>图片入口方法:doPickPhotoAction启动图片和相册筛选</p> 
  36.  * <p>调用该类须从在activity的onActivityResult获取返回数据,回调数据实例:</p> 
  37.  * <pre> 
  38.  * protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
  39.  *      super.onActivityResult(requestCode, resultCode, data); 
  40.  *      if (resultCode == RESULT_OK) { 
  41.  *          switch (requestCode) { 
  42.  *          case PictureActivityUtil.CAMERA_WITH_DATA: // 拍照返回 
  43.  *              PictureActivityUtil.doCropPhoto(UserInfoActivity.this, PictureActivityUtil.CAPTURE_IMAGE_TARGET_PATH); 
  44.  *              break; 
  45.  *          case PictureActivityUtil.PHOTO_PICKED_WITH_DATA: // 选择相册返回 
  46.  *              String path = PictureActivityUtil.getPickPhotoPath(UserInfoActivity.this, data); 
  47.  *              PictureActivityUtil.doCropPhoto(UserInfoActivity.this, path); 
  48.  *              break; 
  49.  *          case PictureActivityUtil.PHOTO_CROP: // 裁剪图片返回 
  50.  *              // 获取图片裁剪后路径 
  51.  *              String cropPath = Uri.parse(data.getAction()).getPath(); 
  52.  *              break; 
  53.  *          } 
  54.         } 
  55.  *  } 
  56.  *  </pre> 
  57.  * @author summer 
  58.  * @date 2014年4月30日 下午3:17:26 
  59.  */  
  60. public class PictureActivityUtil {  
  61.     private static final String TAG = "PictureActivityUtil";  
  62.     /** 
  63.      * 获取图片压缩后保存的路径 
  64.      */  
  65.     private static final String COMPRESS_IMAGE_TARGET_DIR = FileUtil.getSDRootPath() + Config.CACHE_FILEDIR_PIC;  
  66.     /** 
  67.      * 获取照相机保存图片路径 
  68.      */  
  69.     public static final String CAPTURE_IMAGE_TARGET_PATH = FileUtil.getSDRootPath() + Config.CACHE_FILEDIR_PIC  
  70.             + "caputure_temp.jpg";  
  71.   
  72.     public static final String CROP_IMAGE_TARGET_PATH = FileUtil.getSDRootPath() + Config.CACHE_FILEDIR_PIC;  
  73.   
  74.     /** 
  75.      * 用来标识请求照相功能的requestCode 
  76.      */  
  77.     public static final int CAMERA_WITH_DATA = 168;  
  78.     /** 
  79.      * 用来标识请求相册的requestCode 
  80.      */  
  81.     public static final int PHOTO_PICKED_WITH_DATA = 169;  
  82.     /** 
  83.      * 用来标示请求图片裁剪 requestCode 
  84.      */  
  85.     public static final int PHOTO_CROP = 170;  
  86.   
  87.     private static int cut_w; // 裁剪宽度  
  88.     private static int cut_h; // 裁剪长度  
  89.     private static int mAspectX,mAspectY; //裁剪比例  
  90.     private Context mContext;  
  91.   
  92.     public PictureActivityUtil(Context mContext) {  
  93.         this.mContext = mContext;  
  94.     }  
  95.   
  96.     /** 
  97.      * 设置裁剪图片尺寸 
  98.      *  
  99.      * @param w 
  100.      * @param h 
  101.      */  
  102.     public static void initCutSize(int w, int h) {  
  103.         cut_w = w;  
  104.         cut_h = h;  
  105.     }  
  106.     /** 
  107.      * 设置裁剪图片尺寸和比例 
  108.      * @param w 尺寸 
  109.      * @param h 
  110.      * @param aspectX 比例 
  111.      * @param aspectY 
  112.      */  
  113.     public static void initCutSize(int w, int h,int aspectX,int aspectY) {  
  114.         cut_w = w;  
  115.         cut_h = h;  
  116.         mAspectX = aspectX;  
  117.         mAspectX = aspectY;  
  118.     }  
  119.   
  120.     /** 
  121.      * 照片处理入口 
  122.      * 开始启动照片选择框 
  123.      * @param context 
  124.      */  
  125.     public static void doPickPhotoAction(final Activity context) {  
  126.         final AlertDialog alertDialog = new AlertDialog.Builder(context).create();  
  127.         alertDialog.show();  
  128.         alertDialog.setCanceledOnTouchOutside(true);  
  129.         Window window = alertDialog.getWindow();  
  130.         window.setWindowAnimations(R.style.Animation_Dialog_Bottom);  
  131.         window.setGravity(Gravity.BOTTOM);  
  132.         window.setLayout(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);  
  133.         window.setContentView(R.layout.layout_select_image);  
  134.         View view = window.getDecorView();  
  135.           
  136.         view.findViewById(R.id.takePhoto).setOnClickListener(new OnClickListener() {  
  137.               
  138.             @Override  
  139.             public void onClick(View v) {  
  140.                 alertDialog.dismiss();  
  141.                 doTakePhoto(context);// 用户点击了从照相机获取  
  142.                   
  143.             }  
  144.         });  
  145.         view.findViewById(R.id.pickPhoto).setOnClickListener(new OnClickListener() {  
  146.               
  147.             @Override  
  148.             public void onClick(View v) {  
  149.                 alertDialog.dismiss();  
  150.                 doPickPhotoFromGallery(context);// 从相册中去获取  
  151.             }  
  152.         });  
  153.         view.findViewById(R.id.cancel).setOnClickListener(new OnClickListener() {  
  154.               
  155.             @Override  
  156.             public void onClick(View v) {  
  157.                 alertDialog.dismiss();  
  158.             }  
  159.         });  
  160.     }  
  161.   
  162.     /** 
  163.      * 拍照获取图片 
  164.      * @param context 
  165.      */  
  166.     public static void doTakePhoto(Activity context) {  
  167.         String status = Environment.getExternalStorageState();  
  168.         if (!status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡  
  169.             AlertUtil.showToast(context, "没有找到SD卡或者正在使用请关闭usb连接模式");  
  170.             return;  
  171.         }  
  172.         try {  
  173.             Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  174.             intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(CAPTURE_IMAGE_TARGET_PATH)));  
  175.             context.startActivityForResult(intent, CAMERA_WITH_DATA);  
  176.         } catch (Exception e) {  
  177.             Toast.makeText(context, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show();  
  178.                 LogUtil.e(TAG, e.toString());  
  179.         }  
  180.     }  
  181.   
  182.     /** 
  183.      * 调用相册查看图片 
  184.      * @param context 
  185.      */  
  186.     public static void doPickPhotoFromGallery(Activity context) {  
  187.         String status = Environment.getExternalStorageState();  
  188.         if (!status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡  
  189.             AlertUtil.showToast(context, "没有找到SD卡或者正在使用请关闭usb连接模式");  
  190.             return;  
  191.         }  
  192.         try {  
  193.             Intent intent = new Intent(Intent.ACTION_PICK);  
  194.             intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");  
  195.             context.startActivityForResult(intent, PHOTO_PICKED_WITH_DATA);  
  196.         } catch (Exception e) {  
  197.             Toast.makeText(context, R.string.photoPickerNotFoundText1, Toast.LENGTH_LONG).show();  
  198.                 e.printStackTrace();  
  199.         }  
  200.     }  
  201.   
  202.     /**  
  203.      * 开始执行裁剪图片操作  
  204.      *   
  205.      * @param context  
  206.      * @param path  
  207.      *            图片资源地址  
  208.      */  
  209.     public static void doCropPhoto(Activity context, String path) {  
  210.         try {  
  211.             int outputX = cut_w != 0 ? cut_w : Config.w;  
  212.             int outputY = cut_h != 0 ? cut_h : Config.h;  
  213.             int aspectX = mAspectX != 0 ? mAspectX : Config.aspectX;  
  214.             int aspectY = mAspectY != 0 ? mAspectY : Config.aspectY;  
  215.             Intent intent = new Intent(context, CropImage.class);  
  216.             intent.setType("image/*");  
  217.             intent.putExtra("aspectX", aspectX);  
  218.             intent.putExtra("aspectY", aspectY);  
  219.             intent.putExtra("outputX", outputX);  
  220.             intent.putExtra("outputY", outputY);  
  221.             File file = new File(getCropPath());  
  222.             if (file.exists()) {  
  223.                 file.delete();  
  224.             }  
  225.             intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));  
  226.             intent.putExtra("return-data"false);  
  227.             intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG);  
  228.             intent.setData(Uri.parse("file://"+path));  
  229.             context.startActivityForResult(intent, PHOTO_CROP);  
  230.         } catch (Exception e) {  
  231.             Toast.makeText(context, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show();  
  232.             LogUtil.e(TAG, "裁剪:" + e.toString());  
  233.         }  
  234.     }  
  235.   
  236.   
  237.     /**  
  238.      * 获取选择图片路径  
  239.      *   
  240.      * @param activity  
  241.      * @param data  
  242.      * @return path  
  243.      */  
  244.     public static String getPickPhotoPath(Activity activity, Intent data) {  
  245.         String path = "";  
  246.         Uri imageuri = data.getData();  
  247.         if (null != imageuri && imageuri.getScheme().compareTo("file") == 0) {  
  248.             path = imageuri.toString().replace("file://""");  
  249.         } else {  
  250.             if (imageuri != null) {  
  251.                 String[] proj = { MediaStore.Images.Media.DATA };  
  252.                 Cursor cursor = activity.managedQuery(imageuri, proj, nullnullnull);  
  253.                 int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);  
  254.                 if (cursor.moveToFirst()) {  
  255.                     path = cursor.getString(column_index);  
  256.                 }  
  257.             }  
  258.         }  
  259.         return path;  
  260.     }  
  261.   
  262.     /** 
  263.      * 压缩图片到指定大小 
  264.      *  
  265.      * @param srcPath 
  266.      *            返回压缩后图片路径 
  267.      * @param targetPath 
  268.      *            目标路径 
  269.      * @param maxSize 
  270.      *            图片允许最大空间 单位:KB(有一定的出入) 
  271.      * @return 成功返回true,否则返回false 
  272.      */  
  273.     private static boolean compressImage(String srcPath, String targetPath, int maxSize) {  
  274.         Bitmap bitmap = BitmapFactory.decodeFile(srcPath);  
  275.         if (bitmap == null)  
  276.             return false;  
  277.             bitmap = compressImage(bitmap, maxSize);  
  278.         try {  
  279.             File file = new File(targetPath);  
  280.             FileOutputStream out = new FileOutputStream(file);  
  281.             if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {  
  282.                 out.flush();  
  283.                 out.close();  
  284.             }  
  285.         } catch (FileNotFoundException e) {  
  286.             e.printStackTrace();  
  287.             return false;  
  288.         } catch (IOException e) {  
  289.             e.printStackTrace();  
  290.             return false;  
  291.         }  
  292.         return true;// 压缩好比例大小后再进行质量压缩  
  293.     }  
  294.   
  295.     /** 
  296.      * 压缩图片到指定大小 
  297.      *  
  298.      * @param bitmap 
  299.      *            源bitmap 
  300.      * @param maxSize 
  301.      *            图片允许最大空间 单位:KB 
  302.      * @return 
  303.      */  
  304.     private static Bitmap compressImage(Bitmap bitmap, int maxSize) {  
  305.         Bitmap resBitmap = bitmap;  
  306.         // 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)  
  307.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  308.         resBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
  309.         byte[] b = baos.toByteArray();  
  310.         // 将字节换成KB  
  311.         double mid = b.length / 1024;  
  312.         // 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩  
  313.         if (mid > maxSize) {  
  314.             // 获取bitmap大小 是允许最大大小的多少倍  
  315.             double i = mid / maxSize;  
  316.             // 开始执行缩放操作  
  317.             resBitmap = zoomImage(resBitmap, resBitmap.getWidth() / Math.sqrt(i), resBitmap.getHeight() / Math.sqrt(i));  
  318.         }  
  319.   
  320.         return resBitmap;  
  321.     }  
  322.   
  323.     /*** 
  324.      * 图片的缩放方法 
  325.      *  
  326.      * @param bgimage 
  327.      *            :源图片资源 
  328.      * @param newWidth 
  329.      *            :缩放后宽度 
  330.      * @param newHeight 
  331.      *            :缩放后高度 
  332.      * @return 
  333.      */  
  334.     private static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {  
  335.         // 获取这个图片的宽和高  
  336.         float width = bgimage.getWidth();  
  337.         float height = bgimage.getHeight();  
  338.         // 创建操作图片用的matrix对象  
  339.         Matrix matrix = new Matrix();  
  340.         // 计算宽高缩放率  
  341.         float scaleWidth = ((float) newWidth) / width;  
  342.         float scaleHeight = ((float) newHeight) / height;  
  343.         // 缩放图片动作  
  344.         matrix.postScale(scaleWidth, scaleHeight);  
  345.         Bitmap bitmap = Bitmap.createBitmap(bgimage, 00, (int) width, (int) height, matrix, true);  
  346.         return bitmap;  
  347.     }  
  348.   
  349.     /** 
  350.      *  
  351.      * @param context 
  352.      * @param resourcePath图片路径 
  353.      *  
  354.      */  
  355.     /** 
  356.      * 开始压缩图片线程 要上传图片放到回调里去处理 
  357.      *  
  358.      * @param resourcePath 
  359.      *            原图地址 
  360.      * @param maxSize 
  361.      *            压多大 单位是kb 
  362.      * @param icr 
  363.      *            回调接口 
  364.      */  
  365.     public void startCrompressImageTask(String resourcePath, int maxSize, ICompressResult icr) {  
  366.         CompressImageTask imageTask = new CompressImageTask(icr, maxSize);  
  367.         imageTask.execute(resourcePath);  
  368.     }  
  369.   
  370.     class CompressImageTask extends AsyncTask<String, Void, String> {  
  371.   
  372.         ICompressResult icr;  
  373.         int maxSize;  
  374.   
  375.         public CompressImageTask(ICompressResult icr, int maxSize) {  
  376.             this.icr = icr;  
  377.             this.maxSize = maxSize;  
  378.         }  
  379.   
  380.         @Override  
  381.         protected void onPostExecute(String result) {  
  382.             super.onPostExecute(result);  
  383.             AlertUtil.closeProgressDialog();  
  384.             if (result != null && icr != null) {  
  385.                 icr.onSuccus(result);  
  386.                 this.cancel(true);  
  387.             } else {  
  388.                 AlertUtil.showToast(mContext, "图片压缩失败");  
  389.             }  
  390.         }  
  391.   
  392.         @Override  
  393.         protected void onPreExecute() {  
  394.             super.onPreExecute();  
  395.             AlertUtil.showProgressDialog(mContext, """正在压缩图片...");  
  396.         }  
  397.   
  398.         @Override  
  399.         protected String doInBackground(String... params) {  
  400.             String path = params[0];  
  401.             if (path == null) {  
  402.                 return null// 裁剪失败  
  403.             }  
  404.             String compressPath = getCompressPath();  
  405.             boolean isSuccess = PictureActivityUtil.compressImage(path, compressPath, maxSize);  
  406.             if (isSuccess) {  
  407.                 return compressPath;  
  408.             }  
  409.             return null;  
  410.         }  
  411.   
  412.     }  
  413.   
  414.     private String getCompressPath() {  
  415.         return COMPRESS_IMAGE_TARGET_DIR + "compress_temp_" + System.currentTimeMillis() + ".jpg";  
  416.     }  
  417.   
  418.     /** 
  419.      * 获取图片裁剪路径 
  420.      *  
  421.      * @return 
  422.      */  
  423.     public static String getCropPath() {  
  424.         return CROP_IMAGE_TARGET_PATH + System.currentTimeMillis()+"_crop_temp.jpg";  
  425.     }  
  426.   
  427.     /** 
  428.      * 压缩回调接口 
  429.      *  
  430.      * @author summer 
  431.      *  
  432.      */  
  433.     public interface ICompressResult {  
  434.         /** 
  435.          * 压缩成功才调用该方法 
  436.          *  
  437.          * @param path 
  438.          *            压缩后的图片路径 
  439.          */  
  440.         void onSuccus(String path);  
  441.     }  
  442. }  
 

 

在activity里使用方法如下:

1.首先在public void onClick(View v) {      PictureActivityUtil.doPickPhotoAction(MeActivity.this);

}

调用选择弹窗截图如下:

2.回调的时候在

[java]  view plain copy
 
  1. protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  2.     super.onActivityResult(requestCode, resultCode, data);  
  3.     if (resultCode == RESULT_OK) {  
  4.         switch (requestCode) {  
  5.         case PictureActivityUtil.CAMERA_WITH_DATA: // 拍照返回  
  6.             PictureActivityUtil.doCropPhoto(this,  
  7.                     PictureActivityUtil.CAPTURE_IMAGE_TARGET_PATH);  
  8.             break;  
  9.         case PictureActivityUtil.PHOTO_PICKED_WITH_DATA: // 选择相册返回  
  10.             String path = PictureActivityUtil.getPickPhotoPath(this, data);  
  11.             PictureActivityUtil.doCropPhoto(this, path);  
  12.             break;  
  13.         case PictureActivityUtil.PHOTO_CROP: // 裁剪图片返回  
  14.             // 获取图片裁剪后路径  
  15.             String cropPath = Uri.parse(data.getAction()).getPath();  
  16.             showPic(cropPath);  
  17.             break;  
  18.         }  
  19.     }  
  20. }  


 

 

 

3.上传服务器代码如下:

/**
  * 上传文件至Server的方法并返回是否上传成功数据
  * 
  * @param uri
  *            服务器请求地址
  * @param netClass
  *            网络类型
  * @param filePath
  *            文件全路径
  * @param fileName
  *            文件名
  * @return
  */
 public static String uploadFileToWebServer(String uri, String netClass,
   String filePath, String fileName) {
  String end = "\r\n";
  String twoHyphens = "--";
  String boundary = "*****";
  String HTTPBody = "";
  try {
   URL url = new URL(uri);
   HttpURLConnection conn = null;
   if (netClass.indexOf("wap") >= 0) {
    String proxyIP = getWAPGatewayIP(netClass);
    Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP,
      new InetSocketAddress(proxyIP, 80));
    conn = (HttpURLConnection) url.openConnection(proxy);
   } else {
    conn = (HttpURLConnection) url.openConnection();
   }
   /* 允许Input、Output,不使用Cache */
   conn.setDoInput(true);
   conn.setDoOutput(true);
   conn.setUseCaches(false);
   /* 设置传送的method=POST */
   conn.setRequestMethod("POST");
   /* setRequestProperty */
   conn.setRequestProperty("Connection", "Keep-Alive");
   conn.setRequestProperty("Charset", "UTF-8");
   conn.setRequestProperty("Content-Type",
     "multipart/form-data;boundary=" + boundary);
   /* 设置DataOutputStream */
   DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
   ds.writeBytes(twoHyphens + boundary + end);
   ds.writeBytes("Content-Disposition: form-data; "
     + "name=\"uploadfile\";filename=\"" + fileName + "\"" + end);
   ds.writeBytes(end);

   /* 取得文件的FileInputStream */
   FileInputStream fStream = new FileInputStream(filePath);
   /* 设置每次写入1024bytes */
   int bufferSize = 1024;
   byte[] buffer = new byte[bufferSize];
   int length = -1;
   /* 从文件读取数据至缓冲区 */
   while ((length = fStream.read(buffer)) != -1) {
    /* 将资料写入DataOutputStream中 */
    ds.write(buffer, 0, length);
   }
   ds.writeBytes(end);
   ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
   /* close streams */
   fStream.close();
   ds.flush();
   // 读取返回信息
   InputStream in = conn.getInputStream();
   int ch = 0;
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   while ((ch = in.read()) != -1) {
    out.write(ch);
   }
   HTTPBody = out.toString();
   conn.disconnect();
   in.close();
   out.close();
  } catch (Exception e) {
   HTTPBody = "[数据错误]" + e.getMessage();
  }
  return HTTPBody;
 }

另外裁剪的代码可以参照android系统源码进行修改!我这儿整理了一个android 原生裁剪的代码库http://download.csdn.net/detail/xia296/8019117 下载导入到项目中可以直接使用,如果不需要集成到自己的代码中可以通过 调用插件的方式使用

Intent iintent = new Intent();
iintent.setClassName("com.wavefar.camera","com.wavefar.camera.CropImage"); 这种方式必须先要安装好该插件!

最后建议以下2种使用方式使用:

1、以外部引用的方式到自己项目工程中 。

2、copy相应文件到自己项目工程中。

 

注意:

有的android 3.0以上的系统默认开启了硬件加速,但裁剪函数里有的不支持,可能报UnsupportedOperationException异常!在注册清单文件里把 裁剪的activity 设置一个禁用硬件加速即可解决android:hardwareAccelerated="false"

猜你喜欢

转载自lishuaishuai.iteye.com/blog/2290935