鍍金池/ 教程/ Android/ 輕松拍攝照片
檢測常用的手勢
優(yōu)化layout的層級
用戶輸入
管理應(yīng)用的內(nèi)存
聯(lián)系人信息
開發(fā)輔助程序
Android多媒體
添加語音功能
顯示位置地址
提供向下與橫向?qū)Ш?/span>
支持游戲控制器
訪問可穿戴數(shù)據(jù)層
處理多點(diǎn)觸控手勢
全屏沉浸式應(yīng)用
為多線程創(chuàng)建管理器
數(shù)據(jù)保存
Intent的發(fā)送
更新Notification
優(yōu)化下載以高效地訪問網(wǎng)絡(luò)
打印
打包可穿戴應(yīng)用
接收從其他App傳送來的數(shù)據(jù)
發(fā)送與接收消息
建立靈活動(dòng)態(tài)的UI
處理鍵盤輸入
Building a Work Policy Controller
建立測試環(huán)境
創(chuàng)建表盤
分享文件
顯示Notification進(jìn)度
實(shí)現(xiàn)自適應(yīng)UI流(Flows)
使用設(shè)備管理策略增強(qiáng)安全性
使用能感知版本的組件
執(zhí)行網(wǎng)絡(luò)操作
建立文件分享
添加移動(dòng)
更新你的Security Provider來對抗SSL漏洞利用
支持鍵盤導(dǎo)航
創(chuàng)建和監(jiān)視地理圍欄
發(fā)送并同步數(shù)據(jù)
使用BigView樣式
無線連接設(shè)備
提供向上導(dǎo)航與歷史導(dǎo)航
最小化定期更新造成的影響
實(shí)現(xiàn)向下的導(dǎo)航
支持不同的屏幕大小
Android 可穿戴應(yīng)用
添加動(dòng)畫
顯示聯(lián)系人頭像
使用OpenGL ES顯示圖像
處理輸入法可見性
分享文件
保持設(shè)備喚醒
淡化系統(tǒng)Bar
使用NFC分享文件
保存到Preference
Android聯(lián)系人信息與位置信息
創(chuàng)建標(biāo)準(zhǔn)的網(wǎng)絡(luò)請求
使用Drawables
管理Bitmap的內(nèi)存使用
管理Activity的生命周期
按需加載視圖
傳輸資源
為可穿戴設(shè)備創(chuàng)建自定義UI
在一個(gè)線程中執(zhí)行一段特定的代碼
性能優(yōu)化
隱藏導(dǎo)航欄
創(chuàng)建目錄瀏覽器
為多種大小的屏幕進(jìn)行規(guī)劃
View間漸變
使用觸摸手勢
高效加載大圖
使用CursorLoader在后臺加載數(shù)據(jù)
創(chuàng)建抽屜式導(dǎo)航(navigation drawer)
管理音頻焦點(diǎn)
創(chuàng)建后臺服務(wù)
創(chuàng)建功能測試
創(chuàng)建使用Material Design的應(yīng)用
停止與重啟Activity
添加一個(gè)簡便的分享功能
啟動(dòng)Activity時(shí)保留導(dǎo)航
TV應(yīng)用清單
創(chuàng)建向后兼容的UI
?# 優(yōu)化自定義View
創(chuàng)建單元測試
在UI上顯示Bitmap
建立OpenGL ES的環(huán)境
構(gòu)建表盤服務(wù)
JNI Tips
建立搜索界面
實(shí)現(xiàn)自定義View的繪制
使用HTTPS與SSL
按需操控BroadcastReceiver
分享簡單的數(shù)據(jù)
繪制形狀
Android位置信息
創(chuàng)建并運(yùn)行可穿戴應(yīng)用
執(zhí)行 Sync Adpater
獲取最后可知位置
創(chuàng)建 Android 項(xiàng)目
實(shí)現(xiàn)高效的導(dǎo)航
退出全屏的Activity
創(chuàng)建Card
兼容音頻輸出設(shè)備
同步數(shù)據(jù)單元
傳輸數(shù)據(jù)時(shí)避免消耗大量電量
保存到文件
緩存Bitmap
提供配置 Activity
調(diào)度重復(fù)的鬧鐘
實(shí)現(xiàn)輔助功能
重復(fù)的下載是冗余的
隱藏狀態(tài)欄
實(shí)現(xiàn)自定義的網(wǎng)絡(luò)請求
規(guī)劃界面和他們之間的關(guān)系
使用Sync Adapter傳輸數(shù)據(jù)
TV應(yīng)用內(nèi)搜索
響應(yīng)觸摸事件
使用Google Cloud Messaging(已廢棄)
控制相機(jī)
Android網(wǎng)絡(luò)連接與云服務(wù)
請求分享一個(gè)文件
處理TV硬件
響應(yīng)UI可見性的變化
使用網(wǎng)絡(luò)服務(wù)發(fā)現(xiàn)
指定輸入法類型
優(yōu)化電池壽命
創(chuàng)建TV應(yīng)用
獲取聯(lián)系人列表
拖拽與縮放
啟動(dòng)與停止線程池中的線程
創(chuàng)建 Sync Adpater
使用 WiFi P2P 服務(wù)發(fā)現(xiàn)
開始使用Material Design
代理至新的APIs
使用include標(biāo)簽重用layouts
使得View可交互
高效顯示Bitmap
創(chuàng)建企業(yè)級應(yīng)用
Fragments之間的交互
創(chuàng)建與執(zhí)行測試用例
綜合:設(shè)計(jì)我們的樣例 App
繪制表盤
建立簡單的用戶界面
自定義動(dòng)畫
開發(fā)輔助服務(wù)
避免出現(xiàn)程序無響應(yīng)ANR(Keeping Your App Responsive)
使用ViewPager實(shí)現(xiàn)屏幕滑動(dòng)
設(shè)計(jì)高效的導(dǎo)航
Android分享操作(Building Apps with Content Sharing)
提供向后的導(dǎo)航
保持向下兼容
創(chuàng)建TV播放應(yīng)用
縮放View
使用 WiFi 建立 P2P 連接
Android后臺任務(wù)
連接到網(wǎng)絡(luò)
為 Notification 添加頁面
使TV應(yīng)用是可被搜索的
添加Action Bar
使用Material的主題
啟動(dòng)另一個(gè)Activity
顯示正在播放卡片
適配不同的系統(tǒng)版本
輕松錄制視頻
創(chuàng)建可穿戴的應(yīng)用
創(chuàng)建自定義的布局
重新創(chuàng)建Activity
使用CursorLoader執(zhí)行查詢?nèi)蝿?wù)
使用舊的APIs實(shí)現(xiàn)新API的效果
使用備份API
安全要點(diǎn)
Android入門基礎(chǔ):從這里開始
保存并搜索數(shù)據(jù)
根據(jù)網(wǎng)絡(luò)連接類型來調(diào)整下載模式
使用Tabs創(chuàng)建Swipe視圖
SMP(Symmetric Multi-Processor) Primer for Android
解析 XML 數(shù)據(jù)
使用 Volley 傳輸網(wǎng)絡(luò)數(shù)據(jù)
建立ActionBar
Android交互設(shè)計(jì)
使用Intent修改聯(lián)系人信息
增加搜索功能
輕松拍攝照片
定義形狀
測試你的Activity
在 Notifcation 中接收語音輸入
與其他應(yīng)用的交互
管理系統(tǒng)UI
追蹤手勢移動(dòng)
Android界面設(shè)計(jì)
執(zhí)行 Android 程序
顯示確認(rèn)界面
創(chuàng)建Lists與Cards
打印HTML文檔
創(chuàng)建TV應(yīng)用
為多屏幕設(shè)計(jì)
定義Shadows與Clipping視圖
使用Fragment建立動(dòng)態(tài)UI
接收Activity返回的結(jié)果
布局變更動(dòng)畫
定位常見的問題
自定義ActionBar的風(fēng)格
定義Layouts
發(fā)送簡單的網(wǎng)絡(luò)請求
啟動(dòng)與銷毀Activity
與UI線程通信
非UI線程處理Bitmap
創(chuàng)建TV布局
提升Layout的性能
報(bào)告任務(wù)執(zhí)行狀態(tài)
判斷并監(jiān)測網(wǎng)絡(luò)連接狀態(tài)
兼容不同的設(shè)備
處理按鍵動(dòng)作
優(yōu)化性能和電池使用時(shí)間
給其他App發(fā)送簡單的數(shù)據(jù)
Implementing App Restrictions
向后臺服務(wù)發(fā)送任務(wù)請求
展示Card翻轉(zhuǎn)動(dòng)畫
管理ViewGroup中的觸摸事件
兼容不同的屏幕密度
通過藍(lán)牙進(jìn)行調(diào)試
為可穿戴設(shè)備創(chuàng)建Notification
控制音量與音頻播放
獲取聯(lián)系人詳情
在表盤上顯示信息
提供向上的導(dǎo)航
滾動(dòng)手勢動(dòng)畫
幫助用戶在TV上找到內(nèi)容
創(chuàng)建TV導(dǎo)航
為索引指定App內(nèi)容
ActionBar的覆蓋疊加
Android Wear 上的位置檢測
保護(hù)安全與隱私的最佳策略
Ensuring Compatibility with Managed Profiles
解決云同步的保存沖突
獲取位置更新
創(chuàng)建List
測試程序
管理網(wǎng)絡(luò)的使用情況
為App內(nèi)容開啟深度鏈接
推薦TV內(nèi)容
建立一個(gè)Notification
管理音頻播放
設(shè)計(jì)表盤
拍照
處理控制器輸入動(dòng)作
判斷并監(jiān)測設(shè)備的底座狀態(tài)與類型
處理查詢的結(jié)果
保存到數(shù)據(jù)庫
支持多個(gè)游戲控制器
創(chuàng)建 Stub Content Provider
使得ListView滑動(dòng)順暢
處理數(shù)據(jù)層的事件
創(chuàng)建TV應(yīng)用的第一步
使得你的App內(nèi)容可被Google搜索
將 Notification 放成一疊
創(chuàng)建 Stub 授權(quán)器
暫停與恢復(fù)Activity
管理設(shè)備的喚醒狀態(tài)
Android圖像與動(dòng)畫
打印照片
云同步
創(chuàng)建TV直播應(yīng)用
為Notification賦加可穿戴特性
提供一個(gè)Card視圖
建立請求隊(duì)列(RequestQueue)
適配不同的語言
創(chuàng)建詳情頁
測試UI組件
接收其他設(shè)備的文件
創(chuàng)建自定義View
建立第一個(gè)App
創(chuàng)建2D Picker
監(jiān)測電池的電量與充電狀態(tài)
打印自定義文檔
抽象出新的APIs
通知提示用戶
獲取文件信息
運(yùn)用投影與相機(jī)視角
在IntentService中執(zhí)行后臺任務(wù)
多線程操作
創(chuàng)建一個(gè)Fragment
添加Action按鈕
在不同的 Android 系統(tǒng)版本支持控制器
維護(hù)兼容性
發(fā)送文件給其他設(shè)備
創(chuàng)建TV游戲應(yīng)用
創(chuàng)建自定義的View類
代碼性能優(yōu)化建議
Intent過濾
適配不同的屏幕

