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

还是那句话,最近项目比较忙拖了很久这篇文章终于完成了!

先看一下效果图:

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

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

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

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

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

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

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

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

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

下面简单铺一下代码:

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

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

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.avatarImg:// 更换头像点击事件
			menuWindow = new SelectPicPopupWindow(mContext, itemsOnClick);
			menuWindow.showAtLocation(findViewById(R.id.mainLayout),
					Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
			break;
		case R.id.loginBtn://登录按钮跳转事件
			startActivity(new Intent(mContext, UploadActivity.class));
			break;

		default:
			break;
		}
	}

弹出窗绑定一个按钮事件

	//为弹出窗口实现监听类
	private OnClickListener itemsOnClick = new OnClickListener() {
		@Override
		public void onClick(View v) {
			menuWindow.dismiss();
			switch (v.getId()) {
			// 拍照
			case R.id.takePhotoBtn:
				Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
				//下面这句指定调用相机拍照后的照片存储的路径
				takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,
						Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)));
				startActivityForResult(takeIntent, REQUESTCODE_TAKE);
				break;
			// 相册选择图片
			case R.id.pickPhotoBtn:
				Intent pickIntent = new Intent(Intent.ACTION_PICK, null);
				// 如果朋友们要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"
				pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
				startActivityForResult(pickIntent, REQUESTCODE_PICK);
				break;
			default:
				break;
			}
		}
	}; 

