原生Android缩略图填满SD卡的问题

From:http://blog.csdn.net/fengye810130/article/details/9118221

google原生Android中,MiniThumbFile.java里存储图片/视频的缩略图的算法有问题。
该算法的漏洞造成微缩略图文件( DCIM\.thumbnails\.thumbdata4--1967290299 )非常庞大和臃肿,多达1G,理论上可以无限大,直到填满SD卡
重现步骤:
第一步 :插入一张拥有10万张图片的外部SD卡,
第二步 :等待手机扫描完整个SD卡,这个过程大概30分钟。至于扫描是否完成,你可以看TAG为MediaProvider的日志。
第三步 :拔出外部SD卡,再次等手机进行扫描大概10分钟。
第四步 :按下手机的电源key +音量down key来截屏。
第五步 :通过电脑查看内部SD卡的DCIM\.thumbnails\.thumbdata4--1967290299文件。这时你会发现,该文件多达1G.
对于该问题,大概的逻辑是这样的
MediaProvider会对SD卡上的文件的进行扫描,得到一些基本的信息放入数据库的files这个表中。
对于一些图片(比如手机截屏图片),手机会以这些图片文件在files表中的_id的值,作为一个定位标志,把其缩略文件存放在.thumbdata4--1967290299中。
比如 _id为1,那么该文件的缩略图就存放在.thumbdata4--1967290299文件的_id * BYTES_PER_MINTHUMB开始的位置,其中BYTES_PER_MINTHUMB = 17000,
对此可以参照MiniThumbFile.java文件中的 saveMiniThumbToFile(byte[] data, long id, long magic)等函数
对于Android的Sqlite3数据库,_id是自增的。比如,最开始我插入了10001记录,这时最后一条记录的_id为10001,这时如果删除1到10000条记录,
再插入一条记录,那么这条的记录的_id值为10002.
因此, 随着用户日常中不停的向SD卡反复地添加删除文件,那么files表中的_id的值会不停的增大
当该值为10万时,即使我们截屏时,系统只把该截屏图片这样一张图的缩略图保存在.thumbdata4--1967290299文件,
10万*BYTES_PER_MINTHUMB>1G,也就是说.thumbdata4--1967290299文件就会占用了1G多的SD空间。随着时间的推移,该值会继续变大,直到填满SD卡
我们的方案就是把 .thumbdata4--1967290299 文件分成多个文件来存储缩略图。
比如.thumbdata4--1967290299-0存_id 为1到1024的文件的缩略图,.thumbdata4--1967290299-1存_id 为1025到2048的文件的缩略图
同时对缩略图文件做一些维护,即如果一个缩略图文件本身对应原文件不在时,清理掉该微缩略图文件。
另外在极端情况下(剩余容量小于100M下),清理掉所有的微缩略图文件。
在MTK 6575平台上对该问题的修改包含2个文件的修改:
<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>
MiniThumbFile.java文件的主要修改如下:
<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);

 
    
 
    
 
   
MediaScanner.java文件的修改如下:
<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;


 
   

 结束!

你可能感兴趣的:(android,Android开发,多媒体,视频缩略图,VideoThumbnail)