Android获取图片、裁剪、压缩、上传头像

上传方式为post,上传图片格式为multipart/form-data

自己在做毕设找了很多方法,但是没有找到一个符合我需求的,最后自己汇总了一下大家的方法,集成为我需要的方式

布局文件(自定义的原型头像):

<com.example.ff.bishe2.ui.CircleImageView
            android:id="@+id/civ_information"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:src="@drawable/ic_mine_head"
            android:layout_margin="15dp"/>

Activity(这个activity还有一些其他的功能,所以有一些多余的代码):

public class InformationActivity extends AppCompatActivity implements View.OnClickListener {
    private View view;
    private TextView tvBack, tvName, tvPhone, tvAddress;
    private LinearLayout ll_popup;
    private LinearLayout llHead, llName, llPhone, llAddress;
    private SharePreferenceUtil sharePreferenceUtil;
    private String userid;

    //下面这些变量是与题目有关的
    private File photoFile;  //存放图片文件,最后是上传这个file
    private CircleImageView civInformation;  //头像控件
    private PopUtil pop;  //弹出框,选择是从相册选择还是拍照
    protected LoadingDialog loadingDialog;  //上传如果延迟的话,会显示一个不停转圈的dialog
    private PictureCutUtil pictureCutUtil;   //图片压缩工具
    private String filename = System.currentTimeMillis() + ".png"; //如果拍照的话会存放在一个临时文件,所以文件名也是随时生成,以免混淆
    public final static int CONSULT_DOC_PICTURE = 1000;  //相册
    public final static int CONSULT_DOC_CAMERA = 1001;  //拍照
    public final static int CONSULT_DOC_CUTTING = 1002;  //裁剪
    private Uri outputFileUri;  //拍照获得的图片的uri

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        view = getLayoutInflater().inflate(R.layout.activity_information, null);
        setContentView(view);