为图像选取返回的接收处理

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {

		switch (requestCode) {
		case REQUESTCODE_PICK:// 直接从相册获取
			try {
				startPhotoZoom(data.getData());
			} catch (NullPointerException e) {
				e.printStackTrace();// 用户点击取消操作
			}
			break;
		case REQUESTCODE_TAKE:// 调用相机拍照
			File temp = new File(Environment.getExternalStorageDirectory() + "/" + IMAGE_FILE_NAME);
			startPhotoZoom(Uri.fromFile(temp));
			break;
		case REQUESTCODE_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/*");
		// crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
		intent.putExtra("crop", "true");
		// aspectX aspectY 是宽高的比例
		intent.putExtra("aspectX", 1);
		intent.putExtra("aspectY", 1);
		// outputX outputY 是裁剪图片宽高
		intent.putExtra("outputX", 300);
		intent.putExtra("outputY", 300);
		intent.putExtra("return-data", true);
		startActivityForResult(intent, REQUESTCODE_CUTTING);
	}

	/**
	 * 保存裁剪之后的图片数据
	 * @param picdata
	 */
	private void setPicToView(Intent picdata) {
		Bundle extras = picdata.getExtras();
		if (extras != null) {
			// 取得SDCard图片路径做显示
			Bitmap photo = extras.getParcelable("data");
			Drawable drawable = new BitmapDrawable(null, photo);
			urlpath = FileUtil.saveFile(mContext, "temphead.jpg", photo);
			avatarImg.setImageDrawable(drawable);

			// 新线程后台上传服务端
			pd = ProgressDialog.show(mContext, null, "正在上传图片,请稍候...");
			new Thread(uploadImageRunnable).start();
		}
	}

	/**
	 * 使用HttpUrlConnection模拟post表单进行文件
	 * 上传平时很少使用,比较麻烦
	 * 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。
	 */
	Runnable uploadImageRunnable = new Runnable() {
		@Override
		public void run() {

			if(TextUtils.isEmpty(imgUrl)){
				Toast.makeText(mContext, "还没有设置上传服务器的路径!", Toast.LENGTH_SHORT).show();
				return;
			}

			Map<String, String> textParams = new HashMap<String, String>();
			Map<String, File> fileparams = new HashMap<String, File>();

			try {
				// 创建一个URL对象
				URL url = new URL(imgUrl);
				textParams = new HashMap<String, String>();
				fileparams = new HashMap<String, File>();
				// 要上传的图片文件
				File file = new File(urlpath);
				fileparams.put("image", file);
				// 利用HttpURLConnection对象从网络中获取网页数据
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				// 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)
				conn.setConnectTimeout(5000);
				// 设置允许输出(发送POST请求必须设置允许输出)
				conn.setDoOutput(true);
				// 设置使用POST的方式发送
				conn.setRequestMethod("POST");
				// 设置不使用缓存(容易出现问题)
				conn.setUseCaches(false);
				conn.setRequestProperty("Charset", "UTF-8");//设置编码
				// 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头
				conn.setRequestProperty("ser-Agent", "Fiddler");
				// 设置contentType
				conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + NetUtil.BOUNDARY);
				OutputStream os = conn.getOutputStream();
				DataOutputStream ds = new DataOutputStream(os);
				NetUtil.writeStringParams(textParams, ds);
				NetUtil.writeFileParams(fileparams, ds);
				NetUtil.paramsEnd(ds);
				// 对文件流操作完,要记得及时关闭
				os.close();
				// 服务器返回的响应吗
				int code = conn.getResponseCode(); // 从Internet获取网页,发送请求,将网页以流的形式读回来
				// 对响应码进行判断
				if (code == 200) {// 返回的响应码200,是成功
					// 得到网络返回的输入流
					InputStream is = conn.getInputStream();
					resultStr = NetUtil.readString(is);
				} else {
					Toast.makeText(mContext, "请求URL失败!", Toast.LENGTH_SHORT).show();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler
		}
	};

	Handler handler = new Handler(new Handler.Callback() {

		@Override
		public boolean handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				pd.dismiss();

				try {
					// 返回数据示例,根据需求和后台数据灵活处理
					// {"status":"1","statusMessage":"上传成功","imageUrl":"http://120.24.219.49/726287_temphead.jpg"}
					JSONObject jsonObject = new JSONObject(resultStr);

					// 服务端以字符串“1”作为操作成功标记
					if (jsonObject.optString("status").equals("1")) {
						BitmapFactory.Options option = new BitmapFactory.Options();
						// 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图,3为三分之一
						option.inSampleSize = 1;

						// 服务端返回的JsonObject对象中提取到图片的网络URL路径
						String imageUrl = jsonObject.optString("imageUrl");
						Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();
					}else{
						Toast.makeText(mContext, jsonObject.optString("statusMessage"), Toast.LENGTH_SHORT).show();
					}

				} catch (JSONException e) {
					e.printStackTrace();
				}

				break;

			default:
				break;
			}
			return false;
		}
	});

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

直接从这里开始,和头像那里基本没什么区别,我把拍照什么的单独抽出了方法,思路更清晰

	//为弹出窗口实现监听类
	private OnClickListener itemsOnClick = new OnClickListener() {
		@Override
		public void onClick(View v) {
			// 隐藏弹出窗口
			menuWindow.dismiss();

			switch (v.getId()) {
			case R.id.takePhotoBtn:// 拍照
				takePhoto();
				break;
			case R.id.pickPhotoBtn:// 相册选择图片
				pickPhoto();
				break;
			case R.id.cancelBtn:// 取消
				break;
			default:
				break;
			}
		}
	}; 
	/**
	 * 拍照获取图片
	 */
	private void takePhoto() {
		// 执行拍照前,应该先判断SD卡是否存在
		String SDState = Environment.getExternalStorageState();
		if (SDState.equals(Environment.MEDIA_MOUNTED)) {

			Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
			/***
			 * 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的
			 * 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图
			 * 如果不使用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰
			 */
			ContentValues values = new ContentValues();
			photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
			intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
			startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
		} else {
			Toast.makeText(this, "内存卡不存在", Toast.LENGTH_LONG).show();
		}
	}

	/***
	 * 从相册中取图片
	 */
	private void pickPhoto() {
		Intent intent = new Intent();
		// 如果要限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"
		intent.setType("image/*");
		intent.setAction(Intent.ACTION_GET_CONTENT);
		startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
	}

处理一下图片选取的页面回调

@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// 点击取消按钮
		if(resultCode == RESULT_CANCELED){
			return;
		}

		// 可以使用同一个方法,这里分开写为了防止以后扩展不同的需求
		switch (requestCode) {
		case SELECT_PIC_BY_PICK_PHOTO:// 如果是直接从相册获取
			doPhoto(requestCode, data);
			break;
		case SELECT_PIC_BY_TACK_PHOTO:// 如果是调用相机拍照时
			doPhoto(requestCode, data);
			break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

接下来就是显示图片和上传服务器了,上传和头像是同一个流程,只是不进行裁切

	/**
	 * 选择图片后,获取图片的路径
	 *
	 * @param requestCode
	 * @param data
	 */
	private void doPhoto(int requestCode, Intent data) {

		// 从相册取图片,有些手机有异常情况,请注意
		if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {
			if (data == null) {
				Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();
				return;
			}
			photoUri = data.getData();
			if (photoUri == null) {
				Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();
				return;
			}
		}

		String[] pojo = { MediaColumns.DATA };
		// The method managedQuery() from the type Activity is deprecated
		//Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
		Cursor cursor = mContext.getContentResolver().query(photoUri, pojo, null, null, null);
		if (cursor != null) {
			int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
			cursor.moveToFirst();
			picPath = cursor.getString(columnIndex);

			// 4.0以上的版本会自动关闭 (4.0--14;; 4.0.3--15)
			if (Integer.parseInt(Build.VERSION.SDK) < 14) {
				cursor.close();
			}
		}

		// 如果图片符合要求将其上传到服务器
		if (picPath != null && (	picPath.endsWith(".png") ||
									picPath.endsWith(".PNG") ||
									picPath.endsWith(".jpg") ||
									picPath.endsWith(".JPG"))) {

			BitmapFactory.Options option = new BitmapFactory.Options();
			// 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图
			option.inSampleSize = 1;
			// 根据图片的SDCard路径读出Bitmap
			Bitmap bm = BitmapFactory.decodeFile(picPath, option);
			// 显示在图片控件上
			picImg.setImageBitmap(bm);

			pd = ProgressDialog.show(mContext, null, "正在上传图片,请稍候...");
			new Thread(uploadImageRunnable).start();
		} else {
			Toast.makeText(this, "选择图片文件不正确", Toast.LENGTH_LONG).show();
		}

	}

	/**
	 * 使用HttpUrlConnection模拟post表单进行文件
	 * 上传平时很少使用,比较麻烦
	 * 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。
	 */
	Runnable uploadImageRunnable = new Runnable() {
		@Override
		public void run() {

			if(TextUtils.isEmpty(imgUrl)){
				Toast.makeText(mContext, "还没有设置上传服务器的路径!", Toast.LENGTH_SHORT).show();
				return;
			}

			Map<String, String> textParams = new HashMap<String, String>();
			Map<String, File> fileparams = new HashMap<String, File>();

			try {
				// 创建一个URL对象
				URL url = new URL(imgUrl);
				textParams = new HashMap<String, String>();
				fileparams = new HashMap<String, File>();
				// 要上传的图片文件
				File file = new File(picPath);
				fileparams.put("image", file);
				// 利用HttpURLConnection对象从网络中获取网页数据
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				// 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)
				conn.setConnectTimeout(5000);
				// 设置允许输出(发送POST请求必须设置允许输出)
				conn.setDoOutput(true);
				// 设置使用POST的方式发送
				conn.setRequestMethod("POST");
				// 设置不使用缓存(容易出现问题)
				conn.setUseCaches(false);
				// 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头
				conn.setRequestProperty("ser-Agent", "Fiddler");
				// 设置contentType
				conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + NetUtil.BOUNDARY);
				OutputStream os = conn.getOutputStream();
				DataOutputStream ds = new DataOutputStream(os);
				NetUtil.writeStringParams(textParams, ds);
				NetUtil.writeFileParams(fileparams, ds);
				NetUtil.paramsEnd(ds);
				// 对文件流操作完,要记得及时关闭
				os.close();
				// 服务器返回的响应吗
				int code = conn.getResponseCode(); // 从Internet获取网页,发送请求,将网页以流的形式读回来
				// 对响应码进行判断
				if (code == 200) {// 返回的响应码200,是成功
					// 得到网络返回的输入流
					InputStream is = conn.getInputStream();
					resultStr = NetUtil.readString(is);
				} else {
					Toast.makeText(mContext, "请求URL失败!", Toast.LENGTH_SHORT).show();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler
		}
	};

	Handler handler = new Handler(new Handler.Callback() {

		@Override
		public boolean handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				pd.dismiss();

				try {
					JSONObject jsonObject = new JSONObject(resultStr);
					// 服务端以字符串“1”作为操作成功标记
					if (jsonObject.optString("status").equals("1")) {

						// 用于拼接发布说说时用到的图片路径
						// 服务端返回的JsonObject对象中提取到图片的网络URL路径
						String imageUrl = jsonObject.optString("imageUrl");
						// 获取缓存中的图片路径
						Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();
					} else {
						Toast.makeText(mContext, jsonObject.optString("statusMessage"), Toast.LENGTH_SHORT).show();
					}

				} catch (JSONException e) {
					e.printStackTrace();
				}
				break;
			default:
				break;
			}
			return false;
		}
	});

最后放上完整的代码!大家上传路径自己搭建啊!

采集

采集

时间: 2024-10-08 21:17:40

Android图片上传(头像裁切+原图原样)的相关文章

Android 图片上传

上传方式:两种 1:Base64() (1):获取图片路径,将图片转为String 类型 (2):通过post提交的方式.以键值对的方式上传到服务器,和一般的提交关键字没有任何区别. (3):这种适用于图片少的时候使用. 转码代码如下: public class Base64Code { // constructor public Base64Code() { } /** * Encode image to Base64 string * @param srcPath * @return Bas

Android图片上传,可以选择多张图片,缩放预览,拍照上传等

仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 微信 下载地址 : 微信上传图片源码 //部分代码如下 [java] view plaincopy package com.king.photo.activity; import android.annotation.SuppressLint; import android.app.Activity

Android 图片上传 服务器端(一)

直接上浏览器端upload.jsp代码(为测试服务器端) <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/

android图片上传

package com.example.center; import java.io.ByteArrayOutputStream;import java.io.InputStream; import com.example.anuoc.R; import android.app.Activity;import android.app.AlertDialog;import android.content.ContentResolver;import android.content.DialogIn

Android图片上传到服务器的问题

============问题描述============ 我想实现微信朋友圈的发状态的功能,但是不知道应该怎么在服务器端建表.是建一个表统一存入用户名,发的文字,发的图片等信息吗?有人说SQL不适合存放图片.求前辈指导如何在服务器端建表,如何存储用户发的文字图片,感激不尽. ============解决方案1============ 文字可以直接存在数据库中,图片的话,只在数据库中存放图片的路径或索引就行了,而图片存在相应的路径下就是.

Android 图片上传 工具提交类(三)

大体部分与post提交类似,只是需要设置 <pre name="code" class="java">MultipartEntity 代码如下: public class userUploadServiceImpl implements userUploadService{ @Override public String userUpload(InputStream in, Map<String, String> data, String p

头像图片上传到sd及服务器

首先在AndroidManifest.xml设置权限: <!-- 传头像 --> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="

Android开发中使用七牛云存储进行图片上传下载

Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储原理,上面这幅图片是官方给出的原理图,表述当然比较清晰了.可以看出,要进行图片上传的话可以分为五大步: 1. 客户端用户登录到APP的账号系统里面: 2. 客户端上传文件之前,需要向业务服务器申请七牛的上传凭证,这个凭证由业务服务器使用七牛提供的服务端SDK生成: 3. 客户端使用七牛提供的客户端S

Android自定义动态布局 — 多图片上传

Android自定义动态布局 - 多图片上传 本文介绍Android中动态布局添加图片,多图片上传. 项目中效果图:    技术点: 1.动态添加格局中的线条和添加图片的+号 2.多张图片异步上传 首先来看一下布局文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layo