From:http://blog.csdn.net/fengye810130/article/details/9118221
<div><span class="pln"><span class="pln"> modified</span></span><span class="pun" style="color:#0;"><span class="pun">:</span></span><span class="pln"><span class="pln"> frameworks</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="kwd" style="color:#0;"><span class="kwd">base</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">media</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">java</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">android</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">media</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="typ" style="color:#0;"><span class="typ">MediaScanner</span></span><span class="pun" style="color:#0;"><span class="pun">.</span></span><span class="pln"><span class="pln">java</span></span></div><div><span class="pln"><span class="pln"> modified</span></span><span class="pun" style="color:#0;"><span class="pun">:</span></span><span class="pln"><span class="pln"> frameworks</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="kwd" style="color:#0;"><span class="kwd">base</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">media</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">java</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">android</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="pln"><span class="pln">media</span></span><span class="pun" style="color:#0;"><span class="pun">/</span></span><span class="typ" style="color:#0;"><span class="typ">MiniThumbFile</span></span><span class="pun" style="color:#0;"><span class="pun">.</span></span><span class="pln"><span class="pln">java</span></span></div>
<div class="dp-highlighter bg_java" sizcache="27" sizset="60"><div class="bar" sizcache="27" sizset="60"><div class="tools" sizcache="27" sizset="60"><strong>[java]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/fengye810130/article/details/9118221#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">print</a><a target=_blank title="?" class="About" href="http://blog.csdn.net/fengye810130/article/details/9118221#">?</a></div></div><ol class="dp-j"><li class="alt"><span><span><PRE </span><span class="keyword">class</span><span>=java name=</span><span class="string">"code"</span><span>></span><span class="comment">/**</span> </span></li><li><span><span class="comment">@@ -85,16 +89,34 @@ public class MiniThumbFile {</span> </span></li><li class="alt"><span><span class="comment"> /*add 1 on google's version.*/</span><span> </span></span></li><li><span> </span><span class="comment">/*this version add check code for thumbdata.*/</span><span> </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> MINI_THUMB_DATA_FILE_VERSION = </span><span class="number">3</span><span> + </span><span class="number">1</span><span>; </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> BYTES_PER_MINTHUMB = </span><span class="number">17000</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> BYTES_PER_MINTHUMB = </span><span class="number">17000</span><span>; </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> HEADER_SIZE = </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> Uri mUri; </span></li><li><span> </span><span class="keyword">private</span><span> RandomAccessFile mMiniThumbFile; </span></li><li class="alt"><span> Map<Long,RandomAccessFile> mMiniThumbFilesMap = Collections.synchronizedMap(</span><span class="keyword">new</span><span> HashMap<Long,RandomAccessFile>(</span><span class="number">5</span><span>)); </span></li><li><span> </span><span class="keyword">private</span><span> FileChannel mChannel; </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> ByteBuffer mBuffer; </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> Hashtable<String, MiniThumbFile> sThumbFiles = </span></li><li class="alt"><span> </span><span class="keyword">new</span><span> Hashtable<String, MiniThumbFile>(); </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> java.util.zip.Adler32 sChecker = </span><span class="keyword">new</span><span> Adler32(); </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> UNKNOWN_CHECK_CODE = -</span><span class="number">1</span><span>; </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">char</span><span> SEPERATE_CHAR=</span><span class="string">'_'</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String[] parseFileName(String fileName) </span></li><li><span> { </span></li><li class="alt"><span> String str=fileName; </span></li><li><span> </span><span class="keyword">if</span><span>(fileName==</span><span class="keyword">null</span><span>) </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li><span> </span><span class="keyword">int</span><span> index=fileName.lastIndexOf(</span><span class="string">"/"</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span>(index!=-</span><span class="number">1</span><span>) </span></li><li><span> { </span></li><li class="alt"><span> str=fileName.substring(index+</span><span class="number">1</span><span>); </span></li><li><span> } </span></li><li class="alt"><span> String strs[]=str.split(SEPERATE_CHAR+</span><span class="string">""</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span>(strs==</span><span class="keyword">null</span><span>||strs.length!=</span><span class="number">4</span><span>||(!str.startsWith(</span><span class="string">".thumbdata"</span><span>))) </span></li><li class="alt"><span> { </span></li><li><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">return</span><span> strs; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="comment">/**</span> </li><li class="alt"><span><span class="comment"> * We store different types of thumbnails in different files. To remain backward compatibility,</span> </span></li><li><span><span class="comment"> * we should hashcode of content://media/external/images/media remains the same.</span> </span></li><li class="alt"><span><span class="comment">@@ -105,7 +127,18 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> sThumbFiles.clear();</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"></span> </span></li><li><span><span class="comment"> private final static long getMiniThumbFileId(long id)</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (id>>8);</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> public final static int getMiniThumbDataFileBlockNum()</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (1<<8);</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> private final static long getPositionInMiniThumbFile(long id)</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (id&0xff)*BYTES_PER_MINTHUMB;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> public static synchronized MiniThumbFile instance(Uri uri) {</span> </span></li><li class="alt"><span><span class="comment"> String type = uri.getPathSegments().get(1);</span> </span></li><li><span><span class="comment"> MiniThumbFile file = sThumbFiles.get(type);</span> </span></li><li class="alt"><span><span class="comment">@@ -120,10 +153,11 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> private String randomAccessFilePath(int version) {</span> </span></li><li><span><span class="comment"> String type = mUri.getPathSegments().get(1);</span> </span></li><li class="alt"><span><span class="comment"> String directoryName =</span> </span></li><li><span><span class="comment"> Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails";</span> </span></li><li class="alt"><span><span class="comment"> return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode();</span> </span></li><li><span><span class="comment"> return directoryName + "/.thumbdata" + version + SEPERATE_CHAR + mUri.hashCode()+SEPERATE_CHAR+type;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> /**</span> </span></li><li class="alt"><span><span class="comment">@@ -131,18 +165,18 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> * @param uri the Uri same as instance(Uri uri).</span> </span></li><li class="alt"><span><span class="comment"> * @return</span> </span></li><li><span><span class="comment"> */</span><span> </span></span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String getThumbdataPath(Uri uri) { </span></li><li><span> </span><span class="comment">/*public static String getThumbdataPath(Uri uri) {</span> </li><li class="alt"><span><span class="comment"> String type = uri.getPathSegments().get(1);</span> </span></li><li><span><span class="comment"> Uri thumbFileUri = Uri.parse("content://media/external/" + type + "/media");</span> </span></li><li class="alt"><span><span class="comment"> String directoryName = Environment.getExternalStorageDirectory().toString()</span> </span></li><li><span><span class="comment"> + "/DCIM/.thumbnails";</span> </span></li><li class="alt"><span><span class="comment"> String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION + "-" + thumbFileUri.hashCode();</span> </span></li><li><span><span class="comment"> String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION +SEPERATE_CHAR + thumbFileUri.hashCode()+SEPERATE_CHAR+type;</span> </span></li><li class="alt"><span><span class="comment"> if (LOG) Log.i(TAG, "getThumbdataPath(" + uri + ") return " + path);</span> </span></li><li><span><span class="comment"> return path;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> }*/</span><span> </span></span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> removeOldFile() { </span></li><li><span> String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - </span><span class="number">1</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> removeOldMiniThumbDataFile(</span><span class="keyword">long</span><span> miniThumbDataFileId) { </span></li><li><span> String oldPath =getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION - </span><span class="number">1</span><span>,miniThumbDataFileId); </span></li><li class="alt"><span> File oldFile = </span><span class="keyword">new</span><span> File(oldPath); </span></li><li><span> </span><span class="keyword">if</span><span> (oldFile.exists()) { </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span>@@ -</span><span class="number">152</span><span>,</span><span class="number">35</span><span> +</span><span class="number">186</span><span>,</span><span class="number">43</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile() { </span></li><li><span> </span><span class="keyword">if</span><span> (mMiniThumbFile == </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span> removeOldFile(); </span></li><li><span> String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION); </span></li><li class="alt"><span> File directory = </span><span class="keyword">new</span><span> File(path).getParentFile(); </span></li><li><span> </span><span class="keyword">if</span><span> (!directory.isDirectory()) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (!directory.mkdirs()) { </span></li><li><span> Log.e(TAG, </span><span class="string">"Unable to create .thumbnails directory "</span><span> </span></li><li class="alt"><span> + directory.toString()); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">private</span><span> String getMiniThumbDataFilePath(</span><span class="keyword">int</span><span> version,</span><span class="keyword">long</span><span> miniThumbDataFileId) </span></li><li class="alt"><span> { </span></li><li><span> </span><span class="keyword">return</span><span> randomAccessFilePath(version)+SEPERATE_CHAR+miniThumbDataFileId; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile(</span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId) { </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">false</span><span>); </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile(</span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId,</span><span class="keyword">boolean</span><span> onlyRead) { </span></li><li><span> RandomAccessFile miniThumbFile=mMiniThumbFilesMap.get(miniThumbDataFileId); </span></li><li class="alt"><span> String path = getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION,miniThumbDataFileId); </span></li><li><span> File f = </span><span class="keyword">new</span><span> File(path); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (miniThumbFile == </span><span class="keyword">null</span><span>||!f.exists()) { </span></li><li><span> </span><span class="keyword">if</span><span>(onlyRead) </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li><span> removeOldMiniThumbDataFile(miniThumbDataFileId); </span></li><li class="alt"><span> File directory = </span><span class="keyword">new</span><span> File(path).getParentFile(); </span></li><li><span> </span><span class="keyword">if</span><span> (!directory.isDirectory()) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (!directory.mkdirs()) { </span></li><li><span> Log.e(TAG, </span><span class="string">"Unable to create .thumbnails directory "</span><span> </span></li><li class="alt"><span> + directory.toString()); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mMiniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"rw"</span><span>); </span></li><li class="alt"><span> miniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"rw"</span><span>); </span></li><li><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li class="alt"><span> </span><span class="comment">// Open as read-only so we can at least read the existing </span><span> </span></li><li><span> </span><span class="comment">// thumbnails. </span><span> </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mMiniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"r"</span><span>); </span></li><li class="alt"><span> miniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"r"</span><span>); </span></li><li><span> } </span><span class="keyword">catch</span><span> (IOException ex2) { </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mMiniThumbFile != </span><span class="keyword">null</span><span>) { </span></li><li><span> mChannel = mMiniThumbFile.getChannel(); </span></li><li class="alt"><span> } </span></li><li><span> mMiniThumbFilesMap.put(miniThumbDataFileId, miniThumbFile); </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">return</span><span> mMiniThumbFile; </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> miniThumbFile; </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> MiniThumbFile(Uri uri) { </span></li><li><span>@@ -</span><span class="number">189</span><span>,</span><span class="number">10</span><span> +</span><span class="number">231</span><span>,</span><span class="number">19</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">void</span><span> deactivate() { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mMiniThumbFile != </span><span class="keyword">null</span><span>) { </span></li><li><span> </span><span class="keyword">if</span><span> (mMiniThumbFilesMap != </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span> Set<Long> keySet=mMiniThumbFilesMap.keySet(); </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> mMiniThumbFile.close(); </span></li><li><span> mMiniThumbFile = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">for</span><span>(Long key:keySet) </span></li><li><span> { </span></li><li class="alt"><span> RandomAccessFile file=mMiniThumbFilesMap.get(key); </span></li><li><span> </span><span class="keyword">if</span><span>(file!=</span><span class="keyword">null</span><span>) </span></li><li class="alt"><span> { </span></li><li><span> mMiniThumbFilesMap.put(key, </span><span class="keyword">null</span><span>); </span></li><li class="alt"><span> file.close(); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> mMiniThumbFilesMap.clear(); </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li><span> </span><span class="comment">// ignore exception </span><span> </span></li><li class="alt"><span> } </span></li><li><span>@@ -</span><span class="number">205</span><span>,</span><span class="number">18</span><span> +</span><span class="number">256</span><span>,</span><span class="number">20</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> </span><span class="comment">// check the mini thumb file for the right data. Right is </span><span> </span></li><li><span> </span><span class="comment">// defined as having the right magic number at the offset </span><span> </span></li><li class="alt"><span> </span><span class="comment">// reserved for this "id". </span><span> </span></li><li><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li class="alt"><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">true</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (r != </span><span class="keyword">null</span><span>) { </span></li><li><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> mBuffer.clear(); </span></li><li><span> mBuffer.limit(</span><span class="number">1</span><span> + </span><span class="number">8</span><span>); </span></li><li class="alt"><span> lock = mChannel.lock(pos, </span><span class="number">1</span><span> + </span><span class="number">8</span><span>, </span><span class="keyword">true</span><span>); </span></li><li><span> lock = channel.lock(pos, </span><span class="number">1</span><span> + </span><span class="number">8</span><span>, </span><span class="keyword">true</span><span>); </span></li><li class="alt"><span> </span><span class="comment">// check that we can read the following 9 bytes </span><span> </span></li><li><span> </span><span class="comment">// (1 for the "status" and 8 for the long) </span><span> </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mChannel.read(mBuffer, pos) == </span><span class="number">9</span><span>) { </span></li><li><span> </span><span class="keyword">if</span><span> (channel.read(mBuffer, pos) == </span><span class="number">9</span><span>) { </span></li><li class="alt"><span> mBuffer.position(</span><span class="number">0</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span> (mBuffer.get() == </span><span class="number">1</span><span>) { </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> mBuffer.getLong(); </span></li><li><span>@@ -</span><span class="number">242</span><span>,</span><span class="number">10</span><span> +</span><span class="number">295</span><span>,</span><span class="number">12</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">void</span><span> saveMiniThumbToFile(</span><span class="keyword">byte</span><span>[] data, </span><span class="keyword">long</span><span> id, </span><span class="keyword">long</span><span> magic) </span></li><li><span> </span><span class="keyword">throws</span><span> IOException { </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId); </span></li><li><span> </span><span class="keyword">if</span><span> (r == </span><span class="keyword">null</span><span>) </span><span class="keyword">return</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> </span><span class="keyword">if</span><span> (data != </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span>@@ -</span><span class="number">266</span><span>,</span><span class="number">14</span><span> +</span><span class="number">321</span><span>,</span><span class="number">13</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li><span> check = sChecker.getValue(); </span></li><li class="alt"><span> } </span></li><li><span> mBuffer.putLong(check); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"saveMiniThumbToFile("</span><span> + id + </span><span class="string">") flag=1, magic="</span><span> </span></li><li><span> + magic + </span><span class="string">", length="</span><span> + data.length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span></li><li><span> mBuffer.put(data); </span></li><li class="alt"><span> mBuffer.flip(); </span></li><li><span> lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">false</span><span>); </span></li><li class="alt"><span> mChannel.write(mBuffer, pos); </span></li><li><span> lock = channel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">false</span><span>); </span></li><li class="alt"><span> channel.write(mBuffer, pos); </span></li><li><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"saveMiniThumbToFile("</span><span> + id + </span><span class="string">") flag=1, magic="</span><span> </span></li><li class="alt"><span> + magic + </span><span class="string">", length="</span><span> + data.length + </span><span class="string">", check="</span><span> + check); </span></li><li><span> } </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li><span> Log.e(TAG, </span><span class="string">"couldn't save mini thumbnail data for "</span><span> </span></li><li class="alt"><span>@@ -</span><span class="number">319</span><span>,</span><span class="number">27</span><span> +</span><span class="number">373</span><span>,</span><span class="number">29</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li><span> * </span><span class="annotation">@return</span><span> </span></li><li class="alt"><span> */ </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">byte</span><span>[] getMiniThumbFromFile(</span><span class="keyword">long</span><span> id, </span><span class="keyword">byte</span><span> [] data, ThumbResult result) { </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span> (r == </span><span class="keyword">null</span><span>) </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mBuffer.clear(); </span></li><li class="alt"><span> lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">int</span><span> size = mChannel.read(mBuffer, pos); </span></li><li class="alt"><span> lock = channel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">int</span><span> size = channel.read(mBuffer, pos); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (size > </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span>) { </span><span class="comment">// flag, magic, length, check code </span><span> </span></li><li><span> mBuffer.position(</span><span class="number">0</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">byte</span><span> flag = mBuffer.get(); </span></li><li><span> </span><span class="keyword">long</span><span> magic = mBuffer.getLong(); </span></li><li class="alt"><span> </span><span class="keyword">int</span><span> length = mBuffer.getInt(); </span></li><li><span> </span><span class="keyword">long</span><span> check = mBuffer.getLong(); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"getMiniThumbFromFile("</span><span> + id + </span><span class="string">") flag="</span><span> + flag </span></li><li><span> + </span><span class="string">", magic="</span><span> + magic + </span><span class="string">", length="</span><span> + length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span></li><li><span> </span><span class="keyword">long</span><span> newCheck = UNKNOWN_CHECK_CODE; </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (size >= </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span> + length && data.length >= length) { </span></li><li><span> mBuffer.get(data, </span><span class="number">0</span><span>, length); </span></li><li class="alt"><span> Log.i(TAG, </span><span class="string">" success to getMiniThumbFromFile("</span><span> + id + </span><span class="string">") flag="</span><span> + flag </span></li><li><span> + </span><span class="string">", magic="</span><span> + magic + </span><span class="string">", length="</span><span> + length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span><span class="keyword">synchronized</span><span> (sChecker) { </span></li><li><span> sChecker.reset(); </span></li><li class="alt"><span> sChecker.update(data, </span><span class="number">0</span><span>, length);</PRE><BR> </span></li></ol></div><pre class="java" style="DISPLAY: none" sizcache="27" sizset="64" name="code"><div class="dp-highlighter bg_java" sizcache="27" sizset="64"><div class="bar" sizcache="27" sizset="64"><div class="tools" sizcache="27" sizset="64"><strong>[java]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/fengye810130/article/details/9118221#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">print</a><a target=_blank title="?" class="About" href="http://blog.csdn.net/fengye810130/article/details/9118221#">?</a></div></div><ol class="dp-j"><li class="alt"><span><span class="comment">/**</span> </span></li><li><span><span class="comment">@@ -85,16 +89,34 @@ public class MiniThumbFile {</span> </span></li><li class="alt"><span><span class="comment"> /*add 1 on google's version.*/</span><span> </span></span></li><li><span> </span><span class="comment">/*this version add check code for thumbdata.*/</span><span> </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> MINI_THUMB_DATA_FILE_VERSION = </span><span class="number">3</span><span> + </span><span class="number">1</span><span>; </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> BYTES_PER_MINTHUMB = </span><span class="number">17000</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> BYTES_PER_MINTHUMB = </span><span class="number">17000</span><span>; </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">int</span><span> HEADER_SIZE = </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> Uri mUri; </span></li><li><span> </span><span class="keyword">private</span><span> RandomAccessFile mMiniThumbFile; </span></li><li class="alt"><span> Map<Long,RandomAccessFile> mMiniThumbFilesMap = Collections.synchronizedMap(</span><span class="keyword">new</span><span> HashMap<Long,RandomAccessFile>(</span><span class="number">5</span><span>)); </span></li><li><span> </span><span class="keyword">private</span><span> FileChannel mChannel; </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> ByteBuffer mBuffer; </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> Hashtable<String, MiniThumbFile> sThumbFiles = </span></li><li class="alt"><span> </span><span class="keyword">new</span><span> Hashtable<String, MiniThumbFile>(); </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> java.util.zip.Adler32 sChecker = </span><span class="keyword">new</span><span> Adler32(); </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> UNKNOWN_CHECK_CODE = -</span><span class="number">1</span><span>; </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">char</span><span> SEPERATE_CHAR=</span><span class="string">'_'</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String[] parseFileName(String fileName) </span></li><li><span> { </span></li><li class="alt"><span> String str=fileName; </span></li><li><span> </span><span class="keyword">if</span><span>(fileName==</span><span class="keyword">null</span><span>) </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li><span> </span><span class="keyword">int</span><span> index=fileName.lastIndexOf(</span><span class="string">"/"</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span>(index!=-</span><span class="number">1</span><span>) </span></li><li><span> { </span></li><li class="alt"><span> str=fileName.substring(index+</span><span class="number">1</span><span>); </span></li><li><span> } </span></li><li class="alt"><span> String strs[]=str.split(SEPERATE_CHAR+</span><span class="string">""</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span>(strs==</span><span class="keyword">null</span><span>||strs.length!=</span><span class="number">4</span><span>||(!str.startsWith(</span><span class="string">".thumbdata"</span><span>))) </span></li><li class="alt"><span> { </span></li><li><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">return</span><span> strs; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="comment">/**</span> </li><li class="alt"><span><span class="comment"> * We store different types of thumbnails in different files. To remain backward compatibility,</span> </span></li><li><span><span class="comment"> * we should hashcode of content://media/external/images/media remains the same.</span> </span></li><li class="alt"><span><span class="comment">@@ -105,7 +127,18 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> sThumbFiles.clear();</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"></span> </span></li><li><span><span class="comment"> private final static long getMiniThumbFileId(long id)</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (id>>8);</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> public final static int getMiniThumbDataFileBlockNum()</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (1<<8);</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> private final static long getPositionInMiniThumbFile(long id)</span> </span></li><li class="alt"><span><span class="comment"> {</span> </span></li><li><span><span class="comment"> return (id&0xff)*BYTES_PER_MINTHUMB;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> public static synchronized MiniThumbFile instance(Uri uri) {</span> </span></li><li class="alt"><span><span class="comment"> String type = uri.getPathSegments().get(1);</span> </span></li><li><span><span class="comment"> MiniThumbFile file = sThumbFiles.get(type);</span> </span></li><li class="alt"><span><span class="comment">@@ -120,10 +153,11 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> private String randomAccessFilePath(int version) {</span> </span></li><li><span><span class="comment"> String type = mUri.getPathSegments().get(1);</span> </span></li><li class="alt"><span><span class="comment"> String directoryName =</span> </span></li><li><span><span class="comment"> Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails";</span> </span></li><li class="alt"><span><span class="comment"> return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode();</span> </span></li><li><span><span class="comment"> return directoryName + "/.thumbdata" + version + SEPERATE_CHAR + mUri.hashCode()+SEPERATE_CHAR+type;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> /**</span> </span></li><li class="alt"><span><span class="comment">@@ -131,18 +165,18 @@ public class MiniThumbFile {</span> </span></li><li><span><span class="comment"> * @param uri the Uri same as instance(Uri uri).</span> </span></li><li class="alt"><span><span class="comment"> * @return</span> </span></li><li><span><span class="comment"> */</span><span> </span></span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String getThumbdataPath(Uri uri) { </span></li><li><span> </span><span class="comment">/*public static String getThumbdataPath(Uri uri) {</span> </li><li class="alt"><span><span class="comment"> String type = uri.getPathSegments().get(1);</span> </span></li><li><span><span class="comment"> Uri thumbFileUri = Uri.parse("content://media/external/" + type + "/media");</span> </span></li><li class="alt"><span><span class="comment"> String directoryName = Environment.getExternalStorageDirectory().toString()</span> </span></li><li><span><span class="comment"> + "/DCIM/.thumbnails";</span> </span></li><li class="alt"><span><span class="comment"> String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION + "-" + thumbFileUri.hashCode();</span> </span></li><li><span><span class="comment"> String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION +SEPERATE_CHAR + thumbFileUri.hashCode()+SEPERATE_CHAR+type;</span> </span></li><li class="alt"><span><span class="comment"> if (LOG) Log.i(TAG, "getThumbdataPath(" + uri + ") return " + path);</span> </span></li><li><span><span class="comment"> return path;</span> </span></li><li class="alt"><span><span class="comment"> }</span> </span></li><li><span><span class="comment"> }*/</span><span> </span></span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> removeOldFile() { </span></li><li><span> String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - </span><span class="number">1</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> removeOldMiniThumbDataFile(</span><span class="keyword">long</span><span> miniThumbDataFileId) { </span></li><li><span> String oldPath =getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION - </span><span class="number">1</span><span>,miniThumbDataFileId); </span></li><li class="alt"><span> File oldFile = </span><span class="keyword">new</span><span> File(oldPath); </span></li><li><span> </span><span class="keyword">if</span><span> (oldFile.exists()) { </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span>@@ -</span><span class="number">152</span><span>,</span><span class="number">35</span><span> +</span><span class="number">186</span><span>,</span><span class="number">43</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile() { </span></li><li><span> </span><span class="keyword">if</span><span> (mMiniThumbFile == </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span> removeOldFile(); </span></li><li><span> String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION); </span></li><li class="alt"><span> File directory = </span><span class="keyword">new</span><span> File(path).getParentFile(); </span></li><li><span> </span><span class="keyword">if</span><span> (!directory.isDirectory()) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (!directory.mkdirs()) { </span></li><li><span> Log.e(TAG, </span><span class="string">"Unable to create .thumbnails directory "</span><span> </span></li><li class="alt"><span> + directory.toString()); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">private</span><span> String getMiniThumbDataFilePath(</span><span class="keyword">int</span><span> version,</span><span class="keyword">long</span><span> miniThumbDataFileId) </span></li><li class="alt"><span> { </span></li><li><span> </span><span class="keyword">return</span><span> randomAccessFilePath(version)+SEPERATE_CHAR+miniThumbDataFileId; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile(</span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId) { </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">false</span><span>); </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> RandomAccessFile miniThumbDataFile(</span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId,</span><span class="keyword">boolean</span><span> onlyRead) { </span></li><li><span> RandomAccessFile miniThumbFile=mMiniThumbFilesMap.get(miniThumbDataFileId); </span></li><li class="alt"><span> String path = getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION,miniThumbDataFileId); </span></li><li><span> File f = </span><span class="keyword">new</span><span> File(path); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (miniThumbFile == </span><span class="keyword">null</span><span>||!f.exists()) { </span></li><li><span> </span><span class="keyword">if</span><span>(onlyRead) </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li><span> removeOldMiniThumbDataFile(miniThumbDataFileId); </span></li><li class="alt"><span> File directory = </span><span class="keyword">new</span><span> File(path).getParentFile(); </span></li><li><span> </span><span class="keyword">if</span><span> (!directory.isDirectory()) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (!directory.mkdirs()) { </span></li><li><span> Log.e(TAG, </span><span class="string">"Unable to create .thumbnails directory "</span><span> </span></li><li class="alt"><span> + directory.toString()); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mMiniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"rw"</span><span>); </span></li><li class="alt"><span> miniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"rw"</span><span>); </span></li><li><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li class="alt"><span> </span><span class="comment">// Open as read-only so we can at least read the existing </span><span> </span></li><li><span> </span><span class="comment">// thumbnails. </span><span> </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mMiniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"r"</span><span>); </span></li><li class="alt"><span> miniThumbFile = </span><span class="keyword">new</span><span> RandomAccessFile(f, </span><span class="string">"r"</span><span>); </span></li><li><span> } </span><span class="keyword">catch</span><span> (IOException ex2) { </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mMiniThumbFile != </span><span class="keyword">null</span><span>) { </span></li><li><span> mChannel = mMiniThumbFile.getChannel(); </span></li><li class="alt"><span> } </span></li><li><span> mMiniThumbFilesMap.put(miniThumbDataFileId, miniThumbFile); </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">return</span><span> mMiniThumbFile; </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> miniThumbFile; </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> MiniThumbFile(Uri uri) { </span></li><li><span>@@ -</span><span class="number">189</span><span>,</span><span class="number">10</span><span> +</span><span class="number">231</span><span>,</span><span class="number">19</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">void</span><span> deactivate() { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mMiniThumbFile != </span><span class="keyword">null</span><span>) { </span></li><li><span> </span><span class="keyword">if</span><span> (mMiniThumbFilesMap != </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span> Set<Long> keySet=mMiniThumbFilesMap.keySet(); </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> mMiniThumbFile.close(); </span></li><li><span> mMiniThumbFile = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">for</span><span>(Long key:keySet) </span></li><li><span> { </span></li><li class="alt"><span> RandomAccessFile file=mMiniThumbFilesMap.get(key); </span></li><li><span> </span><span class="keyword">if</span><span>(file!=</span><span class="keyword">null</span><span>) </span></li><li class="alt"><span> { </span></li><li><span> mMiniThumbFilesMap.put(key, </span><span class="keyword">null</span><span>); </span></li><li class="alt"><span> file.close(); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> mMiniThumbFilesMap.clear(); </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li><span> </span><span class="comment">// ignore exception </span><span> </span></li><li class="alt"><span> } </span></li><li><span>@@ -</span><span class="number">205</span><span>,</span><span class="number">18</span><span> +</span><span class="number">256</span><span>,</span><span class="number">20</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> </span><span class="comment">// check the mini thumb file for the right data. Right is </span><span> </span></li><li><span> </span><span class="comment">// defined as having the right magic number at the offset </span><span> </span></li><li class="alt"><span> </span><span class="comment">// reserved for this "id". </span><span> </span></li><li><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li class="alt"><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">true</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (r != </span><span class="keyword">null</span><span>) { </span></li><li><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> mBuffer.clear(); </span></li><li><span> mBuffer.limit(</span><span class="number">1</span><span> + </span><span class="number">8</span><span>); </span></li><li class="alt"><span> lock = mChannel.lock(pos, </span><span class="number">1</span><span> + </span><span class="number">8</span><span>, </span><span class="keyword">true</span><span>); </span></li><li><span> lock = channel.lock(pos, </span><span class="number">1</span><span> + </span><span class="number">8</span><span>, </span><span class="keyword">true</span><span>); </span></li><li class="alt"><span> </span><span class="comment">// check that we can read the following 9 bytes </span><span> </span></li><li><span> </span><span class="comment">// (1 for the "status" and 8 for the long) </span><span> </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (mChannel.read(mBuffer, pos) == </span><span class="number">9</span><span>) { </span></li><li><span> </span><span class="keyword">if</span><span> (channel.read(mBuffer, pos) == </span><span class="number">9</span><span>) { </span></li><li class="alt"><span> mBuffer.position(</span><span class="number">0</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span> (mBuffer.get() == </span><span class="number">1</span><span>) { </span></li><li class="alt"><span> </span><span class="keyword">return</span><span> mBuffer.getLong(); </span></li><li><span>@@ -</span><span class="number">242</span><span>,</span><span class="number">10</span><span> +</span><span class="number">295</span><span>,</span><span class="number">12</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li class="alt"><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">void</span><span> saveMiniThumbToFile(</span><span class="keyword">byte</span><span>[] data, </span><span class="keyword">long</span><span> id, </span><span class="keyword">long</span><span> magic) </span></li><li><span> </span><span class="keyword">throws</span><span> IOException { </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId); </span></li><li><span> </span><span class="keyword">if</span><span> (r == </span><span class="keyword">null</span><span>) </span><span class="keyword">return</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> </span><span class="keyword">if</span><span> (data != </span><span class="keyword">null</span><span>) { </span></li><li class="alt"><span>@@ -</span><span class="number">266</span><span>,</span><span class="number">14</span><span> +</span><span class="number">321</span><span>,</span><span class="number">13</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li><span> check = sChecker.getValue(); </span></li><li class="alt"><span> } </span></li><li><span> mBuffer.putLong(check); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"saveMiniThumbToFile("</span><span> + id + </span><span class="string">") flag=1, magic="</span><span> </span></li><li><span> + magic + </span><span class="string">", length="</span><span> + data.length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span></li><li><span> mBuffer.put(data); </span></li><li class="alt"><span> mBuffer.flip(); </span></li><li><span> lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">false</span><span>); </span></li><li class="alt"><span> mChannel.write(mBuffer, pos); </span></li><li><span> lock = channel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">false</span><span>); </span></li><li class="alt"><span> channel.write(mBuffer, pos); </span></li><li><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"saveMiniThumbToFile("</span><span> + id + </span><span class="string">") flag=1, magic="</span><span> </span></li><li class="alt"><span> + magic + </span><span class="string">", length="</span><span> + data.length + </span><span class="string">", check="</span><span> + check); </span></li><li><span> } </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (IOException ex) { </span></li><li><span> Log.e(TAG, </span><span class="string">"couldn't save mini thumbnail data for "</span><span> </span></li><li class="alt"><span>@@ -</span><span class="number">319</span><span>,</span><span class="number">27</span><span> +</span><span class="number">373</span><span>,</span><span class="number">29</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MiniThumbFile { </span></li><li><span> * </span><span class="annotation">@return</span><span> </span></li><li class="alt"><span> */ </span></li><li><span> </span><span class="keyword">public</span><span> </span><span class="keyword">synchronized</span><span> </span><span class="keyword">byte</span><span>[] getMiniThumbFromFile(</span><span class="keyword">long</span><span> id, </span><span class="keyword">byte</span><span> [] data, ThumbResult result) { </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(); </span></li><li><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> miniThumbDataFileId=getMiniThumbFileId(id); </span></li><li class="alt"><span> RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,</span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span> (r == </span><span class="keyword">null</span><span>) </span><span class="keyword">return</span><span> </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">long</span><span> pos = id * BYTES_PER_MINTHUMB; </span></li><li><span> </span><span class="keyword">long</span><span> pos = getPositionInMiniThumbFile(id); </span></li><li class="alt"><span> FileChannel channel=r.getChannel(); </span></li><li><span> FileLock lock = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> mBuffer.clear(); </span></li><li class="alt"><span> lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">int</span><span> size = mChannel.read(mBuffer, pos); </span></li><li class="alt"><span> lock = channel.lock(pos, BYTES_PER_MINTHUMB, </span><span class="keyword">true</span><span>); </span></li><li><span> </span><span class="keyword">int</span><span> size = channel.read(mBuffer, pos); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (size > </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span>) { </span><span class="comment">// flag, magic, length, check code </span><span> </span></li><li><span> mBuffer.position(</span><span class="number">0</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">byte</span><span> flag = mBuffer.get(); </span></li><li><span> </span><span class="keyword">long</span><span> magic = mBuffer.getLong(); </span></li><li class="alt"><span> </span><span class="keyword">int</span><span> length = mBuffer.getInt(); </span></li><li><span> </span><span class="keyword">long</span><span> check = mBuffer.getLong(); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) Log.i(TAG, </span><span class="string">"getMiniThumbFromFile("</span><span> + id + </span><span class="string">") flag="</span><span> + flag </span></li><li><span> + </span><span class="string">", magic="</span><span> + magic + </span><span class="string">", length="</span><span> + length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span></li><li><span> </span><span class="keyword">long</span><span> newCheck = UNKNOWN_CHECK_CODE; </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (size >= </span><span class="number">1</span><span> + </span><span class="number">8</span><span> + </span><span class="number">4</span><span> + </span><span class="number">8</span><span> + length && data.length >= length) { </span></li><li><span> mBuffer.get(data, </span><span class="number">0</span><span>, length); </span></li><li class="alt"><span> Log.i(TAG, </span><span class="string">" success to getMiniThumbFromFile("</span><span> + id + </span><span class="string">") flag="</span><span> + flag </span></li><li><span> + </span><span class="string">", magic="</span><span> + magic + </span><span class="string">", length="</span><span> + length + </span><span class="string">", check="</span><span> + check); </span></li><li class="alt"><span> </span><span class="keyword">synchronized</span><span> (sChecker) { </span></li><li><span> sChecker.reset(); </span></li><li class="alt"><span> sChecker.update(data, </span><span class="number">0</span><span>, length); </span></li></ol></div><pre class="java" style="DISPLAY: none" name="code">/** @@ -85,16 +89,34 @@ public class MiniThumbFile { /*add 1 on google's version.*/ /*this version add check code for thumbdata.*/ private static final int MINI_THUMB_DATA_FILE_VERSION = 3 + 1; public static final int BYTES_PER_MINTHUMB = 17000; public static final int BYTES_PER_MINTHUMB = 17000; private static final int HEADER_SIZE = 1 + 8 + 4 + 8; private Uri mUri; private RandomAccessFile mMiniThumbFile; Map<Long,RandomAccessFile> mMiniThumbFilesMap = Collections.synchronizedMap(new HashMap<Long,RandomAccessFile>(5)); private FileChannel mChannel; private ByteBuffer mBuffer; private static Hashtable<String, MiniThumbFile> sThumbFiles = new Hashtable<String, MiniThumbFile>(); private static java.util.zip.Adler32 sChecker = new Adler32(); private static final long UNKNOWN_CHECK_CODE = -1; final static char SEPERATE_CHAR='_'; public static String[] parseFileName(String fileName) { String str=fileName; if(fileName==null) return null; int index=fileName.lastIndexOf("/"); if(index!=-1) { str=fileName.substring(index+1); } String strs[]=str.split(SEPERATE_CHAR+""); if(strs==null||strs.length!=4||(!str.startsWith(".thumbdata"))) { return null; } return strs; } /** * We store different types of thumbnails in different files. To remain backward compatibility, * we should hashcode of content://media/external/images/media remains the same. @@ -105,7 +127,18 @@ public class MiniThumbFile { } sThumbFiles.clear(); } private final static long getMiniThumbFileId(long id) { return (id>>8); } public final static int getMiniThumbDataFileBlockNum() { return (1<<8); } private final static long getPositionInMiniThumbFile(long id) { return (id&0xff)*BYTES_PER_MINTHUMB; } public static synchronized MiniThumbFile instance(Uri uri) { String type = uri.getPathSegments().get(1); MiniThumbFile file = sThumbFiles.get(type); @@ -120,10 +153,11 @@ public class MiniThumbFile { } private String randomAccessFilePath(int version) { String type = mUri.getPathSegments().get(1); String directoryName = Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails"; return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode(); return directoryName + "/.thumbdata" + version + SEPERATE_CHAR + mUri.hashCode()+SEPERATE_CHAR+type; } /** @@ -131,18 +165,18 @@ public class MiniThumbFile { * @param uri the Uri same as instance(Uri uri). * @return */ public static String getThumbdataPath(Uri uri) { /*public static String getThumbdataPath(Uri uri) { String type = uri.getPathSegments().get(1); Uri thumbFileUri = Uri.parse("content://media/external/" + type + "/media"); String directoryName = Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails"; String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION + "-" + thumbFileUri.hashCode(); String path = directoryName + "/.thumbdata" + MINI_THUMB_DATA_FILE_VERSION +SEPERATE_CHAR + thumbFileUri.hashCode()+SEPERATE_CHAR+type; if (LOG) Log.i(TAG, "getThumbdataPath(" + uri + ") return " + path); return path; } }*/ private void removeOldFile() { String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - 1); private void removeOldMiniThumbDataFile(long miniThumbDataFileId) { String oldPath =getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION - 1,miniThumbDataFileId); File oldFile = new File(oldPath); if (oldFile.exists()) { try { @@ -152,35 +186,43 @@ public class MiniThumbFile { } } } private RandomAccessFile miniThumbDataFile() { if (mMiniThumbFile == null) { removeOldFile(); String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION); File directory = new File(path).getParentFile(); if (!directory.isDirectory()) { if (!directory.mkdirs()) { Log.e(TAG, "Unable to create .thumbnails directory " + directory.toString()); } } final private String getMiniThumbDataFilePath(int version,long miniThumbDataFileId) { return randomAccessFilePath(version)+SEPERATE_CHAR+miniThumbDataFileId; } private RandomAccessFile miniThumbDataFile(final long miniThumbDataFileId) { return miniThumbDataFile(miniThumbDataFileId,false); } private RandomAccessFile miniThumbDataFile(final long miniThumbDataFileId,boolean onlyRead) { RandomAccessFile miniThumbFile=mMiniThumbFilesMap.get(miniThumbDataFileId); String path = getMiniThumbDataFilePath(MINI_THUMB_DATA_FILE_VERSION,miniThumbDataFileId); File f = new File(path); if (miniThumbFile == null||!f.exists()) { if(onlyRead) return null; removeOldMiniThumbDataFile(miniThumbDataFileId); File directory = new File(path).getParentFile(); if (!directory.isDirectory()) { if (!directory.mkdirs()) { Log.e(TAG, "Unable to create .thumbnails directory " + directory.toString()); } } try { mMiniThumbFile = new RandomAccessFile(f, "rw"); miniThumbFile = new RandomAccessFile(f, "rw"); } catch (IOException ex) { // Open as read-only so we can at least read the existing // thumbnails. try { mMiniThumbFile = new RandomAccessFile(f, "r"); miniThumbFile = new RandomAccessFile(f, "r"); } catch (IOException ex2) { } } if (mMiniThumbFile != null) { mChannel = mMiniThumbFile.getChannel(); } mMiniThumbFilesMap.put(miniThumbDataFileId, miniThumbFile); } return mMiniThumbFile; return miniThumbFile; } public MiniThumbFile(Uri uri) { @@ -189,10 +231,19 @@ public class MiniThumbFile { } public synchronized void deactivate() { if (mMiniThumbFile != null) { if (mMiniThumbFilesMap != null) { Set<Long> keySet=mMiniThumbFilesMap.keySet(); try { mMiniThumbFile.close(); mMiniThumbFile = null; for(Long key:keySet) { RandomAccessFile file=mMiniThumbFilesMap.get(key); if(file!=null) { mMiniThumbFilesMap.put(key, null); file.close(); } } mMiniThumbFilesMap.clear(); } catch (IOException ex) { // ignore exception } @@ -205,18 +256,20 @@ public class MiniThumbFile { // check the mini thumb file for the right data. Right is // defined as having the right magic number at the offset // reserved for this "id". RandomAccessFile r = miniThumbDataFile(); final long miniThumbDataFileId=getMiniThumbFileId(id); RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,true); if (r != null) { long pos = id * BYTES_PER_MINTHUMB; FileChannel channel=r.getChannel(); long pos = getPositionInMiniThumbFile(id); FileLock lock = null; try { mBuffer.clear(); mBuffer.limit(1 + 8); lock = mChannel.lock(pos, 1 + 8, true); lock = channel.lock(pos, 1 + 8, true); // check that we can read the following 9 bytes // (1 for the "status" and 8 for the long) if (mChannel.read(mBuffer, pos) == 9) { if (channel.read(mBuffer, pos) == 9) { mBuffer.position(0); if (mBuffer.get() == 1) { return mBuffer.getLong(); @@ -242,10 +295,12 @@ public class MiniThumbFile { public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic) throws IOException { RandomAccessFile r = miniThumbDataFile(); final long miniThumbDataFileId=getMiniThumbFileId(id); RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId); if (r == null) return; long pos = id * BYTES_PER_MINTHUMB; final long pos = getPositionInMiniThumbFile(id); FileChannel channel=r.getChannel(); FileLock lock = null; try { if (data != null) { @@ -266,14 +321,13 @@ public class MiniThumbFile { check = sChecker.getValue(); } mBuffer.putLong(check); if (LOG) Log.i(TAG, "saveMiniThumbToFile(" + id + ") flag=1, magic=" + magic + ", length=" + data.length + ", check=" + check); mBuffer.put(data); mBuffer.flip(); lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false); mChannel.write(mBuffer, pos); lock = channel.lock(pos, BYTES_PER_MINTHUMB, false); channel.write(mBuffer, pos); if (LOG) Log.i(TAG, "saveMiniThumbToFile(" + id + ") flag=1, magic=" + magic + ", length=" + data.length + ", check=" + check); } } catch (IOException ex) { Log.e(TAG, "couldn't save mini thumbnail data for " @@ -319,27 +373,29 @@ public class MiniThumbFile { * @return */ public synchronized byte[] getMiniThumbFromFile(long id, byte [] data, ThumbResult result) { RandomAccessFile r = miniThumbDataFile(); final long miniThumbDataFileId=getMiniThumbFileId(id); RandomAccessFile r = miniThumbDataFile(miniThumbDataFileId,true); if (r == null) return null; long pos = id * BYTES_PER_MINTHUMB; long pos = getPositionInMiniThumbFile(id); FileChannel channel=r.getChannel(); FileLock lock = null; try { mBuffer.clear(); lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, true); int size = mChannel.read(mBuffer, pos); lock = channel.lock(pos, BYTES_PER_MINTHUMB, true); int size = channel.read(mBuffer, pos); if (size > 1 + 8 + 4 + 8) { // flag, magic, length, check code mBuffer.position(0); byte flag = mBuffer.get(); long magic = mBuffer.getLong(); int length = mBuffer.getInt(); long check = mBuffer.getLong(); if (LOG) Log.i(TAG, "getMiniThumbFromFile(" + id + ") flag=" + flag + ", magic=" + magic + ", length=" + length + ", check=" + check); long newCheck = UNKNOWN_CHECK_CODE; if (size >= 1 + 8 + 4 + 8 + length && data.length >= length) { mBuffer.get(data, 0, length); Log.i(TAG, " success to getMiniThumbFromFile(" + id + ") flag=" + flag + ", magic=" + magic + ", length=" + length + ", check=" + check); synchronized (sChecker) { sChecker.reset(); sChecker.update(data, 0, length);
<div class="dp-highlighter bg_java" sizcache="27" sizset="68"><div class="bar" sizcache="27" sizset="68"><div class="tools" sizcache="27" sizset="68"><strong>[java]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/fengye810130/article/details/9118221#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/fengye810130/article/details/9118221#">print</a><a target=_blank title="?" class="About" href="http://blog.csdn.net/fengye810130/article/details/9118221#">?</a></div></div><ol class="dp-j"><li class="alt"><span><span>@@ -</span><span class="number">1224</span><span>,</span><span class="number">14</span><span> +</span><span class="number">1224</span><span>,</span><span class="number">14</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MediaScanner </span></span></li><li><span> c.close(); </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">if</span><span> (videoCount != </span><span class="number">0</span><span>) { </span></li><li class="alt"><span> </span><span class="comment">/*if (videoCount != 0) {</span> </li><li><span><span class="comment"> String fullPathString = MiniThumbFile.getThumbdataPath(mVideoThumbsUri);</span> </span></li><li class="alt"><span><span class="comment"> existingFiles.remove(fullPathString);</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> if (imageCount != 0) {</span> </span></li><li><span><span class="comment"> String fullPathString = MiniThumbFile.getThumbdataPath(mThumbsUri);</span> </span></li><li class="alt"><span><span class="comment"> existingFiles.remove(fullPathString);</span> </span></li><li><span><span class="comment"> }</span> </span></li><li class="alt"><span><span class="comment"> }*/</span><span> </span></span></li><li><span> </span><span class="keyword">for</span><span> (String fileToDelete : existingFiles) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) </span></li><li><span> Log.v(TAG, </span><span class="string">"fileToDelete is "</span><span> + fileToDelete); </span></li><li class="alt"><span>@@ -</span><span class="number">1247</span><span>,</span><span class="number">7</span><span> +</span><span class="number">1247</span><span>,</span><span class="number">163</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MediaScanner </span></li><li><span> e.printStackTrace(); </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="comment">/*[robin_20120511*/</span><span> </span></li><li><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> pruneDeadMiniThumbnailFiles() { </span></li><li class="alt"><span> HashSet<String> existingFiles = </span><span class="keyword">new</span><span> HashSet<String>(); </span></li><li><span> String directory = Environment.getExternalStorageDirectory().toString() + </span><span class="string">"/DCIM/.thumbnails"</span><span>; </span></li><li class="alt"><span> File file=</span><span class="keyword">new</span><span> File(directory); </span></li><li><span> String [] files = (file).list(); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (files == </span><span class="keyword">null</span><span>) { </span></li><li><span> files = </span><span class="keyword">new</span><span> String[</span><span class="number">0</span><span>]; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> i=</span><span class="number">0</span><span>; i < files.length; i++) { </span></li><li class="alt"><span> String fullPathString = directory + </span><span class="string">"/"</span><span> + files[i]; </span></li><li><span> existingFiles.add(fullPathString); </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> Cursor c = mMediaProvider.query( </span></li><li><span> mThumbsUri, </span></li><li class="alt"><span> </span><span class="keyword">new</span><span> String [] { </span><span class="string">"_data"</span><span> }, </span></li><li><span> </span><span class="keyword">null</span><span>, </span></li><li class="alt"><span> </span><span class="keyword">null</span><span>, </span></li><li><span> </span><span class="keyword">null</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (</span><span class="keyword">null</span><span> != c) { </span></li><li><span> </span><span class="keyword">if</span><span> (c.moveToFirst()) { </span></li><li class="alt"><span> </span><span class="keyword">do</span><span> { </span></li><li><span> String fullPathString = c.getString(</span><span class="number">0</span><span>); </span></li><li class="alt"><span> existingFiles.remove(fullPathString); </span></li><li><span> } </span><span class="keyword">while</span><span> (c.moveToNext()); </span></li><li class="alt"><span> } </span></li><li><span> c.close(); </span></li><li class="alt"><span> } </span></li><li><span> c = mMediaProvider.query( </span></li><li class="alt"><span> mVideoThumbsUri, </span></li><li><span> </span><span class="keyword">new</span><span> String [] { </span><span class="string">"_data"</span><span> }, </span></li><li class="alt"><span> </span><span class="keyword">null</span><span>, </span></li><li><span> </span><span class="keyword">null</span><span>, </span></li><li class="alt"><span> </span><span class="keyword">null</span><span>); </span></li><li><span> </span><span class="keyword">if</span><span> (</span><span class="keyword">null</span><span> != c) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (c.moveToFirst()) { </span></li><li><span> </span><span class="keyword">do</span><span> { </span></li><li class="alt"><span> String fullPathString = c.getString(</span><span class="number">0</span><span>); </span></li><li><span> existingFiles.remove(fullPathString); </span></li><li class="alt"><span> } </span><span class="keyword">while</span><span> (c.moveToNext()); </span></li><li><span> } </span></li><li class="alt"><span> c.close(); </span></li><li><span> } </span></li><li class="alt"><span> String strs[]; </span></li><li><span> </span><span class="keyword">long</span><span> fileSN; </span></li><li class="alt"><span> </span><span class="keyword">long</span><span> id0; </span></li><li><span> </span><span class="keyword">long</span><span> id1; </span></li><li class="alt"><span> </span><span class="keyword">int</span><span> blockNum=MiniThumbFile.getMiniThumbDataFileBlockNum(); </span></li><li><span> </span><span class="keyword">final</span><span> String selection_IMAGE=</span><span class="string">" "</span><span>+Images.Thumbnails.IMAGE_ID+</span><span class="string">">=? AND "</span><span>+Images.Thumbnails.IMAGE_ID+</span><span class="string">"<?"</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">final</span><span> String sortOrder_IMAGE=Images.Thumbnails.IMAGE_ID; </span></li><li><span> </span><span class="keyword">final</span><span> String selection_VIDEO=</span><span class="string">" "</span><span>+Video.Thumbnails.VIDEO_ID+</span><span class="string">">=? AND "</span><span>+Video.Thumbnails.VIDEO_ID+</span><span class="string">"<?"</span><span>; </span></li><li class="alt"><span> </span><span class="keyword">final</span><span> String sortOrder_VIDEO=Video.Thumbnails.VIDEO_ID; </span></li><li><span> HashSet<String> fileSet=</span><span class="keyword">new</span><span> HashSet<String>(existingFiles); </span></li><li class="alt"><span> </span><span class="keyword">for</span><span> (String fileToDelete : fileSet) { </span></li><li><span> strs=MiniThumbFile.parseFileName(fileToDelete); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span>(strs==</span><span class="keyword">null</span><span>||strs.length!=</span><span class="number">4</span><span>) </span></li><li><span> { </span></li><li class="alt"><span> existingFiles.remove(fileToDelete); </span></li><li><span> </span><span class="keyword">continue</span><span>; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">if</span><span>(</span><span class="string">"images"</span><span>.equals(strs[</span><span class="number">2</span><span>])||</span><span class="string">"video"</span><span>.equals(strs[</span><span class="number">2</span><span>])) </span></li><li class="alt"><span> { </span></li><li><span> fileSN=Long.parseLong(strs[</span><span class="number">3</span><span>]); </span></li><li class="alt"><span> id0=blockNum*fileSN; </span></li><li><span> id1=blockNum*(fileSN+</span><span class="number">1</span><span>); </span></li><li class="alt"><span> </span><span class="keyword">final</span><span> String[] selectionArgs= </span><span class="keyword">new</span><span> String[]{id0+</span><span class="string">""</span><span>,id1+</span><span class="string">""</span><span>}; </span></li><li><span> </span><span class="keyword">if</span><span>(</span><span class="string">"images"</span><span>.equals(strs[</span><span class="number">2</span><span>])) </span></li><li class="alt"><span> { </span></li><li><span> </span></li><li class="alt"><span> c = mMediaProvider.query( </span></li><li><span> mThumbsUri, </span></li><li class="alt"><span> </span><span class="keyword">new</span><span> String [] { Images.Thumbnails.IMAGE_ID }, </span></li><li><span> selection_IMAGE, </span></li><li class="alt"><span> selectionArgs, </span></li><li><span> sortOrder_IMAGE); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (</span><span class="keyword">null</span><span> != c) { </span></li><li><span> </span><span class="keyword">if</span><span> (c.getCount()></span><span class="number">0</span><span>) { </span></li><li class="alt"><span> </span></li><li><span> existingFiles.remove(fileToDelete); </span></li><li class="alt"><span> } </span></li><li><span> c.close(); </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (</span><span class="string">"video"</span><span>.equals(strs[</span><span class="number">2</span><span>])) </span></li><li><span> { </span></li><li class="alt"><span> c = mMediaProvider.query( </span></li><li><span> mVideoThumbsUri, </span></li><li class="alt"><span> </span><span class="keyword">new</span><span> String [] { Video.Thumbnails.VIDEO_ID }, </span></li><li><span> selection_VIDEO, </span></li><li class="alt"><span> selectionArgs, </span></li><li><span> sortOrder_VIDEO); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (</span><span class="keyword">null</span><span> != c) { </span></li><li><span> </span><span class="keyword">if</span><span> (c.getCount()></span><span class="number">0</span><span>) { </span></li><li class="alt"><span> existingFiles.remove(fileToDelete); </span></li><li><span> } </span></li><li class="alt"><span> c.close(); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">else</span><span> </span></li><li><span> { </span></li><li class="alt"><span> existingFiles.remove(fileToDelete); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">for</span><span> (String fileToDelete : existingFiles) { </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (LOG) </span></li><li><span> Log.v(TAG, </span><span class="string">"fileToDelete is "</span><span> + fileToDelete); </span></li><li class="alt"><span> </span><span class="keyword">try</span><span> { </span></li><li><span> (</span><span class="keyword">new</span><span> File(fileToDelete)).delete(); </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (SecurityException ex) { </span></li><li><span> ex.printStackTrace(); </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> file=</span><span class="keyword">new</span><span> File(directory); </span></li><li><span> </span><span class="keyword">long</span><span> freeDiskSpape=(file.getUsableSpace()>></span><span class="number">20</span><span>); </span></li><li class="alt"><span> </span><span class="comment">/*</span> </li><li><span><span class="comment"> * when the free Disk is very low(<100M),delete all MiniThumbFile</span> </span></li><li class="alt"><span><span class="comment"> */</span><span> </span></span></li><li><span> </span><span class="keyword">if</span><span>(freeDiskSpape<</span><span class="number">100</span><span>) </span></li><li class="alt"><span> { </span></li><li><span> files = (file).list(); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span> (files == </span><span class="keyword">null</span><span>) { </span></li><li><span> files = </span><span class="keyword">new</span><span> String[</span><span class="number">0</span><span>]; </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> i=</span><span class="number">0</span><span>; i < files.length; i++) { </span></li><li class="alt"><span> String fullPathString = directory + </span><span class="string">"/"</span><span> + files[i]; </span></li><li><span> existingFiles.add(fullPathString); </span></li><li class="alt"><span> } </span></li><li><span> fileSet=</span><span class="keyword">new</span><span> HashSet<String>(existingFiles); </span></li><li class="alt"><span> </span><span class="keyword">for</span><span> (String fileToDelete : fileSet) { </span></li><li><span> strs=MiniThumbFile.parseFileName(fileToDelete); </span></li><li class="alt"><span> </span><span class="keyword">if</span><span>(strs==</span><span class="keyword">null</span><span>||strs.length!=</span><span class="number">4</span><span>) </span></li><li><span> { </span></li><li class="alt"><span> existingFiles.remove(fileToDelete); </span></li><li><span> </span><span class="keyword">continue</span><span>; </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> </span><span class="keyword">for</span><span> (String fileToDelete : existingFiles) { </span></li><li><span> </span><span class="keyword">if</span><span> (LOG) </span></li><li class="alt"><span> Log.v(TAG, </span><span class="string">"Memeroy is very Low.delete MiniThumbFile:"</span><span> + fileToDelete); </span></li><li><span> </span><span class="keyword">try</span><span> { </span></li><li class="alt"><span> (</span><span class="keyword">new</span><span> File(fileToDelete)).delete(); </span></li><li><span> } </span><span class="keyword">catch</span><span> (SecurityException ex) { </span></li><li class="alt"><span> ex.printStackTrace(); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> } </span></li><li><span> Log.v(TAG, </span><span class="string">"pruneDeadMiniThumbnailFiles... "</span><span> + c); </span></li><li class="alt"><span> } </span><span class="keyword">catch</span><span> (RemoteException e) { </span></li><li><span> </span><span class="comment">/* We will soon be killed...*/</span><span> </span></li><li class="alt"><span> e.printStackTrace(); </span></li><li><span> } </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="comment">/*robin_20120511]*/</span><span> </span></li><li class="alt"><span> </span><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> postscan(String[] directories) </span><span class="keyword">throws</span><span> RemoteException { </span></li><li><span> Iterator<FileCacheEntry> iterator = mFileCache.values().iterator(); </span></li><li class="alt"><span>@@ -</span><span class="number">1306</span><span>,</span><span class="number">8</span><span> +</span><span class="number">1462</span><span>,</span><span class="number">12</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MediaScanner </span></li><li><span> </span><span class="keyword">if</span><span> ((mOriginalCount == </span><span class="number">0</span><span> || mOriginalVideoCount == </span><span class="number">0</span><span>) </span></li><li class="alt"><span> && mImagesUri.equals(Images.Media.getContentUri(</span><span class="string">"external"</span><span>))) { </span></li><li><span> pruneDeadThumbnailFiles(); </span></li><li class="alt"><span> }</span><span class="comment">/*[robin_20120511*/</span><span> </span></li><li><span> </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (mImagesUri.equals(Images.Media.getContentUri(</span><span class="string">"external"</span><span>))) </span></li><li class="alt"><span> { </span></li><li><span> pruneDeadMiniThumbnailFiles(); </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> </span><span class="comment">/*robin_20120511]*/</span><span> </span></li><li><span> </span><span class="comment">/* allow GC to clean up*/</span><span> </span></li><li class="alt"><span> mPlayLists = </span><span class="keyword">null</span><span>; </span></li><li><span> mFileCache = </span><span class="keyword">null</span><span>; </span></li><li class="alt"><span>@@ -</span><span class="number">1399</span><span>,</span><span class="number">7</span><span> +</span><span class="number">1559</span><span>,</span><span class="number">12</span><span> @@ </span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> MediaScanner </span></li><li><span> </span><span class="keyword">long</span><span> prune = System.currentTimeMillis(); </span></li><li class="alt"><span> pruneDeadThumbnailFiles(); </span></li><li><span> </span><span class="keyword">if</span><span> (LOG) Log.d(TAG, </span><span class="string">"mtkPostscan: pruneDeadThumbnailFiles takes "</span><span> + (System.currentTimeMillis() - prune) + </span><span class="string">"ms."</span><span>); </span></li><li class="alt"><span> }</span><span class="comment">/*[robin_20120511*/</span><span> </span></li><li><span> </span><span class="keyword">else</span><span> </span><span class="keyword">if</span><span> (mImagesUri.equals(Images.Media.getContentUri(</span><span class="string">"external"</span><span>))) </span></li><li class="alt"><span> { </span></li><li><span> pruneDeadMiniThumbnailFiles(); </span></li><li class="alt"><span> } </span></li><li><span> </span><span class="comment">/*robin_20120511]*/</span><span> </span></li><li class="alt"><span> </span></li><li><span> </span><span class="comment">// allow GC to clean up </span><span> </span></li><li class="alt"><span> mPlayLists = </span><span class="keyword">null</span><span>; </span></li></ol></div><pre class="java" style="DISPLAY: none" name="code">@@ -1224,14 +1224,14 @@ public class MediaScanner c.close(); } if (videoCount != 0) { /*if (videoCount != 0) { String fullPathString = MiniThumbFile.getThumbdataPath(mVideoThumbsUri); existingFiles.remove(fullPathString); } if (imageCount != 0) { String fullPathString = MiniThumbFile.getThumbdataPath(mThumbsUri); existingFiles.remove(fullPathString); } }*/ for (String fileToDelete : existingFiles) { if (LOG) Log.v(TAG, "fileToDelete is " + fileToDelete); @@ -1247,7 +1247,163 @@ public class MediaScanner e.printStackTrace(); } } /*[robin_20120511*/ private void pruneDeadMiniThumbnailFiles() { HashSet<String> existingFiles = new HashSet<String>(); String directory = Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails"; File file=new File(directory); String [] files = (file).list(); if (files == null) { files = new String[0]; } for (int i=0; i < files.length; i++) { String fullPathString = directory + "/" + files[i]; existingFiles.add(fullPathString); } try { Cursor c = mMediaProvider.query( mThumbsUri, new String [] { "_data" }, null, null, null); if (null != c) { if (c.moveToFirst()) { do { String fullPathString = c.getString(0); existingFiles.remove(fullPathString); } while (c.moveToNext()); } c.close(); } c = mMediaProvider.query( mVideoThumbsUri, new String [] { "_data" }, null, null, null); if (null != c) { if (c.moveToFirst()) { do { String fullPathString = c.getString(0); existingFiles.remove(fullPathString); } while (c.moveToNext()); } c.close(); } String strs[]; long fileSN; long id0; long id1; int blockNum=MiniThumbFile.getMiniThumbDataFileBlockNum(); final String selection_IMAGE=" "+Images.Thumbnails.IMAGE_ID+">=? AND "+Images.Thumbnails.IMAGE_ID+"<?"; final String sortOrder_IMAGE=Images.Thumbnails.IMAGE_ID; final String selection_VIDEO=" "+Video.Thumbnails.VIDEO_ID+">=? AND "+Video.Thumbnails.VIDEO_ID+"<?"; final String sortOrder_VIDEO=Video.Thumbnails.VIDEO_ID; HashSet<String> fileSet=new HashSet<String>(existingFiles); for (String fileToDelete : fileSet) { strs=MiniThumbFile.parseFileName(fileToDelete); if(strs==null||strs.length!=4) { existingFiles.remove(fileToDelete); continue; } if("images".equals(strs[2])||"video".equals(strs[2])) { fileSN=Long.parseLong(strs[3]); id0=blockNum*fileSN; id1=blockNum*(fileSN+1); final String[] selectionArgs= new String[]{id0+"",id1+""}; if("images".equals(strs[2])) { c = mMediaProvider.query( mThumbsUri, new String [] { Images.Thumbnails.IMAGE_ID }, selection_IMAGE, selectionArgs, sortOrder_IMAGE); if (null != c) { if (c.getCount()>0) { existingFiles.remove(fileToDelete); } c.close(); } } else if ("video".equals(strs[2])) { c = mMediaProvider.query( mVideoThumbsUri, new String [] { Video.Thumbnails.VIDEO_ID }, selection_VIDEO, selectionArgs, sortOrder_VIDEO); if (null != c) { if (c.getCount()>0) { existingFiles.remove(fileToDelete); } c.close(); } } } else { existingFiles.remove(fileToDelete); } } for (String fileToDelete : existingFiles) { if (LOG) Log.v(TAG, "fileToDelete is " + fileToDelete); try { (new File(fileToDelete)).delete(); } catch (SecurityException ex) { ex.printStackTrace(); } } file=new File(directory); long freeDiskSpape=(file.getUsableSpace()>>20); /* * when the free Disk is very low(<100M),delete all MiniThumbFile */ if(freeDiskSpape<100) { files = (file).list(); if (files == null) { files = new String[0]; } for (int i=0; i < files.length; i++) { String fullPathString = directory + "/" + files[i]; existingFiles.add(fullPathString); } fileSet=new HashSet<String>(existingFiles); for (String fileToDelete : fileSet) { strs=MiniThumbFile.parseFileName(fileToDelete); if(strs==null||strs.length!=4) { existingFiles.remove(fileToDelete); continue; } } for (String fileToDelete : existingFiles) { if (LOG) Log.v(TAG, "Memeroy is very Low.delete MiniThumbFile:" + fileToDelete); try { (new File(fileToDelete)).delete(); } catch (SecurityException ex) { ex.printStackTrace(); } } } Log.v(TAG, "pruneDeadMiniThumbnailFiles... " + c); } catch (RemoteException e) { /* We will soon be killed...*/ e.printStackTrace(); } } /*robin_20120511]*/ private void postscan(String[] directories) throws RemoteException { Iterator<FileCacheEntry> iterator = mFileCache.values().iterator(); @@ -1306,8 +1462,12 @@ public class MediaScanner if ((mOriginalCount == 0 || mOriginalVideoCount == 0) && mImagesUri.equals(Images.Media.getContentUri("external"))) { pruneDeadThumbnailFiles(); }/*[robin_20120511*/ else if (mImagesUri.equals(Images.Media.getContentUri("external"))) { pruneDeadMiniThumbnailFiles(); } /*robin_20120511]*/ /* allow GC to clean up*/ mPlayLists = null; mFileCache = null; @@ -1399,7 +1559,12 @@ public class MediaScanner long prune = System.currentTimeMillis(); pruneDeadThumbnailFiles(); if (LOG) Log.d(TAG, "mtkPostscan: pruneDeadThumbnailFiles takes " + (System.currentTimeMillis() - prune) + "ms."); }/*[robin_20120511*/ else if (mImagesUri.equals(Images.Media.getContentUri("external"))) { pruneDeadMiniThumbnailFiles(); } /*robin_20120511]*/ // allow GC to clean up mPlayLists = null;