乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      abdroid MediaScanner(2)

       浮云沫沫33 2013-09-06
      Android MediaScanner:(三)MediaScannerService
              對MediaScannerService的類結(jié)構(gòu)進行靜態(tài)分析,對創(chuàng)建時和啟動時的工作進行動態(tài)分析,分析過程中來看MediaScannerService如何處理MediaScannerReceiver所接收到的各種掃描請求。

      本文是筆者的分析歸納,并用UML圖(ClassDiagram/Sequence Diagram)來呈現(xiàn)。雖然來源于對Android源碼的分析,但文中不會占用大量篇幅羅列源碼,所以讀者在閱讀本文時,手頭最好有Android源碼,結(jié)合源碼來解讀。本文對MediaScannerService的類結(jié)構(gòu)進行靜態(tài)分析,對創(chuàng)建時和啟動時的工作進行動態(tài)分析,分析過程中來看MediaScannerService如何處理MediaScannerReceiver所接收到的各種掃描請求。

       

      一、MediaScannerService的靜態(tài)結(jié)構(gòu)分析

      MediaScanner_ClassDiagram

      •  MediaScannerService是一個Service,并實現(xiàn)Runnable,實現(xiàn)工作線程。
      •  MediaScannerService通過ServiceHandler這個Handler把主線程需要大量計算的工作放到工作線程中去做。

      在Runnable.run()中執(zhí)行消息循環(huán),把通過Handler發(fā)送過來的消息在工作線程中執(zhí)行。


      二、MediaScannerService的動態(tài)分析

              在MediaScannerService被通過startService啟動的過程中,其實包含了創(chuàng)建時的工作。下面分別分析創(chuàng)建時和啟動時所完成的工作。

      2.1 創(chuàng)建之時#0nCreate()

      Service對象在被創(chuàng)建的時候,onCreate()會被調(diào)用,看一下MediaScannerService的onCreate()里面做了什么:

      1. PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);  
      2. mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,TAG);  
      3.    
      4. Thread thr = new Thread(nullthis, “MediaScannerService”);  
      5. Thr.start();  


      MediaScannerService創(chuàng)建就是為了掃描Media的,這一過程是非常費時費力的。所以:

      •  為了防止在媒體掃描過程中,CPU睡死過去,用PowerManager的WakeLock告訴PowerManager,我這邊還在忙,別睡死了[Line#1,2];
      •  在Android的主線程中要快速返回,大量的計算任務(wù)交給工作線程去做,這里啟了一個工作線程,而這個線程的執(zhí)行體就是MediaScannerService所實現(xiàn)Runnable的run()方法,用Handler發(fā)消息之前,一定要先啟動該線程的[Line#4,5]。

      2.2 Service啟動時#onStartCommand()

              Service對象在被啟動的時候,onStartCommand()會被調(diào)用,看一下MediaScannerService的onStartCommand()里面做了什么。


              下圖是MediaScannerService#onStartCommand()中完成的工作:

      MediaScannerService_StartSequence

      •  通過參數(shù)startId和intent獲得的Bundle,通過mServiceHandler發(fā)送到工作線程中去執(zhí)行[Line#1~5];
      •  ServiceHandler的handleMessage()中,根據(jù)傳進來不同的“filepath”、“volume”以及“folder”參數(shù),執(zhí)行不同的掃描工作[Line#6~11];
      •  掃描結(jié)束,MediaScannerService本次的使命也就完成,可以stop自身了[Line#12]。

      • 可以結(jié)合MediaScannerReceiver中啟動方式的不同來看傳入的參數(shù):

      •  如果有“filepath”,是要掃描某個文件,調(diào)用scanFile()。掃描單個文件如何實現(xiàn),在Android MediaScanner:(四)MediaScanner之scanSingleFile中講解。
      •  否則,無論是針對整個volume還是某個folder的掃描,都可歸結(jié)為對目錄的掃描:對內(nèi)部volume,掃描”system/media”;對外部volume,掃描整個“/mnt/sdcard”;對含有“folder”參數(shù)的,directories[]中只包含“folder”中的路徑。

      三、小結(jié)

              本文對MediaScannerService的類結(jié)構(gòu)進行了靜態(tài)分析,對創(chuàng)建時和啟動時的工作進行了動態(tài)分析,分析過程中看MediaScannerService如何響應(yīng)MediaScannerReceiver所接收到的各種掃描請求。


      與其他文章的關(guān)系:

      •  向前看MediaScannerReceiver,來自外部的掃描請求,啟動MediaScannerService,由Service來具體負責實現(xiàn);
      •  向后看MediaScanner才是真正的掃描實現(xiàn),分掃描文件掃描路徑來講解。

      Android MediaScanner:(四)MediaScanner之scanSingleFile

              本文從MediaScannerService的scanFile入口開始,詳細分析MediaScanner和MediaScannerClient對單個媒體文件的掃描處理過程。

      本文分析MediaScanner對單個文件的掃描過程。單個文件的掃描是MediaScanner的基礎(chǔ),對路徑的掃描也要用到對Media文件的掃描。本文從MediaScannerService的scanFile入口開始,詳細分析了MediaScanner和MediaScannerClient對單個媒體文件的掃描處理過程。

       

      一、MediaScannerService.scanFile()


      上文對MediaScannerService的分析,知道對單個文件的掃描是調(diào)用MediaScannerService.scanFile()完成的。下面看scanFile()的實現(xiàn):

      MediaScannerService.scanFile

      scanFile()中判斷如果是外部媒體文件(只掃描外部媒體文件),創(chuàng)建MediaScanner(定義在frameworks/base/media/java/android/media)實例,并設(shè)置locale信息,然后調(diào)用MediaScanner的scanSingleFile()開始掃描。


      二、MediaScanner.scanSingleFile()

       

      MediaScanner.scanSingleFile()是具體的實現(xiàn)??此瓿傻墓ぷ鳎?/p>

      MediaScanner.scanSingleFile

      順序執(zhí)行了

      •  initialize(); 3.1節(jié)中講解該方法的工作;
      •  prescan(); 3.2節(jié)中講解該方法的工作;
      •  MyMediaScannerClient.doScanFile() 3.3節(jié)中講解該方法的工作。

      下面分章節(jié)著重講解這些方法里面都做了哪些工作。


      三、MediaScanner


      位于/framework/base/media/java/android/media/。


       

      3.1 MediaScanner.initialize(volumeName: String)

      initialize()對MediaScanner的MediaProvider/Audio/Video/Image等媒體庫的URI進行初始化獲取,要獲取的屬性有下面這些:

      MediaScanner initialize properties

      另外,如果掃描的是外部volume,要處理playlist和genre,所以mProcessPlaylists和mProcessGenres被設(shè)置為true;創(chuàng)建mGenreCache;獲取Genres和playlists的URI。


       

      3.2 MediaScanner.prescan()

      1. 從Audio、Video和Image各自的數(shù)據(jù)庫中分別讀取出這些媒體文件信息(ID,Path, Modified time),寫入mFileCache: HashMap<String,FileCacheEntry>中;
      2. 從Playlist數(shù)據(jù)庫中讀取出播放列表文件信息(ID,Path, Modified time),寫入mFileCache: HashMap<String,FileCacheEntry>中;

      注意:新創(chuàng)建的FileCacheEntry的mSeenInFileSystem缺省值為false。


      3.3 MyMediaScannerClient.doScanFile()

      MyMediaScannerClient是MediaScanner的內(nèi)部類,實現(xiàn)了MediaScannerClient。

      MyMediaScannerClient

      MyMediaScannerClient提供了doScanFile()方法供外部調(diào)用。另外實現(xiàn)了MediaScannerClient這個Interface,這個Interface在JNI實現(xiàn)中非常重要,講到那里時再詳細闡述。

      •  doScanFile()中調(diào)用beginFile(),獲取FileType和MimeType信息,并初始化內(nèi)部結(jié)構(gòu);
      •  如果返回了FileCacheEntry,并且不是Image文件,調(diào)用JNI方法processFile()解析到具體的文件信息在MyMediaScannerClient中;
      •  調(diào)用endFile()做后續(xù)的媒體庫更新等處理。

       

      3.3.1 beginFile()

      參數(shù):path:String; mimeType: String; lastModified: long, fileSize: long

      1.  用MediaFile獲取FileType和MimeType,并分別賦值給mFileType和mMimeType;
      2.  從mFileCache中獲?。ㄎ募呀?jīng)在數(shù)據(jù)庫中了:3.2preScan()中已經(jīng)把數(shù)據(jù)庫中的文件都寫入到mFileCache),或生成新的entry:FileCacheEntry,加入到mFileCache中;
      3.  設(shè)置entry:FileCacheEntry的屬性mSeenInFileSystem為 true【掃描到了該文件】;
      4.  如果是播放列表文件,加入到mPlaylists:ArrayList<FileCacheEntry>中,并直接返回null;
      5.  為MyMediaScannerClient中的各個屬性(mArtist/ mAlbum / Artist / mAlbum / mTitle / mComposer / mGenre / mTrack / mYear /mDuration / mWriter / mCompliation)賦初值,為mPath / mLastModified賦值。返回 2)生成的FileCacheEntry的實例。

      3.3.2 processFile()

      JNI調(diào)用。詳細分析在文//TODO中。

      3.3.3 endFile(entry: FileCacheEntry, …)

      • 1) 根據(jù)mFileType(Audio/Video/Images),選擇不同的數(shù)據(jù)庫,并把相應(yīng)的URI賦值給entry.mTableUri;
      • 2) 寫入values:ContentValues信息
        • ①分別用MediaScannerClient中的下面各個屬性值,初始化values:

      •  MediaStore.MediaColumns.DATA: mPath
      •  MediaStore.MediaColumns.TITLE: mTitle
      •  MediaStore.MediaColumns.DATE_MODIFIED: mLastModifed
      •  MediaStore.MediaColumns.SIZE: mFileSize
      •  MediaStore.MediaColumns.MIME_TYPE: mMimeType
      •  對于Video文件

      o  MediaStore.MediaColumns.ARTIST: mArtist/MediaStore.UNKNOWN_STRING

      o  MediaStore.MediaColumns.ALBUM: mAlbum/ MediaStore.UNKNOWN_STRING

      o  MediaStore.MediaColumns.DURATION: mDuration

      •  對于Audio文件

      o  MediaStore.MediaColumns.ARTIST: mArtist/MediaStore.UNKNOWN_STRING

      o  MediaStore.MediaColumns.ALBUM_ARTIST: mAlbumArtist/MediaStore.UNKNOWN_STRING

      o  MediaStore.MediaColumns.ALBUM: mAlbum/ MediaStore.UNKNOWN_STRING

      o  MediaStore.MediaColumns.COMPOSER: mComposer

      o  MediaStore.MediaColumns.YEAR: mYear

      o  MediaStore.MediaColumns.TRACK: mTrack

      o  MediaStore.MediaColumns.DURATION: mDuration

      o  MediaStore.MediaColumns.COMPILATION: mCompilation

        • ②對Title和Album做特殊處理
          •  如果Title為空,從MediaStore.MediaColumns.DATA:mPath 中分離出文件名(不含路徑和后綴名),賦到value的MediaStore.MediaColumns.TITLE里;
          •  如果Album為MediaStore.UNKNOWN_STRING也就是文件中不含有Album信息,把MediaStore.MediaColumns.DATA:mPath 的父目錄名賦到value的MediaStore.MediaColumns.ALBUM里。

        • ③對于Audio和JPG文件做一些特殊處理

      新加入的Audio,寫入下列信息:

      •  MediaStore.Audio.Media.IS_RINGTONE: ringtones
      •  MediaStore.Audio.Media.IS_NOTIFICATION: notifications
      •  MediaStore.Audio.Media.IS_ALARM: alarms
      •  MediaStore.Audio.Media.IS_MUSIC: music
      •  MediaStore.Audio.Media.IS_PODCAST: podcasts

      對于JPG文件,用android.media.ExifInterface獲得下列信息:

      •  MediaStore.Images.Media.LATITUDE;
      •  MediaStore.Images.Media.LONGTITUDE;
      •  MediaStore.Images.Media.DATE_TAKEN: gps dateTime;
      •  MediaStore.Images.Media.ORIENTATION。

      • 3) 用2)中的values添加或更新1) 中URI指向的Audio/Video/Images數(shù)據(jù)庫。
      • 4) 如果要處理Genres(判斷標志mProcessGenres,外部媒體都要處理),

        1. 用Genre的名字mGenre查詢Genres的數(shù)據(jù)庫,更新或插入一條由把mGenre賦給MediaStore.Audio.Genres.NAME字段組成的記錄到MediaStore.Audio.Genres數(shù)據(jù)庫中,并返回URI;
        2. 把 {genre, MediaStore.Audio.Genres.Members.CONTENT_DIRECTORY}加入mGenreCache:HashMap<String, Uri>中;
        3. 當前文件所在媒體庫中的rowId賦值給MediaStore.Audio.Genres.Members.AUDIO_ID字段,組成一條記錄插入到MediaStore.Audio.Genres.Members數(shù)據(jù)庫中。

      更新一個媒體文件所屬的Genre,需要更新Genres數(shù)據(jù)庫,和Genres數(shù)據(jù)庫對應(yīng)的記錄所在的Genres.Members數(shù)據(jù)庫。

      • 5) 對notification/ringtone/alarm進行處理
      • 如果是notification/ringtone/alarm,并且還未設(shè)置notification/ringtone/alarm,那么設(shè)置Settings.System的Settings.System.NOTIFICATION_SOUND/ RINGTONE / ALARM_ALERT為媒體數(shù)據(jù)庫的Uri形式。

      • 6) 返回媒體數(shù)據(jù)庫的Uri。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多