知識社群登入
位置: 艾鍗學院 Blog > 專業論壇 > 討論
Android照相檔案無法立即顯示問題
1樓
請問我在實作照相及錄音功能時,圖片及錄音檔案確實立即儲存在SDcard上(由DDMS可以看到),可以使用程式碼開啟檔案,但是卻無法使用Android圖片管理程式及音樂程式看到檔案,必須將SDcard卸載再次掛載才可以看到,這是為什麼呢?請問要如何解決?謝謝
2樓
Android圖片軟體與音樂軟體,並不像一般的檔案總管一樣,一進去就可以看到完整的目錄結構.
而是需要待軟體去進行SD卡的掃瞄動作,將圖片分類出來後才會出現在軟體上. 
3樓
請問老師解決方式,是否可以在程式碼裡下命令先卸載SD卡立刻再掛載?
4樓
如果你是要做將照片錄影存放在SD卡中,而SD卡也確實有資料放進去,那麼也就代表你的應用程式己正確運作.
至於為何相簿軟體會跑不出最新的相片或影片,那麼你必需先了解Android內部針對這些多媒體資料的索引
處理機制。 我會大概的說明其觀念如下:

另外sd卡是不會有權限讓你去隨便缷載的,試想你在缷載時如果還有其它應用程式正在對sd卡存取一筆後重
要的資料,因為你的一個缷載動作而導致其他更嚴重的資料遺失問題,那就因小失大了。



Android內如何處理多媒體資料的索引:

一般相簿軟體裡的相片與影片索引與縮圖的來源都是透過Android內部的ContentProvider提供索引的資料(
因為這樣方便取得又可以節省手機的電源,還可以取得縮圖好的圖片以先方便快速的覽示所有相片) 而
ContentProvider的資料來源,則是利用Android系統的MediaScanner這個服務,因為掃描與索引還有縮圖
的動作是要花費大量的CPU與電力,所以不會一直不斷的去做掃描的動作,因為這樣你的手機會很快就沒電了。
我們可以打開MediaScanner的原始碼來看:其中有一段資訊如下:

 @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Uri uri = intent.getData();
        String externalStoragePath = Environment.getExternalStorageDirectory().getPath();

        if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
            // scan internal storage
            scan(context, MediaProvider.INTERNAL_VOLUME);
        } else {
            if (uri.getScheme().equals("file")) {
                // handle intents related to external storage
                String path = uri.getPath();
                if (action.equals(Intent.ACTION_MEDIA_MOUNTED) &&
                        externalStoragePath.equals(path)) {
                    scan(context, MediaProvider.EXTERNAL_VOLUME);
                } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) &&
                        path != null && path.startsWith(externalStoragePath + "/")) {
                    scanFile(context, path);
                }
            }
        }
    }



由上圖和上述的程式碼中紅色的關ACTION鍵關字可以得知:當系統啟動完成時,MediaScan會去掃描一次,另外
當SD卡重新Mount上去時系統也會去掃瞄一次,最後還有當收到 ACTION_MEDIA_SCANNER_SCAN_FILE 
要求掃瞄時也會去啟動掃瞄索引資料.

1.所以你可以下以下廣播去讓系統對整個SD卡內容重做掃瞄索引(需注意這會很耗系統資源)
public void allScan(){  
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"  
                + Environment.getExternalStorageDirectory())));  
    } 
2.你可以下以下廣播去對單一檔案做更新掃瞄索引的動作(這個只會針對你指定的檔案索引,較不吃資源)
public void fileScan(String fName){  
        Uri data = Uri.parse("file:///"+fName);  
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data));  
    }   


最後附代一提,一般相簿軟體、音樂軟體...大多都是利用ContentProvider去存取系統中索引好的多媒體資料,相關的ContentProvider URI如下
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI     -->音樂
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI  -->圖片
MediaStore.Video.Media.EXTERNAL_CONTENT_URI  -->影片


5樓
 
Jarey 老師 好認真再回覆喔~
 
6樓

對阿,Jarey老師非常認真,來艾鍗上課真是獲益良多,謝謝老師

7樓
Jarey老師
我在實作錄音程式時,有google一些文章,也按照程式碼實作,利用android.media.MediaRecorder.
AudioSource.MIC時是可以正常錄音,但是發現有其他參數如android.media.MediaRecorder.
AudioSource.VOICE_CALL
可以錄通話內容,不過網路上大部分人都說這個參數有BUG,無法如說明文件執行功能,但是也有人說在他們的手機可以正常執行(market上也有通話錄音程式說可以支援到2.3,非免費程式),經我自己實驗發現上述兩個參數錄音結果都相同,請問這個參數是真的有BUG還是要進行其他設定呢?謝謝
8樓
Hi Terry:
提供你一個管道, 一般像你這種疑問,可以透過Google Android Code Project內的ISSUE回報論譠去取得相關的資訊

關於VOICE_CALL 的ISSUE 請參考下篇說明