android 根据uri获取路径及图片压缩、旋转的学习笔记

本文总结了Android中根据uri获取图片路径的问题,包括4.4前后URI格式的区别,处理拍照后uri可能为空的情况,以及解决拍照图片可能存在的旋转问题。提供了一个兼顾不同版本的工具类,并给出了处理图片旋转的思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<span style="font-family: Arial, Helvetica, sans-serif;">做项目用到了这些,根据uri取得图片或视频的路径,上传拍摄的照片,遇到的一些问题:</span>

1. 4.4以前和以后(含4.4)的URI格式不一样

2. 拍照后返回的URI有可能为null

3. 拍照后的图片有可能有旋转


一:URI格式问题

4.4以前:Uri : content://media/extenral/images/media/17766

 4.4及以后: content://com.android.providers.media.documents/document/image%2706

  解决,用一下的工具类即可解决此问题,此工具类兼顾了4.4以前及以后的版本,亲测可用:

@SuppressLint("NewApi")
	public static String getPath(final Context context, final Uri uri) {

		final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

		// DocumentProvider
		if (isKitKat && DocumentsContract.isDocumentUri(context, uri)){
			// ExternalStorageProvider
			if (isExternalStorageDocument(uri)){
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				if ("primary".equalsIgnoreCase(type)){
					return Environment.getExternalStorageDirectory() + "/" + split[1];
				}
			}
			// DownloadsProvider
			else if (isDownloadsDocument(uri)){

				final String id = DocumentsContract.getDocumentId(uri);
				final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

				return getDataColumn(context, contentUri, null, null);
			}
			// MediaProvider
			else if (isMediaDocument(uri)){
				final String docId = DocumentsContract.getDocumentId(uri);
				final String[] split = docId.split(":");
				final String type = split[0];

				Uri contentUri = null;
				if ("image".equals(type)){
					contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
				}
				else if ("video".equals(type)){
					contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
				}
				else if ("audio".equals(type)){
					contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
				}

				final String selection = "_id=?";
				final String[] selectionArgs = new String[] { split[1] };

				return getDataColumn(context, contentUri, selection, selectionArgs);
			}
		}
		// MediaStore (and general)
		else if ("content".equalsIgnoreCase(uri.getScheme())){
			return getDataColumn(context, uri, null, null);
		}
		// File
		else if ("file".equalsIgnoreCase(uri.getScheme())){
			return uri.getPath();
		}

		return null;
	}

	/**
	 * Get the value of the data column for this Uri. This is useful for
	 * MediaStore Uris, and other file-based ContentProviders. 
	 * @param context The context.
	 * @param uri The Uri to query.
	 * @param selection (Optional) Filter used in the query.
	 * @param selectionArgs (Optional) Selection arguments used in the query.
	 * @return The value of the _data column, which is typically a file path.
	 */
	public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {

		Cursor cursor = null;
		final String column = "_data";
		final String[] projection = { column };

		try{
			cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
			if (cursor != null && cursor.moveToFirst()){
				final int column_index = cursor.getColumnIndexOrThrow(column);
				return cursor.getString(column_index);
			}
		} finally{
			if (cursor != null)
				cursor.close();
		}
		return null;
	}

	/**
	 * @param uri  The Uri to check.
	 * @return Whether the Uri authority is ExternalStorageProvider.
	 */
	public static boolean isExternalStorageDocument(Uri uri) {
		return "com.android.externalstorage.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri  The Uri to check.
	 * @return Whether the Uri authority is DownloadsProvider.
	 */
	public static boolean isDownloadsDocument(Uri uri) {
		return "com.android.providers.downloads.documents".equals(uri.getAuthority());
	}

	/**
	 * @param uri The Uri to check.
	 * @return Whether the Uri authority is MediaProvider.
	 */
	public static boolean isMediaDocument(Uri uri) {
		return "com.android.providers.media.documents".equals(uri.getAuthority());
	}

二、拍照后返回的uri为null

  有些机型调用拍照后返回的data为空或取得的uri为null,解决思路:自己构造一个uri,判断获取的uri是否为空,若为空则赋值给它。

  首先,调用一下程序进行拍照:

 

<span style="white-space:pre">	</span>Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
	SimpleDateFormat timeStampFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
	String filename = timeStampFormat.format(new Date());
	ContentValues values = new ContentValues();
	values.put(Media.TITLE, filename);
	photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); //在程序里定义的变量
	intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
	startActivityForResult(intent, PAIZHAO);

在onActivityResult里面进行处理:

Uri uri = null;
if (data != null && data.getData() != null){
		uri = data.getData();
	}
	// 一些机型无法从getData中获取uri,则需手动指定拍照后存储照片的Uri
	if (uri == null){
		if (photoUri != null){
			uri = photoUri;
		}
	}

然后调用开始介绍的工具类即可取得图片的路径。


三、拍照后图片有旋转

有一些手机拍照后图片会有旋转,上传到服务器后显示会有问题。

解决思路,先获取图片选择角度:

	// 判断照片角度
	public static int readPictureDegree(String path) {
		int degree = 0;
		try{
			ExifInterface exifInterface = new ExifInterface(path);
			int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
			switch (orientation) {
			case ExifInterface.ORIENTATION_ROTATE_90:
				degree = 90;
				break;
			case ExifInterface.ORIENTATION_ROTATE_180:
				degree = 180;
				break;
			case ExifInterface.ORIENTATION_ROTATE_270:
				degree = 270;
				break;
			}
		} catch (IOException e){
			e.printStackTrace();
		}
		return degree;
	}
然后进行旋转:

	// 旋转照片
	public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
		if (bitmap != null){
			Matrix m = new Matrix();
			m.postRotate(degress);
			bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
			return bitmap;
		}
		return bitmap;
	}

利用下面的语句可对图像进行压缩:

File outputFile = new File(filePath);
FileOutputStream out = new FileOutputStream(outputFile);
bm.compress(Bitmap.CompressFormat.JPEG, q, out); //q为压缩率,0-100,越小图像压缩后质量越小,一般30以上不失真
//outputFile.getPath();可获取路径


-------------------------------------------------------------------------------------------------------------------------

以上内容非原创,是对网上内容的一个总结。

参考:

http://www.2cto.com/kf/201502/376975.html

http://blog.sina.com.cn/s/blog_4c7d14600101jhaf.html

http://blog.csdn.net/leechee_1986/article/details/25049243









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值