        initView();
        initPop();

    }

    //初始化view
    private void initView() {
        if (loadingDialog == null) {
            loadingDialog = new LoadingDialog(this, R.style.DialogTheme);
        }
        pictureCutUtil = new PictureCutUtil(this);
        tvBack = (TextView) findViewById(R.id.tv_information_back);
        tvName = (TextView) findViewById(R.id.tv_information_name);
        tvPhone = (TextView) findViewById(R.id.tv_information_phone);
        tvAddress = (TextView) findViewById(R.id.tv_information_address);
        civInformation = (CircleImageView) findViewById(R.id.civ_information);

        llHead = (LinearLayout) findViewById(R.id.ll_information_head);
        llName = (LinearLayout) findViewById(R.id.ll_information_name);
        llPhone = (LinearLayout) findViewById(R.id.ll_information_phone);
        llAddress = (LinearLayout) findViewById(R.id.ll_information_address);

        tvBack.setOnClickListener(this);
        llHead.setOnClickListener(this);
        llName.setOnClickListener(this);
        llPhone.setOnClickListener(this);
        llAddress.setOnClickListener(this);
    }

    //初始化弹出框
    private void initPop() {
        pop = new PopUtil(InformationActivity.this, R.layout.item_popupwindows, false);
        ll_popup = pop.getLl_popup();

        TextView bt1 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_camera);//拍照
        TextView bt2 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_Photo);//从相册中选择
        TextView bt3 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_cancel);//取消

        bt1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                File file = new File(Environment.getExternalStorageDirectory(), filename);
                outputFileUri = Uri.fromFile(file);
                Intent intentPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intentPhoto.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                startActivityForResult(intentPhoto, CONSULT_DOC_CAMERA);
                overridePendingTransition(R.anim.translate_bottom_in, R.anim.translate_nomal);
                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
        bt2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");
                startActivityForResult(Intent.createChooser(intent, "选择图片"), CONSULT_DOC_PICTURE);
                overridePendingTransition(R.anim.translate_bottom_in, R.anim.translate_nomal);
                pop.dismiss();
                ll_popup.clearAnimation();
            }
        });
        bt3.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                pop.dismiss();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        initData();
    }
    //做一些数据初始化,与我们讨论的东西无关
    private void initData() {
        sharePreferenceUtil = new SharePreferenceUtil(this);
        civInformation.setImageBitmap(sharePreferenceUtil.getImg(BitmapFactory.decodeResource(getResources(), R.drawable.ic_mine_head)));
        tvName.setText(sharePreferenceUtil.getUsername());
        tvPhone.setText(sharePreferenceUtil.getPhone());
        tvAddress.setText(sharePreferenceUtil.getAddress());
        userid = sharePreferenceUtil.getUserID();
    }

    //在弹出框中选择不同选项,在这里处理返回方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){

            case CONSULT_DOC_PICTURE: //相册选择

                uriphoto = data.getData();  //图片已经存在,所以data中就是图片的uri
                try {
                      startPhotoZoom(data.getData());  //头像一般都要裁剪

                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;

            case CONSULT_DOC_CAMERA:  //拍照
                if (outputFileUri != null) {
                    startPhotoZoom(outputFileUri);  //裁剪
                }
                break;

            case CONSULT_DOC_CUTTING:  //裁剪完之后,压缩保存并上传
                if (data != null) {
                    setPicToView(data);
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * 裁剪图片方法实现
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        // 设置裁剪
        intent.putExtra("crop", "true");
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 320);
        intent.putExtra("outputY", 320);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, CONSULT_DOC_CUTTING);  //返回去
    }

    //裁剪之后的图片不能放回原地址,所以要存放在一个临时file中再上传
    private void setPicToView(Intent data) {
        Bundle extras = data.getExtras();
        if (extras != null) {
            // 取得SDCard图片路径做显示
            Bitmap photo = extras.getParcelable("data");
            sharePreferenceUtil.setImg(photo); //我用sharePreference保存图片

            photoFile = pictureCutUtil.cutPictureQuality(photo, "ff");  //压缩并保存
            if (loadingDialog != null) {  //上传可能要延迟,先弹出等待框
                loadingDialog.show();
            }
            postIcon(); //上传
        }
    }


    //新建子线程上传头像,返回数据提交给handler刷新ui
    private void postIcon() { 
        Thread t = new Thread() {
            @Override
            public void run() {
                String url = "http://119.29.173.118/api/User/SetUserIcon?userid=" + userid;
                String response = UploadImage.uploadFile(photoFile, url);  //方法后面给出

                Message msg = new Message();
                msg.obj = response;
                msg.what= 1;
                handler.sendMessage(msg);
            }
        };
        t.start();
    }

    // 此方法在主线程中调用,可以更新UI
    Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            // 处理消息时需要知道是成功的消息还是失败的消息
            if (!isFinishing()) loadingDialog.dismiss(); //上传返回后,等待框消失
            switch (msg.what) {
                case 1:
                    Toast.makeText(InformationActivity.this, msg.obj.toString() , Toast.LENGTH_LONG).show();
                    break;
                case 0:
                    Toast.makeText(InformationActivity.this, "请求失败", Toast.LENGTH_LONG).show();
                    break;
                default:
                    break;
            }

        }
    };



    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_information_back:
                finish();
                break;
            case R.id.ll_information_head:
                pop.showAtLocation(view, Gravity.BOTTOM, 0, 0);
                break;
            case R.id.ll_information_name:
                IntentUtils.turnTo(InformationActivity.this, NameActivity.class, false);
                break;
            case R.id.ll_information_phone:
                IntentUtils.turnTo(InformationActivity.this, PhoneActivity.class, false);
                break;
            case R.id.ll_information_address:
                IntentUtils.turnTo(InformationActivity.this, AddressActivity.class, false);
                break;
        }
    }
}

PopUtil弹出框:

public class PopUtil extends PopupWindow {
    private AutoLinearLayout ll_popup;
    private long mLastTime = -1;
    private boolean isAnimation;
    private Activity activity;
    private int layout;
    private View bgview;
    private View view;

