前言
在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 }