前言
在Android應用中,經常有場景會需要使用到設備上存儲的圖片,而直接從路徑中獲取無疑是非常不便利的。所以一般推薦調用系統的Gallery應用,選擇圖片,然后使用它。本篇博客將講解如何在Android中通過系統Gallery獲取圖片。
Gallery應用
Android原生內置了很多App,而Gallery為圖庫,用於操作設備上的圖片,它會在開機的時候主動掃描設備上存儲的圖片,並可以使用Gallery操作它們。既然要使用Gallery,那么先看看它的AndroidManifest.xml清單文件。
1 <activity android:name="com.android.camera.ImageGallery" 2 android:label="@string/gallery_label" 3 android:configChanges="orientation|keyboardHidden" 4 android:icon="@drawable/ic_launcher_gallery"> 5 <intent-filter> 6 <action android:name="android.intent.action.MAIN" /> 7 <category android:name="android.intent.category.DEFAULT" /> 8 </intent-filter> 9 <intent-filter> 10 <action android:name="android.intent.action.VIEW" /> 11 <category android:name="android.intent.category.DEFAULT" /> 12 <data android:mimeType="vnd.android.cursor.dir/image" /> 13 </intent-filter> 14 <intent-filter> 15 <action android:name="android.intent.action.VIEW" /> 16 <category android:name="android.intent.category.DEFAULT" /> 17 <data android:mimeType="vnd.android.cursor.dir/video" /> 18 </intent-filter> 19 <intent-filter> 20 <action android:name="android.intent.action.GET_CONTENT" /> 21 <category android:name="android.intent.category.OPENABLE" /> 22 <data android:mimeType="vnd.android.cursor.dir/image" /> 23 </intent-filter> 24 <intent-filter> 25 <action android:name="android.intent.action.GET_CONTENT" /> 26 <category android:name="android.intent.category.OPENABLE" /> 27 <category android:name="android.intent.category.DEFAULT" /> 28 <data android:mimeType="image/*" /> 29 <data android:mimeType="video/*" /> 30 </intent-filter> 31 <intent-filter> 32 <action android:name="android.intent.action.PICK" /> 33 <category android:name="android.intent.category.DEFAULT" /> 34 <data android:mimeType="image/*" /> 35 <data android:mimeType="video/*" /> 36 </intent-filter> 37 <intent-filter> 38 <action android:name="android.intent.action.PICK" /> 39 <category android:name="android.intent.category.DEFAULT" /> 40 <data android:mimeType="vnd.android.cursor.dir/image" /> 41 </intent-filter> 42 </activity>
上面是Gallery的AndroidManifest.xml文件中的部分代碼,展示了ImageGallery,從眾多Intent-filter中可以看出,選取圖片應該使用"android.intent.action.PICK",它有兩個miniType,"image/*"是用來獲取圖片的、"video/*"是用來獲取視頻的。Android中眾多Action的字符串其實被封裝在Intent類中,android.intent.action.PICK也不例外,它是Intent.ACTION_PICK。
既然知道了啟動Gallery的Action,那么再看看ImageGallery.java的源碼,找找其中選中圖片后的返回值。
1 private void launchCropperOrFinish(IImage img) { 2 Bundle myExtras = getIntent().getExtras(); 3 4 long size = MenuHelper.getImageFileSize(img); 5 if (size < 0) { 6 // Return if the image file is not available. 7 return; 8 } 9 10 if (size > mVideoSizeLimit) { 11 DialogInterface.OnClickListener buttonListener = 12 new DialogInterface.OnClickListener() { 13 public void onClick(DialogInterface dialog, int which) { 14 dialog.dismiss(); 15 } 16 }; 17 new AlertDialog.Builder(this) 18 .setIcon(android.R.drawable.ic_dialog_info) 19 .setTitle(R.string.file_info_title) 20 .setMessage(R.string.video_exceed_mms_limit) 21 .setNeutralButton(R.string.details_ok, buttonListener) 22 .show(); 23 return; 24 } 25 26 String cropValue = myExtras != null ? myExtras.getString("crop") : null; 27 if (cropValue != null) { 28 Bundle newExtras = new Bundle(); 29 if (cropValue.equals("circle")) { 30 newExtras.putString("circleCrop", "true"); 31 } 32 33 Intent cropIntent = new Intent(); 34 cropIntent.setData(img.fullSizeImageUri()); 35 cropIntent.setClass(this, CropImage.class); 36 cropIntent.putExtras(newExtras); 37 38 /* pass through any extras that were passed in */ 39 cropIntent.putExtras(myExtras); 40 startActivityForResult(cropIntent, CROP_MSG); 41 } else { 42 Intent result = new Intent(null, img.fullSizeImageUri()); 43 if (myExtras != null && myExtras.getBoolean("return-data")) { 44 // The size of a transaction should be below 100K. 45 Bitmap bitmap = img.fullSizeBitmap( 46 IImage.UNCONSTRAINED, 100 * 1024); 47 if (bitmap != null) { 48 result.putExtra("data", bitmap); 49 } 50 } 51 setResult(RESULT_OK, result); 52 finish(); 53 } 54 }
以上的ImageGallery.java的部分源碼,從setResult()方法可以看出,它返回的Intent包含了選中圖片的Uri,它是一個content://開頭的內容提供者,並且如果傳遞過去的Intent的Extra中,包含一個name為"return-data"並且值為true的時候,還會往Extra中寫入name為"data"的圖片縮略圖。
Gallery獲取圖片Demo
既然已經知道了啟動Gallery的Action,和它如何返回選中的數據,那么接下來通過一個簡單的Demo來演示一下如何從系統Gallery中獲取圖片,並把獲取到的圖片展示到界面的一個ImageView中。
1 package cn.bgxt.sysgallerydemo; 2 3 import android.net.Uri; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.View; 7 import android.view.View.OnClickListener; 8 import android.widget.Button; 9 import android.widget.ImageView; 10 import android.app.Activity; 11 import android.content.Intent; 12 13 public class MainActivity extends Activity { 14 private Button btn_getImage; 15 private ImageView iv_image; 16 private final static String TAG = "main"; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 23 btn_getImage = (Button) findViewById(R.id.btn_getImage); 24 iv_image = (ImageView) findViewById(R.id.iv_image); 25 26 btn_getImage.setOnClickListener(getImage); 27 } 28 29 private View.OnClickListener getImage = new OnClickListener() { 30 31 @Override 32 public void onClick(View v) { 33 // 設定action和miniType 34 Intent intent = new Intent(); 35 intent.setAction(Intent.ACTION_PICK); 36 intent.setType("image/*"); 37 // 以需要返回值的模式開啟一個Activity 38 startActivityForResult(intent, 0); 39 } 40 }; 41 42 @Override 43 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 44 // 如果獲取成功,resultCode為-1 45 Log.i(TAG, "resultCode:" + resultCode); 46 if (requestCode == 0 && resultCode == -1) { 47 // 獲取原圖的Uri,它是一個內容提供者 48 Uri uri = data.getData(); 49 iv_image.setImageURI(uri); 50 } 51 super.onActivityResult(requestCode, resultCode, data); 52 } 53 }
效果展示:
總結
本篇博客到這里就基本上講解了如何在Android下調用系統Gallery獲取圖片,其實功能實現很簡單,主要是要注意Action和miniType不要寫錯了,並且返回值是一個Uri。雖然現在越來越多需要用到圖片的商業應用,都在自己開發獲取設備圖片的功能,但是使用系統自帶的Gallery來獲取不失為一種快速實現功能的解決辦法。為了方便起見,系統的Gallery源碼,也會一並打包放到源碼中,有需要的可以下載來看看。