    public PopUtil(Activity activity, int layout, boolean isAnimation) {
        this.activity = activity;
        this.layout = layout;
        this.isAnimation = isAnimation;
        initPop();
    }

    public AutoLinearLayout getLl_popup() {
        return ll_popup;
    }

    public View getview() {
        return view;
    }

    public void initPop() {
        view = activity.getLayoutInflater().inflate(layout, null);
//      pop = new PopupWindow();
        ll_popup = (AutoLinearLayout) view.findViewById(R.id.ll_popup);

        setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        setBackgroundDrawable(new BitmapDrawable());
        setFocusable(true);
        setOutsideTouchable(true);
        setContentView(view);
//      setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(R.color.black)));

        bgview = ll_popup.findViewById(R.id.view);
        bgview.setAlpha(0.5f);
//      消失的时候设置窗体背景变亮
//      setOnDismissListener(new PopupWindow.OnDismissListener() {
//      @Override
//      public void onDismiss() {
//      }
//      });

        ll_popup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
//                if (isAnimation){
//                    endAnimationPopup(getAnimation());
//                }
            }
        });
    }

    public Animation getAnimation() {
        final Animation endAnimation = AnimationUtils.loadAnimation(activity, R.anim.translate_bottom_out);
        endAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                dismiss();

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        return endAnimation;
    }

    @Override
    public void showAtLocation(View parent, int gravity, int x, int y) {
        super.showAtLocation(parent, gravity, x, y);
//       backgroundAlpha(0.5f);
//       bgview.setVisibility(View.VISIBLE);

    }

    /**
     * 防止重复点击关闭pop动画
     *
     * @param endAnimation
     */
    public void endAnimationPopup(Animation endAnimation) {
        if (mLastTime == -1) {
            ll_popup.startAnimation(endAnimation);
        } else {
            long currentTimeMillis = System.currentTimeMillis();
            long interval = currentTimeMillis - mLastTime;
            if (interval < 300) {
                return;
            } else {
                ll_popup.startAnimation(endAnimation);
            }
        }
        mLastTime = System.currentTimeMillis();
    }

    @Override
    public void dismiss() {
        super.dismiss();
//        backgroundAlpha(1f);
    }

    /**
     * 设置添加屏幕的背景透明度
     *
     * @param bgAlpha
     */
    public void backgroundAlpha(float bgAlpha) {
        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.alpha = bgAlpha; //0.0-1.0
        activity.getWindow().setAttributes(lp);
    }
}

Pop的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<com.zhy.autolayout.AutoLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_popup"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/transparent"
    android:fitsSystemWindows="false"
    android:orientation="vertical">

    <View
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/black"></View>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/grayEFEFEF" />

    <TextView
        android:id="@+id/item_popupwindows_camera"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:gravity="center"
        android:padding="20px"
        android:text="拍照"
        android:textColor="@color/gray585858"
        android:textSize="16sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/grayEFEFEF" />


    <TextView
        android:id="@+id/item_popupwindows_Photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:gravity="center"
        android:padding="20px"
        android:text="从相册中选取"
        android:textColor="@color/gray585858"
        android:textSize="16sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/grayf3f3f3" />

    <TextView
        android:id="@+id/item_popupwindows_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:gravity="center"
        android:padding="20px"
        android:text="取消"
        android:textColor="@color/gray585858"
        android:textSize="16sp" />

</com.zhy.autolayout.AutoLinearLayout>

PictureCutUtil图片工具类:

public class PictureCutUtil {
    private File temp;
    private Context context;

    /**
     * 构造器
     *
     * @param context
     */
    public PictureCutUtil(Context context) {
        this.context = context;
    }

    /**
     * 计算图片的缩放值
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    private int cutBySize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }

    /**
     * 根据路径获得图片并压缩返回bitmap
     *
     * @param filePath
     * @return
     */
    public Bitmap cutPictureSize(String filePath) {

        Display mDisplay = ((Activity) context).getWindowManager().getDefaultDisplay();
        int width = mDisplay.getWidth();
        int height = mDisplay.getHeight();

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        options.inSampleSize = cutBySize(options, width, height);
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(filePath, options);
    }

