Android获取图片、裁剪、压缩、上传头像
2017-03-17 19:42
423 查看
上传方式为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(sharePreferenceUt 13675 il.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"; } } }
效果图:
相关文章推荐
- 在 Android 设备上获取照片、裁剪图片、压缩图片 @TakePhoto V3.0 发布
- Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案
- Android手机调用系统相机拍照、裁剪以及获取Url上传图片
- <android>头像上传,打开相册 —— 图片压缩——上传成功 (附三星手机适配图片旋转问题)
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- TakePhoto是一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库,目前最新版本3.0.0。
- Android开发之头像上传(包含拍照,从相册选择图片,裁剪等)
- Android上传头像,图片剪裁,压缩图片
- android 用户头像,图片裁剪,上传并附带用户数据base64code 方式
- Android上传头像,图片剪裁,压缩图片
- Android获取照片、裁剪图片、压缩图片
- Android上传头像,图片剪裁,压缩图片
- Android中相机拍摄照片,以及相册选择图片压缩上传(压缩后保存进SD中)(可用于修改头像等)
- Android设备上获取照片、裁剪图片、压缩图片
- Android实现类似QQ头像点击打开相册或者拍照,并获取裁剪后的图片
- react-native-image-picker在Android上闪退的解决办法(上传头像base64,压缩上传图片)
- 兼容SDK4.4(api19)拍照、相册选择图片裁剪压缩上传头像
- Android上传头像,图片剪裁,压缩图片
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- 一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库