輕松拍攝照片

編寫:kesenhoo - 原文:http://developer.android.com/training/camera/photobasics.html

這節(jié)課將講解如何使用已有的相機(jī)應(yīng)用拍攝照片。

假設(shè)我們正在實(shí)現(xiàn)一個(gè)基于人群的氣象服務(wù),通過應(yīng)用客戶端拍下的天氣圖片匯聚在一起,可以組成全球氣象圖。整合圖片只是應(yīng)用的一小部分,我們想要通過最簡單的方式獲取圖片,而不是重新設(shè)計(jì)并實(shí)現(xiàn)一個(gè)具有相機(jī)功能的組件。幸運(yùn)的是,通常來說,大多數(shù)Android設(shè)備都已經(jīng)安裝了至少一款相機(jī)程序。在這節(jié)課中,我們會學(xué)習(xí)如何利用已有的相機(jī)應(yīng)用拍攝照片。

請求使用相機(jī)權(quán)限

如果拍照是應(yīng)用的必要功能,那么應(yīng)該令它在Google Play中僅對有相機(jī)的設(shè)備可見。為了讓用戶知道我們的應(yīng)用需要依賴相機(jī),在Manifest清單文件中添加<uses-feature>標(biāo)簽:

 <manifest ... >
    <uses-feature android:name="android.hardware.camera"
                  android:required="true" />
    ...
