使用內置的Camera應用程序捕獲圖像

本章將介紹有關Android上圖像捕獲和存儲的基礎知識。首先將探索Android所提供的內置功能,然後在後續章節中更多地介紹定製軟件。我們將首先介紹如何利用內置的Camera(攝像頭)應用程序,然後介紹如何利用MediaStore——內置的媒體和元數據存儲機制

隨着移動電話迅速成爲移動計算機,它們在許多方面已經取代了各種各樣的消費類電子產品。最早添加到移動電話上且和電話無關的硬件功能之一是攝像頭。現在,似乎很難想象有人會購買一部不包含攝像頭功能的移動電話。當然,基於Android的電話也不例外;從一開始,Android SDK就支持訪問電話內置的硬件攝像頭來捕獲圖像。

在Android上,完成許多事情的最便捷方式是通過使用意圖(intent)來利用該設備上的某個現有軟件。意圖是Android的核心組件,在文檔中將它解釋爲一個“將要執行的操作的描述”。在實踐中,意圖用於觸發其他應用程序來完成某件事情,或者在單個應用程序的活動之間進行切換。

所有帶有合適硬件(攝像頭)的原版Android設備都會附帶Camera應用程序。Camera應用程序包含一個意圖過濾器(intent filter),它使得開發人員能夠提供與Camera應用程序同等的圖像捕獲能力,而不必構建他們自己的定製捕獲例程。

意圖過濾器是程序員用於指定其應用程序能夠提供某個特定功能的一種方法。在應用程序的AndroidManifest.xml 文件中指定一個意圖過濾器,將會告訴Android,這個應用程序(尤其是包含意圖過濾器的活動)將根據指令執行指定的任務。

Camera應用程序在其清單文件中指定了以下意圖過濾器。這裏顯示的意圖過濾器包含在“Camera”活動標記內。

<intent-filter>

<action android:name="android.media.action.IMAGE_CAPTURE"/>

<category android:name="android.intent.category.DEFAULT"/>

</intent-filter>

爲了通過一個意圖利用Camera應用程序,我們所要做的僅僅是必須構造一個將由上述過濾器捕獲的意圖。

Intent i = new Intent("android.media.action.IMAGE_CAPTURE");

在實踐中,我們可能不希望直接使用動作字符串創建意圖。在這種情況下,可以指定MediaStore類中的常量ACTION_IMAGE_CAPTURE。應該使用常量而非字符串本身的原因在於,如果該字符串發生了改變(當然常量也可能會不斷地改變),那麼使用常量將使得我們的調用比之前使用字符串更有利於未來的變化。

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

startActivity(i);

在一個基本的Android活動中使用這種意圖,將導致默認的Camera應用程序以靜止圖片模式(still picture mode)啓動,如圖1-1所示。

圖1-1  通過意圖調用的內置Camera應用程序在模擬器中的運行結果

1.1從Camera應用程序返回數據

    當然,在捕獲一張圖片時,如果Camera 應用程序沒有將圖片返回給調用活動,那麼簡單地使用內置的Camera應用程序捕獲圖像將不具有真正的作用。而爲了使得它真正有用,可以將活動中的startActivity 方法替換爲startActivityForResult 方法。使用該方法將允許我們訪問從Camera應用程序中返回的數據,它恰好是用戶以位圖(Bitmap)形式捕獲的圖像。
以下是一個基本的示例。

package com.apress.proandroidmedia.ch1.cameraintent;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.ImageView;

public class CameraIntent extends Activity {

final static int CAMERA_RESULT = 0;

ImageView imv;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i = new Intent(android.provider
.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, CAMERA_RESULT);
}

protected void onActivityResult(int requestCode, int resultCode,
      Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);

if (resultCode == RESULT_OK)
{
Get Bundle extras = intent.getExtras();
Bitmap bmp = (Bitmap) extras.get("data");


imv = (ImageView) findViewById(R.id.ReturnedImageView);
imv.setImageBitmap(bmp);
}
}
}

它需要在項目的layout/main.xml 文件中添加如下內容:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView android:id="@+id/ReturnedImageView"android:layout_width=
"wrap_content"android:layout_height="wrap_content"></ImageView>
</LinearLayout>

爲了完成上述示例,以下是AndroidManifest.xml 文件的內容。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"package="com.apress.proandroidmedia.ch1
.cameraintent">
<application android:icon="@drawable/icon" android:label=
"@string/app_name">
<activity android:name=".CameraIntent" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>

在此示例中,Camera應用程序在一個通過意圖傳遞的附加值(extra)中返回圖像,而該意圖將在onActivityResult方法中傳遞給主調活動。附加值的名稱爲“data”,它包含一個Bitmap對象,需要從泛型對象將它強制轉換過來。

//從意圖中獲取附加值
Bundle extras = intent.getExtras();

//從附加值中獲取返回的圖像
Bitmap bmp = (Bitmap) extras.get("data");

在我們的佈局XML (layout/main.xml)文件中,有一個ImageView對象。ImageView是泛型視圖的擴展,其支持圖像的顯示。由於我們有一個帶有指定ReturnedImageView編號(id)的ImageView對象,因此需要在活動中獲得它的引用,並通過setImageBitmap方法將它的Bitmap對象設置爲返回的圖像。這將使得應用程序用戶能夠查看這幅捕獲的圖像。
爲了獲得ImageView對象的引用,使用在Activity類中指定的標準方法findViewById。該方法使得我們能夠以編程方式引用在佈局XML文件中指定的元素,我們正在通過將元素id傳遞給setContentView來使用該佈局XML文件。上述示例在XML中以如下方式指定ImageView對象:

<ImageView android:id="@+id/ReturnedImageView" android:layout_width=
"wrap_content" android:layout_height="wrap_content"></ImageView>

爲了引用ImageView並通知它顯示來自Camera的Bitmap對象,使用以下代碼。

imv = (ImageView) findViewById(R.id.ReturnedImageView);
imv.setImageBitmap(bmp);

當運行這個示例時,您可能會注意到結果圖像很小(在我的手機上,它的寬爲121像素,高爲162像素。其他設備會具有不同的默認大小)。這不是一個bug——相反,它是經過精心設計的。當通過一個意圖觸發時,Camera應用程序不會將全尺寸的圖像返回給主調活動。通常,這樣做需要大量的內存,而移動設備一般會在內存方面受限。相反,Camera應用程序將在返回的意圖中返回一幅很小的縮略圖,如圖1-2所示。

圖1-2  在ImageView 中顯示的121×162像素的結果圖像

發佈了3 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章