Android獲取本地相冊(cè)圖片和拍照獲取圖片的實(shí)現(xiàn)方法
需求:從本地相冊(cè)找圖片,或通過(guò)調(diào)用系統(tǒng)相機(jī)拍照得到圖片。
容易出錯(cuò)的地方:
1、當(dāng)我們指定了照片的uri路徑,我們就不能通過(guò)data.getData();來(lái)獲取uri,而應(yīng)該直接拿到uri(用全局變量或者其他方式)然后設(shè)置給imageView
imageView.setImageURI(uri);
2、我發(fā)現(xiàn)手機(jī)前置攝像頭拍出來(lái)的照片只有幾百KB,直接用imageView.setImageURI(uri);沒有很大問(wèn)題,但是后置攝像頭拍出來(lái)的照片比較大,這個(gè)時(shí)候使用imageView.setImageURI(uri);就容易出現(xiàn) out of memory(oom)錯(cuò)誤,我們需要先把URI轉(zhuǎn)換為Bitmap,再壓縮bitmap,然后通過(guò)imageView.setImageBitmap(bitmap);來(lái)顯示圖片。
3、將照片存放到SD卡中后,照片不能立即出現(xiàn)在系統(tǒng)相冊(cè)中,因此我們需要發(fā)送廣播去提醒相冊(cè)更新照片。
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); } //從相冊(cè)取圖片 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()中不能通過(guò)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轉(zhuǎn)換為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; } } /** * 設(shè)置相片存放路徑,先將照片存放到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; } } /** * 將照片插入系統(tǒng)相冊(cè),提醒相冊(cè)更新 * * @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 { /** * 通過(guò)uri獲取圖片并進(jìn)行壓縮 * * @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); } /** * 質(zhì)量壓縮方法 * * @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(); //第一個(gè)參數(shù) :圖片格式 ,第二個(gè)參數(shù): 圖片質(zhì)量,100為最高,0為最差 ,第三個(gè)參數(shù):保存壓縮后的數(shù)據(jù)的流 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="從圖庫(kù)找圖片" 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>
效果圖:
或許有人會(huì)問(wèn),在Android6.0上面怎么點(diǎn)擊拍照就出現(xiàn)閃退,那是因?yàn)槲以O(shè)置的最高SDK版本大于23,而我現(xiàn)在還沒對(duì)運(yùn)行時(shí)權(quán)限做處理,也許我會(huì)在下一篇博客里處理這個(gè)問(wèn)題。謝謝瀏覽,希望對(duì)你有幫助!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 基于Android實(shí)現(xiàn)保存圖片到本地并可以在相冊(cè)中顯示出來(lái)
- android獲取相冊(cè)圖片和路徑的實(shí)現(xiàn)方法
- android照相、相冊(cè)獲取圖片剪裁報(bào)錯(cuò)的解決方法
- 解決Android從相冊(cè)中獲取圖片出錯(cuò)圖片卻無(wú)法裁剪問(wèn)題的方法
- Android實(shí)現(xiàn)讀取相機(jī)(相冊(cè))圖片并進(jìn)行剪裁
- android中打開相機(jī)、打開相冊(cè)進(jìn)行圖片的獲取示例
- Android實(shí)現(xiàn)保存圖片到本地并在相冊(cè)中顯示
- Android實(shí)現(xiàn)長(zhǎng)按圖片保存至相冊(cè)功能
- Android 圖片存儲(chǔ)到指定路徑和相冊(cè)的方法
- Android實(shí)現(xiàn)選擇相冊(cè)圖片并顯示功能
相關(guān)文章
Android?ViewPager你可能不知道的刷新操作分享
這篇文章主要為大家詳細(xì)介紹了Android中ViewPager你可能不知道的刷新操作,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下2023-05-05Kotlin?LinearLayout與RelativeLayout布局使用詳解
Kotlin?的基本特性就先寫到這里,我們這個(gè)系列的定位是基礎(chǔ),也就是能用就好,夠用就好,我們不會(huì)舉太多的例子,但是這些都是最經(jīng)常用到的特性。從這節(jié)開始就是Kotlin和android?進(jìn)行結(jié)合,使用Kotlin進(jìn)行安卓應(yīng)用的開發(fā)了2022-12-12Android單元測(cè)試之對(duì)Activity的測(cè)試示例
本篇文章主要介紹了Android單元測(cè)試之對(duì)Activity的測(cè)試示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08java,Android:在eclipse中的快捷鍵(經(jīng)典收藏)
下面的快捷鍵是常用的,本人就本身喜好且常用的收拾一下,現(xiàn)在曬出來(lái)與大家分享,感興趣的朋友可以了解小哦2013-01-01使用Eclipse配置android開發(fā)環(huán)境教程
這篇文章主要介紹了使用Eclipse配置android開發(fā)環(huán)境教程,本文講解了下載需要用到的工具、下載完需要的工具之后開始安裝、讓Ecplise自動(dòng)安裝Android開發(fā)插件(ADT- plugin)、配置Andiord SDK路徑、測(cè)試開發(fā)一個(gè)Android項(xiàng)目等內(nèi)容,需要的朋友可以參考下2015-04-04Android自定義評(píng)分控件的完整實(shí)例
在Android開發(fā)中,我們經(jīng)常會(huì)用到對(duì)商家或者商品的評(píng)價(jià),運(yùn)用星星進(jìn)行打分,下面這篇文章主要給大家介紹了關(guān)于Android自定義評(píng)分控件的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05Android Studio如何為Activity添加自定義注解信息
好久沒用寫文章了,今天給大家分享Android Studio如何為Activity添加自定義注解信息,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-06-06