</manifest>

如果我們的應(yīng)用使用相機(jī),但相機(jī)并不是應(yīng)用的正常運(yùn)行所必不可少的組件,可以將android:required設(shè)置為"false"。這樣的話,Google Play 也會允許沒有相機(jī)的設(shè)備下載該應(yīng)用。當(dāng)然我們有必要在使用相機(jī)之前通過調(diào)用hasSystemFeature(PackageManager.FEATURE_CAMERA)方法來檢查設(shè)備上是否有相機(jī)。如果沒有,我們應(yīng)該禁用和相機(jī)相關(guān)的功能!

使用相機(jī)應(yīng)用程序進(jìn)行拍照

利用一個(gè)描述了執(zhí)行目的Intent對象,Android可以將某些執(zhí)行任務(wù)委托給其他應(yīng)用。整個(gè)過程包含三部分: Intent 本身,一個(gè)函數(shù)調(diào)用來啟動(dòng)外部的 Activity,當(dāng)焦點(diǎn)返回到我們的Activity時(shí),處理返回圖像數(shù)據(jù)的代碼。

下面的函數(shù)通過發(fā)送一個(gè)Intent來捕獲照片:

static final int REQUEST_IMAGE_CAPTURE = 1;

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    }
}

注意在調(diào)用startActivityForResult()方法之前,先調(diào)用resolveActivity(),這個(gè)方法會返回能處理該Intent的第一個(gè)Activity(譯注:即檢查有沒有能處理這個(gè)Intent的Activity)。執(zhí)行這個(gè)檢查非常重要,因?yàn)槿绻谡{(diào)用startActivityForResult()時(shí),沒有應(yīng)用能處理你的Intent,應(yīng)用將會崩潰。所以只要返回結(jié)果不為null,使用該Intent就是安全的。

獲取縮略圖

拍攝照片并不是應(yīng)用的最終目的,我們還想要從相機(jī)應(yīng)用那里取回拍攝的照片,并對它執(zhí)行某些操作。

Android的相機(jī)應(yīng)用會把拍好的照片編碼為縮小的Bitmap,使用extra value的方式添加到返回的Intent當(dāng)中,并傳送給onActivityResult(),對應(yīng)的Key為"data"。下面的代碼展示的是如何獲取這一圖片并顯示在ImageView上。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bundle extras = data.getExtras();
        Bitmap imageBitmap = (Bitmap) extras.get("data");
        mImageView.setImageBitmap(imageBitmap);
    }
}

Note: 這張從"data"中取出的縮略圖適用于作為圖標(biāo),但其他作用會比較有限。而處理一張全尺寸圖片需要做更多的工作。

保存全尺寸照片

如果我們提供了一個(gè)File對象給Android的相機(jī)程序,它會保存這張全尺寸照片到給定的路徑下。另外,我們必須提供存儲圖片所需要的含有后綴名形式的文件名。

一般而言,用戶使用設(shè)備相機(jī)所拍攝的任何照片都應(yīng)該被存放在設(shè)備的公共外部存儲中,這樣它們就能被所有的應(yīng)用訪問。將DIRECTORY_PICTURES作為參數(shù),傳遞給getExternalStoragePublicDirectory()方法,可以返回適用于存儲公共圖片的目錄。由于該方法提供的目錄被所有應(yīng)用共享,因此對該目錄進(jìn)行讀寫操作分別需要READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE權(quán)限。另外,因?yàn)閷憴?quán)限隱含了讀權(quán)限,所以如果需要外部存儲的寫權(quán)限,那么僅僅需要請求一項(xiàng)權(quán)限就可以了:

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

然而,如果希望照片對我們的應(yīng)用而言是私有的,那么可以使用getExternalFilesDir()提供的目錄。在Android 4.3及以下版本的系統(tǒng)中,寫這個(gè)目錄需要WRITE_EXTERNAL_STORAGE權(quán)限。從Android 4.4開始,該目錄將無法被其他應(yīng)用訪問,所以該權(quán)限就不再需要了,你可以通過添加maxSdkVersion屬性,聲明只在低版本的Android設(shè)備上請求這個(gè)權(quán)限。

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
    ...
</manifest>

Note: 所有存儲在getExternalFilesDir()提供的目錄中的文件會在用戶卸載你的app后被刪除。

一旦選定了存儲文件的目錄,我們還需要設(shè)計(jì)一個(gè)保證文件名不會沖突的命名規(guī)則。當(dāng)然我們還可以將路徑存儲在一個(gè)成員變量里以備在將來使用。下面的例子使用日期時(shí)間戳作為新照片的文件名:

String mCurrentPhotoPath;

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
        imageFileName,  /* prefix */
        ".jpg",         /* suffix */
        storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;
}

有了上面的方法,我們就可以給新照片創(chuàng)建文件對象了,現(xiàn)在我們可以像這樣創(chuàng)建并觸發(fā)一個(gè)Intent

static final int REQUEST_TAKE_PHOTO = 1;

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there's a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            // Error occurred while creating the File
            ...
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                    Uri.fromFile(photoFile));
            startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }
}

將照片添加到相冊中

由于我們通過Intent創(chuàng)建了一張照片,因此圖片的存儲位置我們是知道的。對其他人來說,也許查看我們的照片最簡單的方式是通過系統(tǒng)的Media Provider。

Note: 如果將圖片存儲在getExternalFilesDir()提供的目錄中,Media Scanner將無法訪問到我們的文件,因?yàn)樗鼈冸`屬于應(yīng)用的私有數(shù)據(jù)。

下面的例子演示了如何觸發(fā)系統(tǒng)的Media Scanner,將我們的照片添加到Media Provider的數(shù)據(jù)庫中,這樣就可以使得Android相冊程序與其他程序能夠讀取到這些照片。

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

解碼一幅縮放圖片

在有限的內(nèi)存下,管理許多全尺寸的圖片會很棘手。如果發(fā)現(xiàn)應(yīng)用在展示了少量圖片后消耗了所有內(nèi)存,我們可以通過縮放圖片到目標(biāo)視圖尺寸,之后再載入到內(nèi)存中的方法,來顯著降低內(nèi)存的使用,下面的例子演示了這個(gè)技術(shù):

private void setPic() {
    // Get the dimensions of the View
    int targetW = mImageView.getWidth();
    int targetH = mImageView.getHeight();

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
    mImageView.setImageBitmap(bitmap);
}