    /**
     * 存储图片
     *
     * @param bitmap
     * @param savePackage
     * @return
     */
    public File cutPictureQuality(Bitmap bitmap, String savePackage) {

        String fileName = UUID.randomUUID().toString().replace("-","") + ".png";
        String filePath = Environment.getExternalStorageDirectory() + File.separator + savePackage;
        // 判断文件夹存在
        File file = new File(filePath);
        if (file != null && !file.exists()) {
            file.mkdirs();
        }

        try {

            // 第一次压缩
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            temp = new File(filePath, fileName);
            FileOutputStream fos = new FileOutputStream(temp);

            int options = 100;
            // 如果大于150kb则再次压缩,最多压缩三次
            while (baos.toByteArray().length / 1024 > 150 && options != 10) {
                // 清空baos
                baos.reset();
                // 这里压缩options%,把压缩后的数据存放到baos中
                bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
                options -= 30;
            }
            fos.write(baos.toByteArray());
            fos.close();
            baos.close();

        } catch (Exception e) {
        }
        return temp;
    }
}

上传头像UploadImage(post方式,multipart/form-data格式):

public class UploadImage {
    private static final String TAG = "uploadFile";
    private static final int TIME_OUT = 10*10000000; //超时时间
    private static final String CHARSET = "utf-8"; //设置编码
    private static final String BOUNDARY = "FlPm4LpSXsE" ; //UUID.randomUUID().toString(); //边界标识 随机生成 String PREFIX = "--" , LINE_END = "\r\n";
    private static final String PREFIX="--";
    private static final String LINE_END="\r\n";
    private static final String CONTENT_TYPE = "multipart/form-data"; //内容类型

    /** * android上传文件到服务器
     * @param file 需要上传的文件
     * @param requestURL 请求的rul
     * @return 返回响应的内容
     */
    public static String uploadFile(File file, String requestURL) {
        try {
            URL url = new URL(requestURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(TIME_OUT);
            conn.setConnectTimeout(TIME_OUT);
            conn.setDoInput(true); //允许输入流
            conn.setDoOutput(true); //允许输出流
            conn.setUseCaches(false); //不允许使用缓存
            conn.setRequestMethod("POST"); //请求方式
            conn.setRequestProperty("Charset", CHARSET);//设置编码
            //头信息

            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            if(file!=null) {
                /** * 当文件不为空,把文件包装并且上传 */
                OutputStream outputSteam=conn.getOutputStream();
                DataOutputStream dos = new DataOutputStream(outputSteam);

                StringBuffer sb = new StringBuffer();
                sb.append(PREFIX);
                sb.append(BOUNDARY);
                sb.append(LINE_END);

                sb.append("Content-Disposition: form-data; name=\"file\";filename=" + "\"" + file.getName() + "\"" + LINE_END);
                sb.append("Content-Type: image/jpg"+LINE_END);
                sb.append(LINE_END);
                dos.write(sb.toString().getBytes());
                //读取文件的内容
                InputStream is = new FileInputStream(file);
                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());
                //写入end data
                byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes();
                dos.write(end_data);
                dos.flush();
                /**
                 * 获取响应码 200=成功
                 * 当响应成功,获取响应的流
                 */
                int res = conn.getResponseCode();
                if(res==200) {
                    String oneLine;
                    StringBuffer response = new StringBuffer();
                    BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    while ((oneLine = input.readLine()) != null) {
                        response.append(oneLine);
                    }
                    return response.toString();
                }else{
                    return ""+res;
                }
            }else{
                return "file not found";
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return "Malformed failed";
        } catch (IOException e) {
            e.printStackTrace();
            return "IO failed";
        }
    }

}

效果图:


这里写图片描述
这里写图片描述
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值