Android获取本地相册图片和拍照获取图片的实现方法

需求:从本地相册找图片,或通过调用系统相机拍照得到图片。

容易出错的地方:

1、当我们指定了照片的uri路径,我们就不能通过data.getData();来获取uri,而应该直接拿到uri(用全局变量或者其他方式)然后设置给imageView

imageView.setImageURI(uri);

2、我发现手机前置摄像头拍出来的照片只有几百KB,直接用imageView.setImageURI(uri);没有很大问题,但是后置摄像头拍出来的照片比较大,这个时候使用imageView.setImageURI(uri);就容易出现 out of memory(oom)错误,我们需要先把URI转换为Bitmap,再压缩bitmap,然后通过imageView.setImageBitmap(bitmap);来显示图片。

3、将照片存放到SD卡中后,照片不能立即出现在系统相册中,因此我们需要发送广播去提醒相册更新照片。

4、这里用到了sharepreference,要注意用完之后移除缓存。

代码:

MainActivity:

package com.sctu.edu.test; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.ImageView; import com.sctu.edu.test.tools.ImageTools; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class MainActivity extends AppCompatActivity { private static final int PHOTO_FROM_GALLERY = 1; private static final int PHOTO_FROM_CAMERA = 2; private ImageView imageView; private File appDir; private Uri uriForCamera; private Date date; private String str = ""; private SharePreference sharePreference; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Android不推荐使用全局变量,我在这里使用了sharePreference sharePreference = SharePreference.getInstance(this); imageView = (ImageView) findViewById(R.id.imageView); } //从相册取图片 public void gallery(View view) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(intent, PHOTO_FROM_GALLERY); } //拍照取图片 public void camera(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); uriForCamera = Uri.fromFile(createImageStoragePath()); sharePreference.setCache("uri", String.valueOf(uriForCamera)); /** * 指定了uri路径,startActivityForResult不返回intent, * 所以在onActivityResult()中不能通过data.getData()获取到uri; */ intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForCamera); startActivityForResult(intent, PHOTO_FROM_CAMERA); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //第一层switch switch (requestCode) { case PHOTO_FROM_GALLERY: //第二层switch switch (resultCode) { case RESULT_OK: if (data != null) { Uri uri = data.getData(); imageView.setImageURI(uri); } break; case RESULT_CANCELED: break; } break; case PHOTO_FROM_CAMERA: if (resultCode == RESULT_OK) { Uri uri = Uri.parse(sharePreference.getString("uri")); updateDCIM(uri); try { //把URI转换为Bitmap,并将bitmap压缩,防止OOM(out of memory) Bitmap bitmap = ImageTools.getBitmapFromUri(uri, this); imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } removeCache("uri"); } else { Log.e("result", "is not ok" + resultCode); } break; default: break; } } /** * 设置相片存放路径,先将照片存放到SD卡中,再操作 * * @return */ private File createImageStoragePath() { if (hasSdcard()) { appDir = new File("/sdcard/testImage/"); if (!appDir.exists()) { appDir.mkdirs(); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); date = new Date(); str = simpleDateFormat.format(date); String fileName = str + ".jpg"; File file = new File(appDir, fileName); return file; } else { Log.e("sd", "is not load"); return null; } } /** * 将照片插入系统相册,提醒相册更新 * * @param uri */ private void updateDCIM(Uri uri) { Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(uri); this.sendBroadcast(intent); Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath()); MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "", ""); } /** * 判断SD卡是否可用 * * @return */ private boolean hasSdcard() { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return true; } else { return false; } } /** * 移除缓存 * * @param cache */ private void removeCache(String cache) { if (sharePreference.ifHaveShare(cache)) { sharePreference.removeOneCache(cache); } else { Log.e("this cache", "is not exist."); } } }

ImageTools:

package com.sctu.edu.test.tools; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; public class ImageTools { /** * 通过uri获取图片并进行压缩 * * @param uri * @param activity * @return * @throws IOException */ public static Bitmap getBitmapFromUri(Uri uri, Activity activity) throws IOException { InputStream inputStream = activity.getContentResolver().openInputStream(uri); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; options.inDither = true; options.inPreferredConfig = Bitmap.Config.ARGB_8888; BitmapFactory.decodeStream(inputStream, null, options); inputStream.close(); int originalWidth = options.outWidth; int originalHeight = options.outHeight; if (originalWidth == -1 || originalHeight == -1) { return null; } float height = 800f; float width = 480f; int be = 1; //be=1表示不缩放 if (originalWidth > originalHeight && originalWidth > width) { be = (int) (originalWidth / width); } else if (originalWidth < originalHeight && originalHeight > height) { be = (int) (originalHeight / height); } if (be <= 0) { be = 1; } BitmapFactory.Options bitmapOptinos = new BitmapFactory.Options(); bitmapOptinos.inSampleSize = be; bitmapOptinos.inDither = true; bitmapOptinos.inPreferredConfig = Bitmap.Config.ARGB_8888; inputStream = activity.getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, bitmapOptinos); inputStream.close(); return compressImage(bitmap); } /** * 质量压缩方法 * * @param bitmap * @return */ public static Bitmap compressImage(Bitmap bitmap) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); int options = 100; while (byteArrayOutputStream.toByteArray().length / 1024 > 100) { byteArrayOutputStream.reset(); //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流 bitmap.compress(Bitmap.CompressFormat.JPEG, options, byteArrayOutputStream); options -= 10; } ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); Bitmap bitmapImage = BitmapFactory.decodeStream(byteArrayInputStream, null, null); return bitmapImage; } }

AndroidMainfest.xml:

<?xml version="1.0" encoding="utf-8"?> <manifest package="com.sctu.edu.test" xmlns:android="http://schemas.android.com/apk/res/android"> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="com.miui.whetstone.permission.ACCESS_PROVIDER"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-feature android:name="android.hardware.camera.autofocus" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff" android:orientation="vertical" tools:context="com.sctu.edu.test.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="从图库找图片" android:id="@+id/gallery" android:onClick="gallery" android:background="#ccc" android:textSize="20sp" android:padding="10dp" android:layout_marginLeft="30dp" android:layout_marginTop="40dp" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照获取图片" android:id="@+id/camera" android:onClick="camera" android:background="#ccc" android:textSize="20sp" android:padding="10dp" android:layout_marginLeft="30dp" android:layout_marginTop="40dp" /> <ImageView android:layout_width="300dp" android:layout_height="300dp" android:id="@+id/imageView" android:scaleType="fitXY" android:background="@mipmap/ic_launcher" android:layout_marginTop="40dp" android:layout_marginLeft="30dp" /> </LinearLayout>

效果图:

或许有人会问,在Android6.0上面怎么点击拍照就出现闪退,那是因为我设置的最高SDK版本大于23,而我现在还没对运行时权限做处理,也许我会在下一篇博客里处理这个问题。谢谢浏览,希望对你有帮助!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-10-24 19:28:47

Android获取本地相册图片和拍照获取图片的实现方法的相关文章

Android中从SD卡中/拍照选择图片并进行剪裁的方法

类似QQ头像选择的一个功能,让用户从手机图片或者自己拍照并图图像大小剪裁之后选择,当时觉得很实用,但是自己不知道怎么实现.最近参考同事写的代码并自己在网上查阅了相关信息,发现大概都是同样的方式,自己简单整合了一下,可以实现基本的功能,至于上传方面还没有深入研究. 效果图:     下面是代码的部分,部分是从网路上摘录的,自己整理后当做工具类使用   配置文件:布局很简单,一个ImageButton和一个Button,点击都可以实现图像选择的功能,具体的实现根据大家在实际中用的效果而定 -----

Asp.Net获取本地计算机和其他计算机的MAC值的方法

asp.net Public Function ValueSepR(ByVal RawString As String, ByVal SepChar As String) As String If InStr(1, RawString, SepChar) <> 0 Then ValueSepR = Microsoft.VisualBasic.Right(RawString,Len(RawString) - InStr(1, RawString, SepChar)) Else ValueSepR

获取三星手机本地相册图片时,如何解决图片的旋转问题

问题描述 获取三星手机本地相册图片时,如何解决图片的旋转问题 用SharePhoto获取本地相册图片时,三星手机显示的图片总是被旋转90度,如何在获取本地图片的时候直接显示正常的图样,求帮忙大神解答 解决方案 解决三星手机拍照后裁剪图片时横屏问题三星等手机拍照选取图片,图片反转的问题 解决方案二: 你是不是把图片的文件名写成.png了?改成.jpg试试.JPEG图片里面Exif字段存储图片方便,下面这个方法你可以参考一下 public static int getCameraPhotoOrien

Android优化查询加载大数量的本地相册图片_Android

一.概述 讲解优化查询相册图片之前,我们先来看下PM提出的需求,PM的需求很简单,就是要做一个类似微信的本地相册图片查询控件,主要包含两个两部分: 进入图片选择页面就要显示出手机中所有的照片,包括系统相册图片和其他目录下的所有图片,并按照时间倒叙排列 切换相册功能,切换相册页面列出手机中所有的图片目录列表,并且显示出每个目录下所有的图片个数以及封面图片 这两个需求看似简单,实则隐藏着一系列的性能优化问题.在做优化之前,我们调研了一些其他比较出名的app在加载大数量图片的性能表现(gif录制的不够

Android通过手机拍照或从本地相册选取图片设置头像

像微信.QQ.微博等社交类的APP,通常都有设置头像的功能,设置头像通常有两种方式: 1.让用户通过选择本地相册之类的图片库中已有的图像,裁剪后作为头像. 2.让用户启动手机的相机拍照,拍完照片后裁剪,然后作为头像. 我现在写一个简单的完整代码例子,说明如何在android中实现上述两个头像设置功能. MainActivity.Java文件: package zhangpgil.photo; import java.io.File; import android.support.v7.app.A

解决AssetsLibrary无法获取本地所有相册

        本地有两个相册:相机胶卷和照片图库.后者是通过同步产生的. dispatch_async(dispatch_get_main_queue(), ^{ [_assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock: ^(ALAssetsGroup *group, BOOL *stop) { if (group) { [self.groupArray addObject:group]; [self perfo

iOS中获取系统相册中的图片实例_IOS

本文介绍了iOS中获取系统相册中的图片,在很多应用中都能用到,可以获取单张图片,也可以同时获取多张图片,废话不多说了,看下面吧. 一.获取单张图片 思路: 1.利用UIImagePickerController可以从系统自带的App(照片\相机)中获得图片 2.设置代理,遵守代理协议 注意这个UIImagePickerController类比较特殊,需要遵守两个代理协议 @interface ViewController () <UIImagePickerControllerDelegate,

Android中通过访问本地相册或者相机设置用户头像实例

目前几乎所有的APP在用户注册时都会有设置头像的需求,大致分为三种情况: (1)通过获取本地相册的图片,经过裁剪后作为头像. (2)通过启动手机相机,现拍图片然后裁剪作为头像. (3)在APP中添加一些自带的头像资源,供用户选择(不够人性化,目前很少使用). 这次我们简单介绍下通过获取本地相册以及相机拍摄的方法设置头像,实现思路如下: (1)通过startActivityForResult方法,分别传递调用系统相册的Intent和调用相机拍照的Intent来做选择 (2)调用Android系统中

Android拍照裁剪图片

下面是效果图,看看是不是亲想要的效果图,如果是,这段代码你就可以参考下了,但是要灵活运用,根据需求做相应的改动. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation