<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                1. 創建MediaScanner 認識一下MediaScanner,它的代碼如下所示: **MediaScanner.java** ~~~ public class MediaScanner { static { /* 加載libmedia_jni.so,這么重要的庫竟然放在如此不起眼的MediaScanner類中加載。 個人覺得,可能是因為開機后多媒體系統中最先啟動的就是媒體掃描工作吧。 */ System.loadLibrary("media_jni"); native_init(); } //創建媒體掃描器 public MediaScanner(Context c) { native_setup();//調用JNI層的函數做一些初始化工作 ...... } ~~~ 在上面的MS中,比較重要的幾個調用函數是: - native_init和native_setup,關于它們的故事,在分析JNI層時再做介紹。 MS創建好后,MSS將調用它的scanDirectories開展掃描工作,下面來看這個函數。 2. scanDirectories的分析 scanDirectories的代碼如下所示: **MediaScanner.java** ~~~ public void scanDirectories(String[]directories, String volumeName) { try { long start = System.currentTimeMillis(); initialize(volumeName);//①初始化 prescan(null);//②掃描前的預處理 long prescan = System.currentTimeMillis(); for(int i = 0; i < directories.length; i++) { /* ③ processDirectory是一個native函數,調用它來對目標文件夾進行掃描, 其中MediaFile.sFileExtensions是一個字符串,包含了當前多媒體系統所支持的 媒體文件的后綴名,例如.MP3、.MP4等。mClient為MyMediaScannerClient類型, 它是從MediaScannerClient類派生的。它的作用我們后面再做分析。 */ processDirectory(directories[i], MediaFile.sFileExtensions, mClient); } long scan = System.currentTimeMillis(); postscan(directories);//④掃描后處理 long end = System.currentTimeMillis(); ......//統計掃描時間等 } ~~~ 上面一共列出了四個關鍵點,下面逐一對其分析。 (1)initialize的分析 initialize主要是初始化一些Uri,因為掃描時需把文件的信息插入媒體數據庫中,而媒體數據庫針對Video、Audio、Image文件等都有對應的表,這些表的地址則由Uri表示。下面是initialize的代碼: **MediaScanner.java** ~~~ private void initialize(String volumeName) { //得到IMediaProvider對象,通過這個對象可以對媒體數據庫進行操作。 mMediaProvider= mContext.getContentResolver().acquireProvider("media"); //初始化Uri,下面分別介紹一下。 //音頻表的地址,也就是數據庫中的audio_meta表。 mAudioUri =Audio.Media.getContentUri(volumeName); //視頻表地址,也就是數據庫中的video表。 mVideoUri = Video.Media.getContentUri(volumeName); //圖片表地址,也就是數據庫中的images表。 mImagesUri = Images.Media.getContentUri(volumeName); //縮略圖表地址,也就是數據庫中的thumbs表。 mThumbsUri = Images.Thumbnails.getContentUri(volumeName); //如果掃描的是外部存儲,則支持播放列表、音樂的流派等內容。 if(!volumeName.equals("internal")) { mProcessPlaylists = true; mProcessGenres = true; mGenreCache = new HashMap<String, Uri>(); mGenresUri = Genres.getContentUri(volumeName); mPlaylistsUri = Playlists.getContentUri(volumeName); if ( Process.supportsProcesses()) { //SD卡存儲區域一般使用FAT文件系統,所以文件名與大小寫無關 mCaseInsensitivePaths = true; } } } ~~~ 下面看第二個關鍵函數prescan。 (2)prescan的分析 在媒體掃描過程中,有個令人頭疼的問題,來舉個例子,這個例子會貫穿在對這個問題整體分析的過程中。例子:假設某次掃描之前SD卡中有100個媒體文件,數據庫中有100條關于這些文件的記錄,現因某種原因刪除了其中的50個媒體文件,那么媒體數據庫什么時候會被更新呢? 讀者別小瞧這個問題。現在有很多文件管理器支持刪除文件和文件夾,它們用起來很方便,卻沒有對應地更新數據庫,這導致了查詢數據庫時還能得到這些媒體文件信息,但這個文件實際上已不存在了,而且后面所有和此文件有關的操作都會因此而失敗。 其實,MS已經考慮到這一點了,prescan函數的主要作用是在掃描之前把數據庫中和文件相關的信息取出并保存起來,這些信息主要是媒體文件的路徑,所屬表的Uri。就上面這個例子來說,它會從數據庫中取出100個文件的文件信息。 prescan的代碼如下所示: **MediaScanner.java** ~~~ privatevoid prescan(String filePath) throws RemoteException { Cursor c = null; String where = null; String[] selectionArgs = null; //mFileCache保存從數據庫中獲取的文件信息。 if(mFileCache == null) { mFileCache = new HashMap<String, FileCacheEntry>(); }else { mFileCache.clear(); } ...... try { //從Audio表中查詢其中和音頻文件相關的文件信息。 if (filePath != null) { where = MediaStore.Audio.Media.DATA + "=?"; selectionArgs = new String[] { filePath }; } //查詢數據庫的Audio表,獲取對應的音頻文件信息。 c = mMediaProvider.query(mAudioUri, AUDIO_PROJECTION, where, selectionArgs,null); if (c != null) { try { while (c.moveToNext()) { long rowId =c.getLong(ID_AUDIO_COLUMN_INDEX); //音頻文件的路徑 String path =c.getString(PATH_AUDIO_COLUMN_INDEX); long lastModified = c.getLong(DATE_MODIFIED_AUDIO_COLUMN_INDEX); if(path.startsWith("/")) { String key = path; if(mCaseInsensitivePaths) { key =path.toLowerCase(); } //把文件信息存到mFileCache中 mFileCache.put(key, new FileCacheEntry(mAudioUri, rowId, path, lastModified)); } } } finally { c.close(); c = null; } } ......//查詢其他表,取出數據中關于視頻,圖像等文件的信息并存入到mFileCache中。 finally { if (c != null) { c.close(); } } } ~~~ 懂了前面的例子,在閱讀prescan函數時可能就比較輕松了。prescan函數執行完后,mFileCache保存了掃描前所有媒體文件的信息,這些信息是從數據庫中查詢得來的,也就是舊有的信息。 接下來,看最后兩個關鍵函數。 (3)processDirectory和postscan的分析 processDirectory是一個native函數,其具體功能放到JNI層再分析,這里先簡單介紹,它在解決上一節那個例子中提出的問題時,所做的工作。答案是:processDirectory將掃描SD卡,每掃描一個文件,都會設置mFileCache中對應文件的一個叫mSeenInFileSystem的變量為true。這個值表示這個文件目前還存在于SD卡上。這樣,待整個SD卡掃描完后,mFileCache的那100個文件中就會有50個文件的mSeenInFileSystem為true,而剩下的另50個文件則為初始值false。 看到上面的內容,可以知道postscan的作用了吧?就是它把不存在于SD卡的文件信息從數據庫中刪除,而使數據庫得以徹底更新的。來看postscan函數是否是這樣處理的: **MediaScanner.java** ~~~ private void postscan(String[] directories)throws RemoteException { Iterator<FileCacheEntry> iterator =mFileCache.values().iterator(); while(iterator.hasNext()) { FileCacheEntry entry = iterator.next(); String path = entry.mPath; boolean fileMissing = false; if (!entry.mSeenInFileSystem) { if (inScanDirectory(path, directories)) { fileMissing = true; //這個文件確實丟失了 } else { File testFile = newFile(path); if (!testFile.exists()) { fileMissing = true; } } } //如果文件確實丟失,則需要把數據庫中和它相關的信息刪除。 if(fileMissing) { MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path); int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType); if(MediaFile.isPlayListFileType(fileType)) { ......//處理丟失文件是播放列表的情況 } else { /*由于文件信息中還攜帶了它在數據庫中的相關信息,所以從數據庫中刪除對應的信息會非常快。 */ mMediaProvider.delete(ContentUris.withAppendedId( entry.mTableUri, entry.mRowId), null, null); iterator.remove(); } } } ......//刪除縮略圖文件等工作 } ~~~ Java層中的四個關鍵點,至此已介紹了三個,另外一個processDirectory是媒體掃描的關鍵函數,由于它是一個native函數,所以下面將轉戰到JNI層來進行分析。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看