<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_努力吧</title><subtitle type="text">IOS&amp;Android开发，欢迎交流。欢迎转载，转载请注明出处！ghanguo@gmail.com</subtitle><id>http://feed.cnblogs.com/blog/u/71288/rss</id><updated>2012-03-19T06:21:14Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/71288/rss"/><entry><id>http://www.cnblogs.com/halzhang/archive/2011/10/10/2206596.html</id><title type="text">单个for循环打印九九乘法表</title><summary type="text">1 for (int i = 1,j=1; j &lt;= 9; i++) {2 printf("%d * %d = %d %s",i,j,i*j,"\t"); 3 // NSLog(@"%d * %d = %d",i,j,i*j);4 if(i == j){5 i =0;j++;6 // NSLog(@"%@",@"\n");7 printf("%s","\n");8 }9 }</summary><published>2011-10-10T13:40:00Z</published><updated>2011-10-10T13:40:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/10/10/2206596.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/10/10/2206596.html"/><content type="html">&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;  &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;1&lt;/span&gt;,j=&lt;span style="color: #800080;"&gt;1&lt;/span&gt;; j &amp;lt;= &lt;span style="color: #800080;"&gt;9&lt;/span&gt;; i++) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;         printf(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;%d * %d = %d %s&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,i,j,i*j,&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;\t&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;); &lt;br /&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;         &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; NSLog(@"%d * %d = %d",i,j,i*j);&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;(i == j){&lt;br /&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;             i =&lt;span style="color: #800080;"&gt;0&lt;/span&gt;;j++;&lt;br /&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; NSLog(@"%@",@"\n");&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;            printf(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;%s&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;\n&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt;         }&lt;br /&gt;&lt;span style="color: #008080;"&gt;9&lt;/span&gt; }&lt;/div&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/2206596.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/10/10/2206596.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/10/07/2200631.html</id><title type="text">常见排序算法-采用Objective-c实现</title><summary type="text">国庆比较闲，复习一下算法，随便练练objective-c；本文采用objective-c实现常见的排序算法：选择排序，插入排序，快速排序。悼念乔帮主，期待apple在后乔帮主时代创造出更出色的产品。 1 // 2 // Sort.h 3 // Algorithm 4 // 5 // Created by 张 汉国 on 11-9-30. 6 // Copyright 2011年 __MyCompanyName__. All rights reserved. 7 // 8 9 #import &lt;Foundation/Foundation.h&gt;10 11 @interface Sort</summary><published>2011-10-07T08:36:00Z</published><updated>2011-10-07T08:36:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/10/07/2200631.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/10/07/2200631.html"/><content type="html">&lt;p class="p1"&gt;国庆比较闲，复习一下算法，随便练练objective-c；&lt;/p&gt;&lt;p class="p1"&gt;本文采用objective-c实现常见的排序算法：选择排序，插入排序，快速排序。&lt;/p&gt;&lt;p class="p1"&gt;悼念乔帮主，期待apple在后乔帮主时代创造出更出色的产品。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Sort.h&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Algorithm&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Created by 张 汉国 on 11-9-30.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Copyright 2011年 __MyCompanyName__. All rights reserved.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#import&lt;/span&gt; &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@interface&lt;/span&gt; Sort : NSObject{&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;选择排序&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;-(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)selectSortWithArray:(NSArray *)aData;&lt;br /&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;插入排序&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;-(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)insertSortWithArray:(NSArray *)aData;&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;快速排序&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;-(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)quickSortWithArray:(NSArray *)aData;&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)swapWithData:(NSMutableArray *)aData index1:(NSInteger)index1 index2:(NSInteger)index2;&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Sort.m&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Algorithm&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Created by 张 汉国 on 11-9-30.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Copyright 2011年 __MyCompanyName__. All rights reserved.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#import&lt;/span&gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sort.h&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@interface&lt;/span&gt; Sort()&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)quickSortWithArray:(NSArray *)aData left:(NSInteger)left right:(NSInteger)right;&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@end&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@implementation&lt;/span&gt; Sort&lt;br /&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; - (&lt;span style="color: #0000ff;"&gt;id&lt;/span&gt;)init&lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;     self = [super init];&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (self) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;         &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Initialization code here.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;    }&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)selectSortWithArray:(NSArray *)aData{&lt;br /&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;     NSMutableArray *data = [[NSMutableArray alloc]initWithArray:aData];&lt;br /&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i=&lt;span style="color: #800080;"&gt;0&lt;/span&gt;; i&amp;lt;[data count]-&lt;span style="color: #800080;"&gt;1&lt;/span&gt;; i++) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; m =i;&lt;br /&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; j =i+&lt;span style="color: #800080;"&gt;1&lt;/span&gt;; j&amp;lt;[data count]; j++) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ([data objectAtIndex:j] &amp;lt; [data objectAtIndex:m]) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt;                 m = j;&lt;br /&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;             }&lt;br /&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;         }&lt;br /&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (m != i) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;             [self swapWithData:data index1:m index2:i];&lt;br /&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt;         }&lt;br /&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt;     }&lt;br /&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt;     NSLog(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;选择排序后的结果：%@&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,[data description]);&lt;br /&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt;     [data release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;43&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;44&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)insertSortWithArray:(NSArray *)aData{&lt;br /&gt;&lt;span style="color: #008080;"&gt;45&lt;/span&gt;     NSMutableArray *data = [[NSMutableArray alloc]initWithArray:aData];&lt;br /&gt;&lt;span style="color: #008080;"&gt;46&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;1&lt;/span&gt;; i &amp;lt; [data count]; i++) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;47&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;id&lt;/span&gt; tmp = [data objectAtIndex:i];&lt;br /&gt;&lt;span style="color: #008080;"&gt;48&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; j = i-&lt;span style="color: #800080;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;49&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (j != -&lt;span style="color: #800080;"&gt;1&lt;/span&gt; &amp;amp;&amp;amp; [data objectAtIndex:j] &amp;gt; tmp) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;50&lt;/span&gt;             [data replaceObjectAtIndex:j+&lt;span style="color: #800080;"&gt;1&lt;/span&gt; withObject:[data objectAtIndex:j]];&lt;br /&gt;&lt;span style="color: #008080;"&gt;51&lt;/span&gt;             j--;&lt;br /&gt;&lt;span style="color: #008080;"&gt;52&lt;/span&gt;         }&lt;br /&gt;&lt;span style="color: #008080;"&gt;53&lt;/span&gt;         [data replaceObjectAtIndex:j+&lt;span style="color: #800080;"&gt;1&lt;/span&gt; withObject:tmp];&lt;br /&gt;&lt;span style="color: #008080;"&gt;54&lt;/span&gt;     }&lt;br /&gt;&lt;span style="color: #008080;"&gt;55&lt;/span&gt;     NSLog(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;插入排序后的结果：%@&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,[data description]);&lt;br /&gt;&lt;span style="color: #008080;"&gt;56&lt;/span&gt;     [data release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;57&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;58&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;59&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)quickSortWithArray:(NSArray *)aData{&lt;br /&gt;&lt;span style="color: #008080;"&gt;60&lt;/span&gt;     NSMutableArray *data = [[NSMutableArray alloc] initWithArray:aData];&lt;br /&gt;&lt;span style="color: #008080;"&gt;61&lt;/span&gt;     [self quickSortWithArray:data left:&lt;span style="color: #800080;"&gt;0&lt;/span&gt; right:[aData count]-&lt;span style="color: #800080;"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: #008080;"&gt;62&lt;/span&gt;     NSLog(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;快速排序后的结果：%@&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,[data description]);&lt;br /&gt;&lt;span style="color: #008080;"&gt;63&lt;/span&gt;     [data release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;64&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;65&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;66&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;67&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)quickSortWithArray:(NSMutableArray *)aData left:(NSInteger)left right:(NSInteger)right{&lt;br /&gt;&lt;span style="color: #008080;"&gt;68&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (right &amp;gt; left) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;69&lt;/span&gt;         NSInteger i = left;&lt;br /&gt;&lt;span style="color: #008080;"&gt;70&lt;/span&gt;         NSInteger j = right + &lt;span style="color: #800080;"&gt;1&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;71&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;72&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (i+&lt;span style="color: #800080;"&gt;1&lt;/span&gt; &amp;lt; [aData count] &amp;amp;&amp;amp; [aData objectAtIndex:++i] &amp;lt; [aData objectAtIndex:left]) ;&lt;br /&gt;&lt;span style="color: #008080;"&gt;73&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (j-&lt;span style="color: #800080;"&gt;1&lt;/span&gt; &amp;gt; -&lt;span style="color: #800080;"&gt;1&lt;/span&gt; &amp;amp;&amp;amp; [aData objectAtIndex:--j] &amp;gt; [aData objectAtIndex:left]) ;&lt;br /&gt;&lt;span style="color: #008080;"&gt;74&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (i &amp;gt;= j) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;75&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;76&lt;/span&gt;             }&lt;br /&gt;&lt;span style="color: #008080;"&gt;77&lt;/span&gt;             [self swapWithData:aData index1:i index2:j];&lt;br /&gt;&lt;span style="color: #008080;"&gt;78&lt;/span&gt;         }&lt;br /&gt;&lt;span style="color: #008080;"&gt;79&lt;/span&gt;         [self swapWithData:aData index1:left index2:j];&lt;br /&gt;&lt;span style="color: #008080;"&gt;80&lt;/span&gt;         [self quickSortWithArray:aData left:left right:j-&lt;span style="color: #800080;"&gt;1&lt;/span&gt;];&lt;br /&gt;&lt;span style="color: #008080;"&gt;81&lt;/span&gt;         [self quickSortWithArray:aData left:j+&lt;span style="color: #800080;"&gt;1&lt;/span&gt; right:right];&lt;br /&gt;&lt;span style="color: #008080;"&gt;82&lt;/span&gt;     }&lt;br /&gt;&lt;span style="color: #008080;"&gt;83&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;84&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;85&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;86&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)dealloc{&lt;br /&gt;&lt;span style="color: #008080;"&gt;87&lt;/span&gt;     [super dealloc];&lt;br /&gt;&lt;span style="color: #008080;"&gt;88&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;89&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;90&lt;/span&gt; -(&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)swapWithData:(NSMutableArray *)aData index1:(NSInteger)index1 index2:(NSInteger)index2{&lt;br /&gt;&lt;span style="color: #008080;"&gt;91&lt;/span&gt;     NSNumber *tmp = [aData objectAtIndex:index1];&lt;br /&gt;&lt;span style="color: #008080;"&gt;92&lt;/span&gt;     [aData replaceObjectAtIndex:index1 withObject:[aData objectAtIndex:index2]];&lt;br /&gt;&lt;span style="color: #008080;"&gt;93&lt;/span&gt;     [aData replaceObjectAtIndex:index2 withObject:tmp];&lt;br /&gt;&lt;span style="color: #008080;"&gt;94&lt;/span&gt; }&lt;br /&gt;&lt;span style="color: #008080;"&gt;95&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;96&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;p class="p1"&gt;测试例子：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  main.m&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Algorithm&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Created by 张 汉国 on 11-9-30.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;  Copyright 2011年 __MyCompanyName__. All rights reserved.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#import&lt;/span&gt; &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#import&lt;/span&gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sort.h&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt; kSize 20&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt; kMax 100&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; main (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; argc, &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; * argv[])&lt;br /&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; {&lt;br /&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;     &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; insert code here...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;    NSLog(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Hello, World!&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;     NSMutableArray *data = [[NSMutableArray alloc] initWithCapacity:kSize];&lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i =&lt;span style="color: #800080;"&gt;0&lt;/span&gt;;i&amp;lt;kSize;i++) {&lt;br /&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;         u_int32_t x = arc4random() % kMax;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;0~kMax&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;        NSNumber *num = [[NSNumber alloc] initWithInt:x];&lt;br /&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;         [data addObject:num];&lt;br /&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;         [num release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;     }&lt;br /&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;     NSLog(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;排序前的数据：%@&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,[data description]);&lt;br /&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt;     &lt;br /&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;     Sort *sort = [[Sort alloc] init];&lt;br /&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;     [sort selectSortWithArray:data];&lt;br /&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;     [sort insertSortWithArray:data];&lt;br /&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;     [sort quickSortWithArray:data];&lt;br /&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt;     [sort release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt;     [data release];&lt;br /&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt;     [pool drain];&lt;br /&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #800080;"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt; }&lt;/div&gt;&lt;p class="p1"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/2200631.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/10/07/2200631.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/07/16/2108470.html</id><title type="text">Android开发——利用Cursor+CursorAdapter实现界面实时更新</title><summary type="text">好久没有更新博客了。不是没时间写，而是太懒。而且感觉有些东西没有时间总结，之之后再想写，就想不起来了。晚上新发现一点东西，所以就及时写下来。最近利用业余时间在看Android的Download模块，看得是2.3之前版本的源码，2.3之后android就开放了一个下载管理器，并提供了一些api。不过想对下载模块有更深入的了解还是必须自己花点时间看看downloadprovider的源码。相信会收获很多。如果有时间想写写文章对downloadprovider进行分析。这篇文章不是分析download的，不过却是我从读download的源码发现的。情景分析：我们有一个Service，这个Servic</summary><published>2011-07-16T15:33:00Z</published><updated>2011-07-16T15:33:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/07/16/2108470.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/07/16/2108470.html"/><content type="html">&lt;p&gt;好久没有更新博客了。不是没时间写，而是太懒。而且感觉有些东西没有时间总结，之之后再想写，就想不起来了。晚上新发现一点东西，所以就及时写下来。&lt;/p&gt;&lt;p&gt;最近利用业余时间在看Android的Download模块，看得是2.3之前版本的源码，2.3之后android就开放了一个下载管理器，并提供了一些api。不过想对下载模块有更深入的了解还是必须自己花点时间看看downloadprovider的源码。相信会收获很多。如果有时间想写写文章对downloadprovider进行分析。&lt;/p&gt;&lt;p&gt;这篇文章不是分析download的，不过却是我从读download的源码发现的。&lt;/p&gt;&lt;p&gt;情景分析：&lt;/p&gt;&lt;p&gt;我们有一个Service，这个Service在后台会不断的更新多条数据，我们又想将不断更新的数据展现在ui上面这时你是怎么解决的呢？其实就是类似有些浏览器的下载管理器界面，有没有想过是怎么实现的？？&lt;/p&gt;&lt;p&gt;解决方案:&lt;/p&gt;&lt;p&gt;1,使用通知，只能在通知栏看到更新，加入用户想在一个activity中有个进度显示呢？&lt;/p&gt;&lt;p&gt;2,发送更新广播，当是在一个listView中的多个列需要更新广播就有点吃力了；&lt;/p&gt;&lt;p&gt;还有吗？&lt;/p&gt;&lt;p&gt;参考方案：&lt;/p&gt;&lt;p&gt;利用Provider将数据持久化，再用Cursor监听Provider的变化来更新数据。当然这需要中Service update数据。&lt;/p&gt;&lt;p&gt;-----部分代码-------&lt;/p&gt;&lt;p&gt;//一个观察者&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;private&lt;/span&gt; &lt;span style="color: #971965;"&gt;class&lt;/span&gt; MyContentObserver &lt;span style="color: #971965;"&gt;extends&lt;/span&gt; ContentObserver {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;public&lt;/span&gt; MyContentObserver() {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;super&lt;/span&gt;(&lt;span style="color: #971965;"&gt;new&lt;/span&gt; Handler());&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;@Override&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;public&lt;/span&gt; &lt;span style="color: #971965;"&gt;void&lt;/span&gt; onChange(&lt;span style="color: #971965;"&gt;boolean&lt;/span&gt; selfChange) {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;super&lt;/span&gt;.onChange(selfChange);&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt; Log.i(&lt;/span&gt;"DLA"&lt;span style="color: #000000;"&gt;, &lt;/span&gt;"MyContentObserver onChange!"&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt;//处理数据更新回调&lt;/span&gt;&lt;/p&gt;&lt;p&gt;refreshData();&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;private&lt;/span&gt; &lt;span style="color: #971965;"&gt;void&lt;/span&gt; refreshData() {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;if&lt;/span&gt; (&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;.isClosed()) {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;return&lt;/span&gt;;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;//更新&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;.requery();&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;//一个实现CursorAdapter的适配器&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;private&lt;/span&gt; MyAdapter &lt;span style="color: #142cc4;"&gt;mAdapter&lt;/span&gt;;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;private&lt;/span&gt; Cursor &lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;private&lt;/span&gt; MyContentObserver &lt;span style="color: #142cc4;"&gt;mObserver&lt;/span&gt;;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;@Override&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;protected&lt;/span&gt; &lt;span style="color: #971965;"&gt;void&lt;/span&gt; onCreate(Bundle savedInstanceState) {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;super&lt;/span&gt;.onCreate(savedInstanceState);&lt;/p&gt;&lt;p&gt;setContentView(R.layout.&lt;span style="color: #142cc4;"&gt;list&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;setupViews();&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt; = getContentResolver().query(MyProvider.&lt;span style="color: #142cc4;"&gt;&lt;span class="caps"&gt;CONTENT&lt;/span&gt;_URI&lt;/span&gt;, &lt;span style="color: #142cc4;"&gt;sAppReadableColumnsArray&lt;/span&gt;,&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;null&lt;/span&gt;, &lt;span style="color: #971965;"&gt;null&lt;/span&gt;, &lt;span style="color: #971965;"&gt;null&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mObserver&lt;/span&gt; = &lt;span style="color: #971965;"&gt;new&lt;/span&gt; MyContentObserver();&lt;/p&gt;&lt;p&gt;//注册观察者&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;.registerContentObserver(&lt;span style="color: #142cc4;"&gt;mObserver&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mAdapter&lt;/span&gt; = &lt;span style="color: #971965;"&gt;new&lt;/span&gt; MyAdapter(&lt;span style="color: #971965;"&gt;this&lt;/span&gt;, R.layout.&lt;span style="color: #142cc4;"&gt;list_item&lt;/span&gt;, &lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;setListAdapter(&lt;span style="color: #142cc4;"&gt;mAdapter&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;@Override&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;protected&lt;/span&gt; &lt;span style="color: #971965;"&gt;void&lt;/span&gt; onDestroy() {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;super&lt;/span&gt;.onDestroy();&lt;/p&gt;&lt;p&gt;&lt;span style="color: #971965;"&gt;if&lt;/span&gt; (&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt; != &lt;span style="color: #971965;"&gt;null&lt;/span&gt;) {&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;.unregisterContentObserver(&lt;span style="color: #142cc4;"&gt;mObserver&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;&lt;span style="color: #142cc4;"&gt;mCursor&lt;/span&gt;.close();&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;⋯⋯&lt;/p&gt;&lt;p&gt;⋯⋯&lt;/p&gt;&lt;p&gt;这样实现后当MyProvider.CONTENT_URI对应的数据发生变化时都会调用观察者的onChange方法，mCursor.requery()执行后listview就直接更新了。（不知道在其他类型的Adapter中是否自动更新，而不需要调用adapter的&lt;span style="font-family: Monaco; font-size: 11px;"&gt;notifyDataSetChanged)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: Monaco; font-size: 11px;"&gt;--------end--------&lt;/span&gt;&lt;/p&gt;&lt;script type="text/javascript" charset="utf-8"&gt;// &lt;![CDATA[(function(){  var _w = 106 , _h = 58;  var param = {    url:location.href,    type:'5',    count:'1', /**是否显示分享数，1显示(可选)*/    appkey:'', /**您申请的应用appkey,显示分享来源(可选)*/    title:'', /**分享的文字内容(可选，默认为所在页面的title)*/    pic:'', /**分享图片的路径(可选)*/    ralateUid:'1639066941', /**关联用户的UID，分享微博会@该用户(可选)*/    rnd:new Date().valueOf()  }  var temp = [];  for( var p in param ){    temp.push(p + '=' + encodeURIComponent( param[p] || '' ) )  }  document.write('&lt;iframe allowTransparency="true" frameborder="0" scrolling="no" src="http://hits.sinajs.cn/A1/weiboshare.html?' + temp.join('&amp;') + '" width="'+ _w+'" height="'+_h+'"&gt;&lt;/iframe&gt;')})()// ]]&gt;&lt;/script&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/2108470.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/07/16/2108470.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/03/20/1989287.html</id><title type="text">Android开发&amp;mdash;&amp;mdash;MediaPlayer源码不完整分析</title><summary type="text">因为MediaPlayer的源码比较多，所以只能来一个不完整分析了。 转载请注明出处：http://www.cnblogs.com/halzhang 前段时间在工作中遇到一个问题就是MediaPlayer的播放网络流媒体的时候，当没有完全下载完毕的时，我们调用seekTo的时候会触发OnCompletionListener，你们懂的咯，这样就直接播放下一首了。挺纠结的，所以就决定看看mediapl...</summary><published>2011-03-20T03:31:00Z</published><updated>2011-03-20T03:31:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/03/20/1989287.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/03/20/1989287.html"/><content type="html">&lt;p&gt;因为MediaPlayer的源码比较多，所以只能来一个不完整分析了。&lt;/p&gt;  &lt;p&gt;&lt;font color="#ffffff"&gt;&lt;strong&gt;&lt;font size="4"&gt;转载请注明出处&lt;/font&gt;&lt;/strong&gt;：&lt;/font&gt;&lt;font color="#ffffff"&gt;http://www.cnblogs.com/halzhang&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;前段时间在工作中遇到一个问题就是MediaPlayer的播放网络流媒体的时候，当没有完全下载完毕的时，我们调用seekTo的时候会触发OnCompletionListener，你们懂的咯，这样就直接播放下一首了。挺纠结的，所以就决定看看mediaplayer的源码咯，希望能从中找到解决的方法。&lt;/p&gt;  &lt;p&gt;seekTo在MediaPlayer的调用流程如下图：&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103201131091034.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="SeekTo" border="0" alt="SeekTo" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103201131187601.jpg" width="644" height="393" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;font style="background-color: #ffff00" size="3"&gt;&lt;strong&gt;seekTo&lt;/strong&gt;&lt;/font&gt;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/257730/o_SeekTo.jpg" target="_blank"&gt;大图点此&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;在MediaPlayer.java中的seekTo是一个native修饰的方法&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;/**&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt; * Seeks to specified time position.&lt;/span&gt;    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt; *&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt; * @param msec the offset in milliseconds from the start to seek to&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt; * @throws IllegalStateException if the internal player engine has not been&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt; * initialized&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt; */&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; native &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; seekTo(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; msec) throws IllegalStateException;  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;好，我们来看看此方法的JNI是如何实现的。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; msec)    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     sp&amp;lt;MediaPlayer&amp;gt; mp = getMediaPlayer(env, thiz);&lt;span style="color: #008000"&gt;//获取MediaPlayer实例&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mp == NULL ) {    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/IllegalStateException&amp;quot;&lt;/span&gt;, NULL);    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     LOGV(&lt;span style="color: #006080"&gt;&amp;quot;seekTo: %d(msec)&amp;quot;&lt;/span&gt;, msec);    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     status_t result = mp-&amp;gt;seekTo(msec);&lt;span style="color: #008000"&gt;//1,调用MediaPlayer的seekTo方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     process_media_player_call( env, thiz, result, NULL, NULL );&lt;span style="color: #008000"&gt;//2,处理MediaPlayer方法调用的返回结果&lt;/span&gt;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;font style="background-color: #ffff00" size="3"&gt;&lt;strong&gt;1，调用MediaPlayer的seekTo方法&lt;/strong&gt;&lt;/font&gt; &lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; status_t MediaPlayer::seekTo_l(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; msec)    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     LOGV(&lt;span style="color: #006080"&gt;&amp;quot;seekTo %d&amp;quot;&lt;/span&gt;, msec);    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((mPlayer != 0) &amp;amp;&amp;amp; ( mCurrentState &amp;amp; ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( msec &amp;lt; 0 ) {    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             LOGW(&lt;span style="color: #006080"&gt;&amp;quot;Attempt to seek to invalid position: %d&amp;quot;&lt;/span&gt;, msec);    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             msec = 0;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((mDuration &amp;gt; 0) &amp;amp;&amp;amp; (msec &amp;gt; mDuration)) {    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             LOGW(&lt;span style="color: #006080"&gt;&amp;quot;Attempt to seek to past end of file: request = %d, EOF = %d&amp;quot;&lt;/span&gt;, msec, mDuration);    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             msec = mDuration;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// cache duration&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         mCurrentPosition = msec;    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mSeekPosition &amp;lt; 0) {    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             getDuration_l(NULL);    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             mSeekPosition = msec;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//调用seekTo了&lt;/span&gt;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; mPlayer-&amp;gt;seekTo(msec);    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             LOGV(&lt;span style="color: #006080"&gt;&amp;quot;Seek in progress - queue up seekTo[%d]&amp;quot;&lt;/span&gt;, msec);    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; NO_ERROR;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     LOGE(&lt;span style="color: #006080"&gt;&amp;quot;Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u&amp;quot;&lt;/span&gt;, mPlayer.get(), mCurrentState);    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; INVALID_OPERATION;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt; }    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  29:&lt;/span&gt; status_t MediaPlayer::seekTo(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; msec)    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;     mLockThreadId = getThreadId();    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     Mutex::Autolock _l(mLock);    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     status_t result = seekTo_l(msec);    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     mLockThreadId = 0;    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;    &lt;span style="color: #606060"&gt;  36:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;2，处理MediaPlayer方法调用的返回结果&lt;/font&gt;&lt;/strong&gt; &lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* exception, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *message)    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (exception == NULL) {  &lt;span style="color: #008000"&gt;// Don't throw exception. Instead, send an event.&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (opStatus != (status_t) OK) {    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             sp&amp;lt;MediaPlayer&amp;gt; mp = getMediaPlayer(env, thiz);    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mp != 0) mp-&amp;gt;notify(MEDIA_ERROR, opStatus, 0);&lt;span style="color: #008000"&gt;//调用MediaPlayer的notify&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {  &lt;span style="color: #008000"&gt;// Throw exception!&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( opStatus == (status_t) INVALID_OPERATION ) {    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/IllegalStateException&amp;quot;&lt;/span&gt;, NULL);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( opStatus != (status_t) OK ) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (strlen(message) &amp;gt; 230) {    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;                &lt;span style="color: #008000"&gt;// if the message is too long, don't bother displaying the status code&lt;/span&gt;    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                jniThrowException( env, exception, message);    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; msg[256];    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// append the status code to the message&lt;/span&gt;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                sprintf(msg, &lt;span style="color: #006080"&gt;&amp;quot;%s: status=0x%X&amp;quot;&lt;/span&gt;, message, opStatus);    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                jniThrowException( env, exception, msg);    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;接下来看看MediaPlayer的notify方法，这个方法主要是通过判断MediaPlayer的状态向我们的app发送回调：&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; MediaPlayer::notify(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; msg, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ext1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ext2)    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     LOGV(&lt;span style="color: #006080"&gt;&amp;quot;message received msg=%d, ext1=%d, ext2=%d&amp;quot;&lt;/span&gt;, msg, ext1, ext2);    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; send = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; locked = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// TODO: In the future, we might be on the same thread if the app is&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// running in the same process as the media server. In that case,&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// this will deadlock.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//&lt;/span&gt;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// The threadId hack below works around this for the care of prepare&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// and seekTo within the same process.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// FIXME: Remember, this is a hack, it's not even a hack that is applied&lt;/span&gt;    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// consistently for all use-cases, this needs to be revisited.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mLockThreadId != getThreadId()) {    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         mLock.&lt;span style="color: #0000ff"&gt;lock&lt;/span&gt;();    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         locked = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mPlayer == 0) {    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;notify(%d, %d, %d) callback on disconnected mediaplayer&amp;quot;&lt;/span&gt;, msg, ext1, ext2);    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (locked) mLock.unlock();   &lt;span style="color: #008000"&gt;// release the lock when done.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt; (msg) {    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_NOP: &lt;span style="color: #008000"&gt;// interface test message&lt;/span&gt;    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_PREPARED:&lt;span style="color: #008000"&gt;//prepared结束&lt;/span&gt;    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;prepared&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         mCurrentState = MEDIA_PLAYER_PREPARED;    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mPrepareSync) {    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;             LOGV(&lt;span style="color: #006080"&gt;&amp;quot;signal application thread&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;             mPrepareSync = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;             mPrepareStatus = NO_ERROR;    &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;             mSignal.signal();    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_PLAYBACK_COMPLETE:&lt;span style="color: #008000"&gt;//播放完毕&lt;/span&gt;    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;playback complete&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!mLoop) {    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt;             mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;    &lt;span style="color: #606060"&gt;  43:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  44:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  45:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_ERROR:&lt;span style="color: #008000"&gt;//出错&lt;/span&gt;    &lt;span style="color: #606060"&gt;  46:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// Always log errors.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  47:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// ext1: Media framework error code.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  48:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// ext2: Implementation dependant error code.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  49:&lt;/span&gt;         LOGE(&lt;span style="color: #006080"&gt;&amp;quot;error (%d, %d)&amp;quot;&lt;/span&gt;, ext1, ext2);    &lt;span style="color: #606060"&gt;  50:&lt;/span&gt;         mCurrentState = MEDIA_PLAYER_STATE_ERROR;    &lt;span style="color: #606060"&gt;  51:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mPrepareSync)    &lt;span style="color: #606060"&gt;  52:&lt;/span&gt;         {    &lt;span style="color: #606060"&gt;  53:&lt;/span&gt;             LOGV(&lt;span style="color: #006080"&gt;&amp;quot;signal application thread&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  54:&lt;/span&gt;             mPrepareSync = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  55:&lt;/span&gt;             mPrepareStatus = ext1;    &lt;span style="color: #606060"&gt;  56:&lt;/span&gt;             mSignal.signal();    &lt;span style="color: #606060"&gt;  57:&lt;/span&gt;             send = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  58:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  59:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  60:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_INFO:&lt;span style="color: #008000"&gt;//logcat经常可以看到&lt;/span&gt;    &lt;span style="color: #606060"&gt;  61:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// ext1: Media framework error code.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  62:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// ext2: Implementation dependant error code.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  63:&lt;/span&gt;         LOGW(&lt;span style="color: #006080"&gt;&amp;quot;info/warning (%d, %d)&amp;quot;&lt;/span&gt;, ext1, ext2);    &lt;span style="color: #606060"&gt;  64:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  65:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_SEEK_COMPLETE:&lt;span style="color: #008000"&gt;//seek完毕&lt;/span&gt;    &lt;span style="color: #606060"&gt;  66:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;Received seek complete&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  67:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mSeekPosition != mCurrentPosition) {    &lt;span style="color: #606060"&gt;  68:&lt;/span&gt;             LOGV(&lt;span style="color: #006080"&gt;&amp;quot;Executing queued seekTo(%d)&amp;quot;&lt;/span&gt;, mSeekPosition);    &lt;span style="color: #606060"&gt;  69:&lt;/span&gt;             mSeekPosition = -1;    &lt;span style="color: #606060"&gt;  70:&lt;/span&gt;             seekTo_l(mCurrentPosition);    &lt;span style="color: #606060"&gt;  71:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  72:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  73:&lt;/span&gt;             LOGV(&lt;span style="color: #006080"&gt;&amp;quot;All seeks complete - return to regularly scheduled program&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  74:&lt;/span&gt;             mCurrentPosition = mSeekPosition = -1;    &lt;span style="color: #606060"&gt;  75:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  76:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  77:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_BUFFERING_UPDATE:&lt;span style="color: #008000"&gt;//缓冲&lt;/span&gt;    &lt;span style="color: #606060"&gt;  78:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;buffering %d&amp;quot;&lt;/span&gt;, ext1);    &lt;span style="color: #606060"&gt;  79:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  80:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; MEDIA_SET_VIDEO_SIZE:&lt;span style="color: #008000"&gt;//设置视频大小&lt;/span&gt;    &lt;span style="color: #606060"&gt;  81:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;New video size %d x %d&amp;quot;&lt;/span&gt;, ext1, ext2);    &lt;span style="color: #606060"&gt;  82:&lt;/span&gt;         mVideoWidth = ext1;    &lt;span style="color: #606060"&gt;  83:&lt;/span&gt;         mVideoHeight = ext2;    &lt;span style="color: #606060"&gt;  84:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  85:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;default&lt;/span&gt;:    &lt;span style="color: #606060"&gt;  86:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;unrecognized message: (%d, %d, %d)&amp;quot;&lt;/span&gt;, msg, ext1, ext2);    &lt;span style="color: #606060"&gt;  87:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  88:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  89:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  90:&lt;/span&gt;     sp&amp;lt;MediaPlayerListener&amp;gt; listener = mListener;    &lt;span style="color: #606060"&gt;  91:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (locked) mLock.unlock();    &lt;span style="color: #606060"&gt;  92:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  93:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// this prevents re-entrant calls into client code&lt;/span&gt;    &lt;span style="color: #606060"&gt;  94:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((listener != 0) &amp;amp;&amp;amp; send) {    &lt;span style="color: #606060"&gt;  95:&lt;/span&gt;         Mutex::Autolock _l(mNotifyLock);    &lt;span style="color: #606060"&gt;  96:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;callback application&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  97:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//调用监听器，回调应用的监听器&lt;/span&gt;    &lt;span style="color: #606060"&gt;  98:&lt;/span&gt;         listener-&amp;gt;notify(msg, ext1, ext2);    &lt;span style="color: #606060"&gt;  99:&lt;/span&gt;         LOGV(&lt;span style="color: #006080"&gt;&amp;quot;back from callback&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt; 100:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt; 101:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;在监听器的notify方法中，是通过jni“&lt;strong&gt;&lt;font color="#0000ff"&gt;反向调用&lt;/font&gt;&lt;/strong&gt;”MediaPlayer.java中的postEventFromNative，在通过mEventHandler根据不同的消息类型调用不同的监听器。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; postEventFromNative(Object mediaplayer_ref,    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;                                           &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; what, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; arg1, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; arg2, Object obj)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;   {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;       MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mp == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;           &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;       }    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;       &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mp.mEventHandler != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;           Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;           mp.mEventHandler.sendMessage(m);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;       }    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;   }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;OK，至此我们分析了seekTo的整个流程。其他方法的流程是很相似的，大家不妨亲自去看看。&lt;/p&gt;&lt;p&gt;回到本文开头的问题，通过观察logcat得知是发生错误导致的，暂时未找到解决的办法。如果你有解决方法不妨告诉我哦。&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;------------------------&lt;/font&gt;&lt;/p&gt;&lt;p&gt;03-20 03:08:13.302: ERROR/MediaPlayer(419): Attempt to call getDuration without a valid mediaplayer   &lt;br /&gt;03-20 03:08:13.365: ERROR/MediaPlayer(419): error (-38, 0)   &lt;br /&gt;03-20 03:08:13.372: ERROR/MediaPlayer(419): Attempt to call getDuration without a valid mediaplayer   &lt;br /&gt;03-20 03:08:13.512: ERROR/MediaPlayer(419): error (-38, 0)   &lt;br /&gt;03-20 03:08:13.522: DEBUG/dalvikvm(419): GC freed 3405 objects / 831072 bytes in 122ms   &lt;br /&gt;03-20 03:08:13.752: ERROR/MediaPlayer(419): Error (-38,0)   &lt;br /&gt;03-20 03:08:13.762: DEBUG/MultiPlayer(419): Error: -38,0   &lt;br /&gt;03-20 03:08:13.772: ERROR/MediaPlayer(419): Error (-38,0)   &lt;br /&gt;03-20 03:08:13.781: ERROR/MediaPlayer(419): pause called in state 0   &lt;br /&gt;03-20 03:08:13.781: ERROR/MediaPlayer(419): error (-38, 0)&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;-------------------------&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;PS：“反向调用”就是在c/c++中通过jni来调用java中的方法或属性。这个叫法很不专业，如果哪位同学知道专业的叫法麻烦留言告诉我。！！！！一定要告诉我哦！！！一定要哦！！！！谢谢！&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="4"&gt;转载请注明出处&lt;/font&gt;：&lt;a href="http://www.cnblogs.com/halzhang"&gt;http://www.cnblogs.com/halzhang&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;----------OK The END------------&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1989287.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/03/20/1989287.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/03/10/1980319.html</id><title type="text">Android学习&amp;mdash;&amp;mdash;MediaScanner源码分析</title><summary type="text">神马是MediaScanner呢？在Android的SDK里面是看不到这个类的，因为被google隐藏了。通过Android的源码我们可以看到MediaScanner的类注解多了一个@hide的标注。所以对于一般应用开发者，此文意义不是很大，大家可以绕道。 在前两篇文章中，最后我们都了解了Android的媒体文件的扫描是在MediaScannerService中调用MediaScanner的sca...</summary><published>2011-03-10T15:35:00Z</published><updated>2011-03-10T15:35:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/03/10/1980319.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/03/10/1980319.html"/><content type="html">&lt;p align="left"&gt;神马是MediaScanner呢？在Android的SDK里面是看不到这个类的，因为被google隐藏了。通过Android的源码我们可以看到MediaScanner的类注解多了一个@hide的标注。所以对于一般应用开发者，此文意义不是很大，大家可以绕道。&lt;/p&gt;  &lt;p&gt;在前两篇文章中，最后我们都了解了Android的媒体文件的扫描是在MediaScannerService中调用MediaScanner的scanDirectories或者scanSingleFile完成最终的扫描的。那么MediaScanner是如何工作的呢？&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #ffff00" size="3"&gt;&lt;strong&gt;&lt;a href="http://t.sina.com.cn/halzhang" target="_blank"&gt;转载请注明出处&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;google对MediaScanner写了一大堆的类注释，如下：&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;/* In summary:&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MediaScannerService calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MediaScanner scanDirectories, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MediaScanner processDirectory (native method), which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;* native MediaScanner processDirectory, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;* native MyMediaScannerClient scanFile, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MyMediaScannerClient scanFile, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MediaScannerClient doScanFile, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MediaScanner processFile (native method), which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt; &lt;span style="color: #008000"&gt;* native MediaScanner processFile, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #008000"&gt;* native parseMP3, parseMP4, parseMidi, parseOgg or parseWMA, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #008000"&gt;* native MyMediaScanner handleStringTag, which calls&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Java MyMediaScanner handleStringTag.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt; &lt;span style="color: #008000"&gt;* Once MediaScanner processFile returns, an entry is inserted in to the database.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt; &lt;span style="color: #008000"&gt;*&lt;/span&gt;    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt; &lt;span style="color: #008000"&gt;* {@hide}&lt;/span&gt;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt; &lt;span style="color: #008000"&gt;*/&lt;/span&gt;  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;下面为调用时序图，如下：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/257730/o_MediaScanner%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86.jpg" target="_blank"&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/halzhang/257730/o_MediaScanner%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86.jpg" width="581" height="480" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;这时序图好像不是很规范！&lt;strong&gt;&lt;font color="#ff0000" size="3"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/257730/o_MediaScanner%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86.jpg" target="_blank"&gt;点击看大图&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;！请见谅。&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smilewithtongueout" alt="吐舌笑脸" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103102334139562.png" /&gt;&amp;#160; 开始看代码把……&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;1，scanDirectories。&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;初始化数据并调用&lt;font color="#ff0000"&gt;&lt;strong&gt;processDirectory&lt;/strong&gt;&lt;/font&gt;处理扫描。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; scanDirectories(String[] directories, String volumeName) {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; start = System.currentTimeMillis();    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//初始化&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             initialize(volumeName);    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//将数据库中的数据缓存到mFileCache&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             &lt;span style="color: #008000"&gt;/*&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000"&gt;             * mFileCache.put(key, new FileCacheEntry(uri, rowId, path, lastModified));&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000"&gt;             */&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             prescan(&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; prescan = System.currentTimeMillis();    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; directories.length; i++) {    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;//扫描处理&lt;/span&gt;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                 processDirectory(directories[i], MediaFile.sFileExtensions, mClient);    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; scan = System.currentTimeMillis();    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//处理后续数据&lt;/span&gt;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             postscan(directories);    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; end = System.currentTimeMillis();  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;font size="3"&gt;2，processDirectory&lt;/font&gt;&lt;/strong&gt; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;这是一个native方法，所以我们直接转向jni，代码如下：&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; android_media_MediaScanner_processDirectory(JNIEnv *env, jobject thiz, jstring path, jstring extensions, jobject client)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {   &lt;span style="color: #008000"&gt;//获取MediaScanner&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     MediaScanner *mp = (MediaScanner *)env-&amp;gt;GetIntField(thiz, fields.context);    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//参数判断，并抛出异常&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (path == NULL) {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/IllegalArgumentException&amp;quot;&lt;/span&gt;, NULL);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extensions == NULL) {    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/IllegalArgumentException&amp;quot;&lt;/span&gt;, NULL);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *pathStr = env-&amp;gt;GetStringUTFChars(path, NULL);    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pathStr == NULL) {  &lt;span style="color: #008000"&gt;// Out of memory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/RuntimeException&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Out of memory&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *extensionsStr = env-&amp;gt;GetStringUTFChars(extensions, NULL);    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extensionsStr == NULL) {  &lt;span style="color: #008000"&gt;// Out of memory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         env-&amp;gt;ReleaseStringUTFChars(path, pathStr);    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/RuntimeException&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Out of memory&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//初始化client实例&lt;/span&gt;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     MyMediaScannerClient myClient(env, client);    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//mp调用processDirectory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     mp-&amp;gt;processDirectory(pathStr, extensionsStr, myClient, ExceptionCheck, env);    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//gc&lt;/span&gt;    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;     env-&amp;gt;ReleaseStringUTFChars(path, pathStr);    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     env-&amp;gt;ReleaseStringUTFChars(extensions, extensionsStr);    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;3，mp-&amp;gt;processDirectory(pathStr, extensionsStr, myClient, ExceptionCheck, env);&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; status_t MediaScanner::processDirectory(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *path, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* extensions,    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         MediaScannerClient&amp;amp; client, ExceptionCheck exceptionCheck, &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;* exceptionEnv)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;span style="color: #008000"&gt;//这方法不知道干吗的，估计跟线程有关&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     InitializeForThread();    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pathLength = strlen(path);    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pathLength &amp;gt;= PATH_MAX) {    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; PVMFFailure;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* pathBuffer = (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *)malloc(PATH_MAX + 1);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!pathBuffer) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; PVMFFailure;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pathRemaining = PATH_MAX - pathLength;    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     strcpy(pathBuffer, path);    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pathBuffer[pathLength - 1] != &lt;span style="color: #006080"&gt;'/'&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         pathBuffer[pathLength] = &lt;span style="color: #006080"&gt;'/'&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         pathBuffer[pathLength + 1] = 0;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         --pathRemaining;    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     client.setLocale(mLocale);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//有是一个关键点&lt;/span&gt;    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     status_t result = doProcessDirectory(pathBuffer, pathRemaining, extensions, client, exceptionCheck, exceptionEnv);    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//释放内存&lt;/span&gt;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     free(pathBuffer);    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;4，doProcessDirectory&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; status_t MediaScanner::doProcessDirectory(&lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *path, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pathRemaining, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* extensions,    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         MediaScannerClient&amp;amp; client, ExceptionCheck exceptionCheck, &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;* exceptionEnv)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     ……    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;      ……    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (type == DT_REG || type == DT_DIR) {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nameLength = strlen(name);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; isDirectory = (type == DT_DIR);    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (nameLength &amp;gt; pathRemaining || (isDirectory &amp;amp;&amp;amp; nameLength + 1 &amp;gt; pathRemaining)) {    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// path too long!&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             strcpy(fileSpot, name);    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (isDirectory) {    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// ignore directories with a name that starts with '.'&lt;/span&gt;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// for example, the Mac &amp;quot;.Trashes&amp;quot; directory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name[0] == &lt;span style="color: #006080"&gt;'.'&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                 strcat(fileSpot, &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;//文件夹，递归调用&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (err) {    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;// pass exceptions up - ignore other errors&lt;/span&gt;    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (exceptionCheck &amp;amp;&amp;amp; exceptionCheck(exceptionEnv)) &lt;span style="color: #0000ff"&gt;goto&lt;/span&gt; failure;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                     LOGE(&lt;span style="color: #006080"&gt;&amp;quot;Error processing '%s' - skipping\n&amp;quot;&lt;/span&gt;, path);    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                 }    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (fileMatchesExtension(path, extensions)) {    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;//文件，扩展名符合&lt;/span&gt;    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; stat statbuf;    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;                 stat(path, &amp;amp;statbuf);    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (statbuf.st_size &amp;gt; 0) {    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;//调用client的scanFile方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                     client.scanFile(path, statbuf.st_mtime, statbuf.st_size);    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt;                 }    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (exceptionCheck &amp;amp;&amp;amp; exceptionCheck(exceptionEnv)) &lt;span style="color: #0000ff"&gt;goto&lt;/span&gt; failure;    &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt; ……    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt; ……  &lt;/div&gt;&lt;/div&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;5，client.scanFile&lt;/font&gt;&lt;/strong&gt; &lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// returns true if it succeeded, false if an exception occured in the Java code&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;  &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; scanFile(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* path, &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; lastModified, &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; fileSize)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;  {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;      jstring pathStr;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((pathStr = mEnv-&amp;gt;NewStringUTF(path)) == NULL) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;      &lt;span style="color: #008000"&gt;//有点反射的感觉，调用java里面mClient中的scanFile方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;      mEnv-&amp;gt;CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;      mEnv-&amp;gt;DeleteLocalRef(pathStr);    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (!mEnv-&amp;gt;ExceptionCheck());    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;  }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;6，mEnv-&amp;gt;CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize);&lt;/font&gt;&lt;/strong&gt; 让我们回到Java&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-openmouthedsmile" alt="大笑" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103102334154381.png" /&gt;&lt;/p&gt;&lt;p&gt;在android.media.MediaScanner.MyMediaScannerClient中的scanFile方法是直接调用doScanFile的，来看看doScanFile&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Uri doScanFile(String path, String mimeType, &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; lastModified, &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; fileSize,    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;                 boolean scanAlways) {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             Uri result = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// long t1 = System.currentTimeMillis();&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;                 FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// rescan for metadata if file was modified since last scan&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (entry != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; (entry.mLastModifiedChanged || scanAlways)) {    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;                     String lowpath = path.toLowerCase();    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;                     boolean ringtones = (lowpath.indexOf(RINGTONES_DIR) &amp;gt; 0);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                     boolean notifications = (lowpath.indexOf(NOTIFICATIONS_DIR) &amp;gt; 0);    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;                     boolean alarms = (lowpath.indexOf(ALARMS_DIR) &amp;gt; 0);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                     boolean podcasts = (lowpath.indexOf(PODCAST_DIR) &amp;gt; 0);    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                     boolean music = (lowpath.indexOf(MUSIC_DIR) &amp;gt; 0)    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;                             || (!ringtones &amp;amp;&amp;amp; !notifications &amp;amp;&amp;amp; !alarms &amp;amp;&amp;amp; !podcasts);    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (isMetadataSupported(mFileType)) {    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                         &lt;span style="color: #008000"&gt;// 调用jni方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;                         processFile(path, mimeType, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (MediaFile.isImageFileType(mFileType)) {    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                         &lt;span style="color: #008000"&gt;// we used to compute the width and height but it's not&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                         &lt;span style="color: #008000"&gt;// worth it&lt;/span&gt;    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                     }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                     result = endFile(entry, ringtones, notifications, alarms, music, podcasts);    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                 }    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;             } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (RemoteException e) {    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                 Log.e(TAG, &lt;span style="color: #006080"&gt;&amp;quot;RemoteException in MediaScanner.scanFile()&amp;quot;&lt;/span&gt;, e);    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// long t2 = System.currentTimeMillis();&lt;/span&gt;    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// Log.v(TAG, &amp;quot;scanFile: &amp;quot; + path + &amp;quot; took &amp;quot; + (t2-t1));&lt;/span&gt;    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         }  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;font color="#ff0000" size="3"&gt;补充：result = endFile(entry, ringtones, notifications, alarms, music, podcasts);就是在这里将媒体数据信息存放到数据库的&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;7，接着是native的 processFile&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; android_media_MediaScanner_processFile(JNIEnv *env, jobject thiz, jstring path, jstring mimeType, jobject client)    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     MediaScanner *mp = (MediaScanner *)env-&amp;gt;GetIntField(thiz, fields.context);    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (path == NULL) {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/IllegalArgumentException&amp;quot;&lt;/span&gt;, NULL);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *pathStr = env-&amp;gt;GetStringUTFChars(path, NULL);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pathStr == NULL) {  &lt;span style="color: #008000"&gt;// Out of memory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/RuntimeException&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Out of memory&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *mimeTypeStr = (mimeType ? env-&amp;gt;GetStringUTFChars(mimeType, NULL) : NULL);    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mimeType &amp;amp;&amp;amp; mimeTypeStr == NULL) {  &lt;span style="color: #008000"&gt;// Out of memory&lt;/span&gt;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         env-&amp;gt;ReleaseStringUTFChars(path, pathStr);    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         jniThrowException(env, &lt;span style="color: #006080"&gt;&amp;quot;java/lang/RuntimeException&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Out of memory&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     MyMediaScannerClient myClient(env, client);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//调用MediaScanner的processFile&lt;/span&gt;    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     mp-&amp;gt;processFile(pathStr, mimeTypeStr, myClient);    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     env-&amp;gt;ReleaseStringUTFChars(path, pathStr);    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mimeType) {    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         env-&amp;gt;ReleaseStringUTFChars(mimeType, mimeTypeStr);    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;8，mp-&amp;gt;processFile(pathStr, mimeTypeStr, myClient);&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;在此方法中根据不同的文件扩展名调用更加底层的解析方法，我想主要是ID3信息解析&lt;/div&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; status_t MediaScanner::processFile(&lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; *path, &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* mimeType, MediaScannerClient&amp;amp; client)    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     status_t result;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     InitializeForThread();    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//初始化client&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     client.setLocale(mLocale);    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     client.beginFile();    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//LOGD(&amp;quot;processFile %s mimeType: %s\n&amp;quot;, path, mimeType);&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;char&lt;/span&gt;* extension = strrchr(path, &lt;span style="color: #006080"&gt;'.'&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//根据扩展名调用不同的解析方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extension &amp;amp;&amp;amp; strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.mp3&amp;quot;&lt;/span&gt;) == 0) {    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         result = parseMP3(path, client);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extension &amp;amp;&amp;amp;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         (strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.mp4&amp;quot;&lt;/span&gt;) == 0 || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.m4a&amp;quot;&lt;/span&gt;) == 0 ||    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;          strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.3gp&amp;quot;&lt;/span&gt;) == 0 || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.3gpp&amp;quot;&lt;/span&gt;) == 0 ||    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;          strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.3g2&amp;quot;&lt;/span&gt;) == 0 || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.3gpp2&amp;quot;&lt;/span&gt;) == 0)) {    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         result = parseMP4(path, client);    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extension &amp;amp;&amp;amp; strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.ogg&amp;quot;&lt;/span&gt;) == 0) {    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         result = parseOgg(path, client);    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extension &amp;amp;&amp;amp;    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         ( strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.mid&amp;quot;&lt;/span&gt;) == 0 || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.smf&amp;quot;&lt;/span&gt;) == 0    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.imy&amp;quot;&lt;/span&gt;) == 0)) {    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         result = parseMidi(path, client);    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (extension &amp;amp;&amp;amp;    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;        (strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.wma&amp;quot;&lt;/span&gt;) == 0 || strcasecmp(extension, &lt;span style="color: #006080"&gt;&amp;quot;.aac&amp;quot;&lt;/span&gt;) == 0)) {    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//TODO: parseWMA needs to be renamed to reflect what it is really doing,&lt;/span&gt;    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//ie. using OpenCORE frame metadata utility(FMU) to retrieve metadata.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;         result = parseWMA(path, client);    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         result = PVMFFailure;    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//调用client&lt;/span&gt;    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     client.endFile();    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffff00" size="3"&gt;9，client.endFile()&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; MediaScannerClient::endFile()    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (mLocaleEncoding != kEncodingNone) {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; size = mNames-&amp;gt;size();    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         uint32_t encoding = kEncodingAll;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// compute a bit mask containing all possible encodings&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; mNames-&amp;gt;size(); i++)    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             encoding &amp;amp;= possibleEncodings(mValues-&amp;gt;getEntry(i));    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// if the locale encoding matches, then assume we have a native encoding.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (encoding &amp;amp; mLocaleEncoding)    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             convertValues(mLocaleEncoding);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// finally, push all name/value pairs to the client&lt;/span&gt;    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; mNames-&amp;gt;size(); i++) {    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//在handleStringTag中是通过类反射的方法调用java中的handleStringTag&lt;/span&gt;    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!handleStringTag(mNames-&amp;gt;getEntry(i), mValues-&amp;gt;getEntry(i)))    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// else addStringTag() has done all the work so we have nothing to do&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     delete mNames;    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     delete mValues;    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     mNames = NULL;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     mValues = NULL;    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;font style="background-color: #ffff00"&gt;&lt;strong&gt;&lt;font size="3"&gt;10，java中的handleStringTag&lt;/font&gt;&lt;/strong&gt;，这个方法主要处理那些在底层解析后的数据返回到java层&lt;/font&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; handleStringTag(String name, String &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;title&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;title;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// Don't trim() here, to preserve the special \001 character&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// used to force sorting. The media provider will trim() before&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// inserting the title in to the database.&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;          mTitle = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;artist&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;artist;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;          mArtist = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.trim();    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;albumartist&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;albumartist;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;          mAlbumArtist = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.trim();    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;album&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;album;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;          mAlbum = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.trim();    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;composer&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;composer;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;          mComposer = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.trim();    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;genre&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;genre;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// handle numeric genres, which PV sometimes encodes like &amp;quot;(20)&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;          &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.length() &amp;gt; 0) {    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;              &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; genreCode = -1;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;              &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; ch = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.charAt(0);    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;              &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ch == &lt;span style="color: #006080"&gt;'('&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                  genreCode = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 1, -1);    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;              } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ch &amp;gt;= &lt;span style="color: #006080"&gt;'0'&lt;/span&gt; &amp;amp;&amp;amp; ch &amp;lt;= &lt;span style="color: #006080"&gt;'9'&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                  genreCode = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 0, -1);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;              }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;              &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (genreCode &amp;gt;= 0 &amp;amp;&amp;amp; genreCode &amp;lt; ID3_GENRES.length) {    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                  &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; = ID3_GENRES[genreCode];    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;              }    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;          }    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;          mGenre = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;year&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;year;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;          mYear = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 0, 0);    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;tracknumber&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;tracknumber;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// track number might be of the form &amp;quot;2/12&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// we just read the number before the slash&lt;/span&gt;    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;          &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; num = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 0, 0);    &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;          mTrack = (mTrack / 1000) * 1000 + num;    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;discnumber&amp;quot;&lt;/span&gt;) ||    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt;              name.equals(&lt;span style="color: #006080"&gt;&amp;quot;set&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;set;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// set number might be of the form &amp;quot;1/3&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;          &lt;span style="color: #008000"&gt;// we just read the number before the slash&lt;/span&gt;    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt;          &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; num = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 0, 0);    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt;          mTrack = (num * 1000) + (mTrack % 1000);    &lt;span style="color: #606060"&gt;  43:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;duration&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  44:&lt;/span&gt;          mDuration = parseSubstring(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, 0, 0);    &lt;span style="color: #606060"&gt;  45:&lt;/span&gt;      } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (name.equalsIgnoreCase(&lt;span style="color: #006080"&gt;&amp;quot;writer&amp;quot;&lt;/span&gt;) || name.startsWith(&lt;span style="color: #006080"&gt;&amp;quot;writer;&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  46:&lt;/span&gt;          mWriter = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;.trim();    &lt;span style="color: #606060"&gt;  47:&lt;/span&gt;      }    &lt;span style="color: #606060"&gt;  48:&lt;/span&gt;  }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;此致，此文结束，累。&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-ninja" alt="忍者" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103102334162363.png" /&gt;&lt;/p&gt;&lt;p&gt;三篇有关MediaScanner的文章，希望对大家有所帮助。&lt;/p&gt;&lt;p&gt;对C/C++不是很熟悉，如发现分析有误，请告知。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#a5a5a5" size="4"&gt;&lt;a href="http://t.sina.com.cn/halzhang" target="_blank"&gt;转载请注明出处&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;--------END-------&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1980319.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/03/10/1980319.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/03/08/1977314.html</id><title type="text">Android开发&amp;mdash;&amp;mdash;MediaProvider源码分析（2）</title><summary type="text">转载请注明出处！ 欲读此文，先读上文：MediaProvider源码分析（1） ----------------------START--------------------------- 在上一篇文章中说到系统当接收到扫描请求广播的时候就会调用scan或者scanFile去扫描手机（手机内存和sdcard）中的媒体文件。这两个方法都是启动MediaScannerService这个服务来完成扫描任...</summary><published>2011-03-08T07:25:00Z</published><updated>2011-03-08T07:25:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/03/08/1977314.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/03/08/1977314.html"/><content type="html">&lt;p&gt;&lt;a href="http://t.sina.com.cn/halzhang" target="_blank"&gt;转载请注明出处！&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;欲读此文，先读上文：&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html" target="_blank"&gt;MediaProvider源码分析（1）&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;----------------------START---------------------------&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在上一篇文章中说到系统当接收到扫描请求广播的时候就会调用scan或者scanFile去扫描手机（手机内存和sdcard）中的媒体文件。这两个方法都是启动MediaScannerService这个服务来完成扫描任务的。接下来我们来看看MediaScannerService是怎么工作的……&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;4.MediaScannerService（MSS）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;MSS实现了Runnable，所以必然的需要实现run方法了，代码如下：&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; run()    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;    {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;        &lt;span style="color: #008000"&gt;// reduce priority below other background threads to avoid interfering&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;        &lt;span style="color: #008000"&gt;// with other services at boot time.&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND +    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;                Process.THREAD_PRIORITY_LESS_FAVORABLE);    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;        Looper.prepare();    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;        mServiceLooper = Looper.myLooper();    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;        mServiceHandler = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ServiceHandler();    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;        Looper.loop();    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;    }  &lt;/div&gt;&lt;/div&gt;在run方法中设置了线程的优先级，优先级比较低，主要为了避免跟其他服务抢夺资源。还有就是利用looper对ServiceHandler的消息进行循环控制。 &lt;p&gt;接着看一下&lt;strong&gt;&lt;font color="#0000ff"&gt;ServiceHandler&lt;/font&gt;&lt;/strong&gt;的实现代码：&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; final &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ServiceHandler extends Handler    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;    {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;        @Override    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; handleMessage(Message msg)    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;        {    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;            Bundle arguments = (Bundle) msg.obj;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;            &lt;span style="color: #008000"&gt;//获取文件路径&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;            String filePath = arguments.getString(&lt;span style="color: #006080"&gt;&amp;quot;filepath&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;                &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (filePath != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;//文件路径不为空，则调用扫面当个文件的方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;                    IBinder binder = arguments.getIBinder(&lt;span style="color: #006080"&gt;&amp;quot;listener&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                    IMediaScannerListener listener =     &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                            (binder == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; ? &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; : IMediaScannerListener.Stub.asInterface(binder));    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;                    Uri uri = scanFile(filePath, arguments.getString(&lt;span style="color: #006080"&gt;&amp;quot;mimetype&amp;quot;&lt;/span&gt;));&lt;span style="color: #008000"&gt;//扫描单个文件&lt;/span&gt;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (listener != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                         &lt;span style="color: #008000"&gt;//执行扫描完成方法&lt;/span&gt;    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                        listener.scanCompleted(filePath, uri);    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;                    }    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;//如果文件路径为空，则获取扫面手机内存或者sdcard&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                    String volume = arguments.getString(&lt;span style="color: #006080"&gt;&amp;quot;volume&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                    String[] directories = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;                    &lt;span style="color: #008000"&gt;//内置卡&lt;/span&gt;    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (MediaProvider.INTERNAL_VOLUME.equals(volume)) {    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                        &lt;span style="color: #008000"&gt;// scan internal media storage&lt;/span&gt;    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                        directories = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; String[] {    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                                Environment.getRootDirectory() + &lt;span style="color: #006080"&gt;&amp;quot;/media&amp;quot;&lt;/span&gt;,    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;                        };    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;                    }&lt;span style="color: #008000"&gt;//外置卡&lt;/span&gt;    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (MediaProvider.EXTERNAL_VOLUME.equals(volume)) {    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;                        &lt;span style="color: #008000"&gt;// scan external storage&lt;/span&gt;    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;                        directories = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; String[] {    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;                                Environment.getExternalStorageDirectory().getPath(),    &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                                };    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt;                    }    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt;                        &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (directories != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Config.LOGD) Log.d(TAG, &lt;span style="color: #006080"&gt;&amp;quot;start scanning volume &amp;quot;&lt;/span&gt; + volume);    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt;                         &lt;span style="color: #008000"&gt;//扫描&lt;/span&gt;    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt;                        scan(directories, volume);    &lt;span style="color: #606060"&gt;  43:&lt;/span&gt;                        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Config.LOGD) Log.d(TAG, &lt;span style="color: #006080"&gt;&amp;quot;done scanning volume &amp;quot;&lt;/span&gt; + volume);    &lt;span style="color: #606060"&gt;  44:&lt;/span&gt;                    }    &lt;span style="color: #606060"&gt;  45:&lt;/span&gt;                }    &lt;span style="color: #606060"&gt;  46:&lt;/span&gt;            } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e) {    &lt;span style="color: #606060"&gt;  47:&lt;/span&gt;                Log.e(TAG, &lt;span style="color: #006080"&gt;&amp;quot;Exception in handleMessage&amp;quot;&lt;/span&gt;, e);    &lt;span style="color: #606060"&gt;  48:&lt;/span&gt;            }    &lt;span style="color: #606060"&gt;  49:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  50:&lt;/span&gt;            stopSelf(msg.arg1);    &lt;span style="color: #606060"&gt;  51:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  52:&lt;/span&gt;    };  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;在ServiceHandler中主要根据相关参数来调用不同的扫描方法。&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-openmouthedsmile" alt="大笑" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103081524266281.png" /&gt;&lt;/p&gt;&lt;p&gt;那是在哪里调用ServiceHandler发送消息的呢？请看如下代码：&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; @Override    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onCreate() {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//启用新线程，这样就可以避免阻塞，执行run，初始化成员变量loop和handler&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     Thread thr = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Thread(&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;MediaScannerService&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     thr.start();    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt; }    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  10:&lt;/span&gt; @Override    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; onStartCommand(Intent intent, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; flags, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; startId) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (mServiceHandler == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         synchronized (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;                 wait(100);    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (InterruptedException e) {    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (intent == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         Log.e(TAG, &lt;span style="color: #006080"&gt;&amp;quot;Intent is null in onStartCommand: &amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NullPointerException());    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Service.START_NOT_STICKY;    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     Message msg = mServiceHandler.obtainMessage();    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     msg.arg1 = startId;    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     msg.obj = intent.getExtras();    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//ServiceHandler发送消息&lt;/span&gt;    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;     mServiceHandler.sendMessage(msg);    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Try again later if we are killed before we can finish scanning.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Service.START_REDELIVER_INTENT;    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt; }    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  36:&lt;/span&gt; @Override    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onDestroy() {    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt;     &lt;span style="color: #008000"&gt;// Make sure thread has started before telling it to quit.&lt;/span&gt;    &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (mServiceLooper == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         synchronized (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt;                 wait(100);    &lt;span style="color: #606060"&gt;  43:&lt;/span&gt;             } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (InterruptedException e) {    &lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  45:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  46:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  47:&lt;/span&gt;     mServiceLooper.quit();    &lt;span style="color: #606060"&gt;  48:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;以上三个方法是属于Service的生命周期的。当我们调用startService的时候，如果对应的Service还未创建就会调用onCreate方法===方法。每次startService的时候就调用onStartCommand，所以ServiceHandler就在此发送消息了。&lt;/div&gt;&lt;p&gt;最后，稍微看一下MSS里面扫描方面。主要是调用MediaScanner对媒体文件进行扫描分析的。至于MediaScanner的实现以后在分析。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; openDatabase(String volumeName) {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;            ContentValues values = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ContentValues();    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;            values.put(&lt;span style="color: #006080"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;, volumeName);    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;            getContentResolver().insert(Uri.parse(&lt;span style="color: #006080"&gt;&amp;quot;content://media/&amp;quot;&lt;/span&gt;), values);    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;        } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (IllegalArgumentException ex) {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;            Log.w(TAG, &lt;span style="color: #006080"&gt;&amp;quot;failed to open media database&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;        }             &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;    }    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; closeDatabase(String volumeName) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;            getContentResolver().delete(    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                    Uri.parse(&lt;span style="color: #006080"&gt;&amp;quot;content://media/&amp;quot;&lt;/span&gt; + volumeName), &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;        } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e) {    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;            Log.w(TAG, &lt;span style="color: #006080"&gt;&amp;quot;failed to close media database &amp;quot;&lt;/span&gt; + volumeName + &lt;span style="color: #006080"&gt;&amp;quot; exception: &amp;quot;&lt;/span&gt; + e);    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;    }    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt; &lt;span style="color: #008000"&gt;//创建扫描器&lt;/span&gt;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; MediaScanner createMediaScanner() {    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;        MediaScanner scanner = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MediaScanner(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;        Locale locale = getResources().getConfiguration().locale;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (locale != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;            String language = locale.getLanguage();    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;            String country = locale.getCountry();    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;            String localeString = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (language != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (country != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                    scanner.setLocale(language + &lt;span style="color: #006080"&gt;&amp;quot;_&amp;quot;&lt;/span&gt; + country);    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;                } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;                    scanner.setLocale(language);    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                }    &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;            }        &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;            &lt;span style="color: #606060"&gt;  36:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; scanner;    &lt;span style="color: #606060"&gt;  37:&lt;/span&gt;    }    &lt;span style="color: #606060"&gt;  38:&lt;/span&gt; &lt;span style="color: #008000"&gt;//扫描目录&lt;/span&gt;    &lt;span style="color: #606060"&gt;  39:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; scan(String[] directories, String volumeName) {    &lt;span style="color: #606060"&gt;  40:&lt;/span&gt;        &lt;span style="color: #008000"&gt;// don't sleep while scanning&lt;/span&gt;    &lt;span style="color: #606060"&gt;  41:&lt;/span&gt;        mWakeLock.acquire();    &lt;span style="color: #606060"&gt;  42:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  43:&lt;/span&gt;        ContentValues values = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ContentValues();    &lt;span style="color: #606060"&gt;  44:&lt;/span&gt;        values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName);    &lt;span style="color: #606060"&gt;  45:&lt;/span&gt;        Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values);    &lt;span style="color: #606060"&gt;  46:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  47:&lt;/span&gt;        Uri uri = Uri.parse(&lt;span style="color: #006080"&gt;&amp;quot;file://&amp;quot;&lt;/span&gt; + directories[0]);    &lt;span style="color: #606060"&gt;  48:&lt;/span&gt;        sendBroadcast(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Intent(Intent.ACTION_MEDIA_SCANNER_STARTED, uri));    &lt;span style="color: #606060"&gt;  49:&lt;/span&gt;            &lt;span style="color: #606060"&gt;  50:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  51:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) {    &lt;span style="color: #606060"&gt;  52:&lt;/span&gt;                 openDatabase(volumeName);        &lt;span style="color: #606060"&gt;  53:&lt;/span&gt;            }    &lt;span style="color: #606060"&gt;  54:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  55:&lt;/span&gt;            MediaScanner scanner = createMediaScanner();    &lt;span style="color: #606060"&gt;  56:&lt;/span&gt;            scanner.scanDirectories(directories, volumeName);    &lt;span style="color: #606060"&gt;  57:&lt;/span&gt;        } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e) {    &lt;span style="color: #606060"&gt;  58:&lt;/span&gt;            Log.e(TAG, &lt;span style="color: #006080"&gt;&amp;quot;exception in MediaScanner.scan()&amp;quot;&lt;/span&gt;, e);     &lt;span style="color: #606060"&gt;  59:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  60:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  61:&lt;/span&gt;        getContentResolver().delete(scanUri, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  62:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  63:&lt;/span&gt;        sendBroadcast(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri));    &lt;span style="color: #606060"&gt;  64:&lt;/span&gt;        mWakeLock.release();    &lt;span style="color: #606060"&gt;  65:&lt;/span&gt;    }    &lt;span style="color: #606060"&gt;  66:&lt;/span&gt; &lt;span style="color: #008000"&gt;//扫描文件&lt;/span&gt;    &lt;span style="color: #606060"&gt;  67:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Uri scanFile(String path, String mimeType) {    &lt;span style="color: #606060"&gt;  68:&lt;/span&gt;         String volumeName = MediaProvider.INTERNAL_VOLUME;    &lt;span style="color: #606060"&gt;  69:&lt;/span&gt;         String externalStoragePath = Environment.getExternalStorageDirectory().getPath();    &lt;span style="color: #606060"&gt;  70:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  71:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (path.startsWith(externalStoragePath)) {    &lt;span style="color: #606060"&gt;  72:&lt;/span&gt;             volumeName = MediaProvider.EXTERNAL_VOLUME;    &lt;span style="color: #606060"&gt;  73:&lt;/span&gt;             openDatabase(volumeName);    &lt;span style="color: #606060"&gt;  74:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  75:&lt;/span&gt;         MediaScanner scanner = createMediaScanner();    &lt;span style="color: #606060"&gt;  76:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//扫描单个文件&lt;/span&gt;    &lt;span style="color: #606060"&gt;  77:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; scanner.scanSingleFile(path, volumeName, mimeType);    &lt;span style="color: #606060"&gt;  78:&lt;/span&gt;     }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;在MediaProvider中还有一个类：MediaThumbRequest，用来创建预览图的，比如视频的预览图，图片的预览图，音频的专辑图片…这些图片的信息也是保存在数据库的，有兴趣的同学可以自己打开数据库看看里面的表。如下图：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103081524287653.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="media_db_tables" border="0" alt="media_db_tables" src="http://images.cnblogs.com/cnblogs_com/halzhang/201103/201103081524312896.jpg" width="322" height="395" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;啰哩啰唆的写了两篇文章，希望对大家有所帮助。&lt;/p&gt;&lt;p&gt;其中应该有不少是错误的观点，望大家指正。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;----------------------END------------------------------&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1977314.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/03/08/1977314.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html</id><title type="text">Android开发&amp;mdash;&amp;mdash;MediaProvider源码分析（1）</title><summary type="text">转载请注明出处。 --------------START------------ MediaProvider包括五个类： com.android.providers.media.MediaProvider com.android.providers.media.MediaScannerCursor com.android.providers.media.MediaScannerReceiver c...</summary><published>2011-03-07T12:40:00Z</published><updated>2011-03-07T12:40:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html"/><content type="html">&lt;p&gt;&lt;a href="http://t.sina.com.cn/halzhang" target="_blank"&gt;转载请注明出处。&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;--------------START------------&lt;/p&gt;  &lt;p&gt;MediaProvider包括五个类：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;com.android.providers.media.MediaProvider &lt;/li&gt;    &lt;li&gt;com.android.providers.media.MediaScannerCursor &lt;/li&gt;    &lt;li&gt;com.android.providers.media.MediaScannerReceiver &lt;/li&gt;    &lt;li&gt;com.android.providers.media.MediaScannerService &lt;/li&gt;    &lt;li&gt;com.android.providers.media.MediaThumbRequest &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;1.MediaProvider&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;此类继承ContentProvider，实现一个内容提供者。主要用于创建媒体库的数据库表。有自己创建过ContentProvider的同学相信都比较清楚的。&lt;/p&gt;  &lt;p&gt;特别说明一下在MediaProvider中有个广播接收者，代码如下：&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; BroadcastReceiver mUnmountReceiver = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; BroadcastReceiver() {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;         @Override    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onReceive(Context context, Intent intent) {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (intent.getAction().equals(Intent.ACTION_MEDIA_EJECT)) {    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// Remove the external volume and then notify all cursors backed by&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// data on that volume&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;                 detachVolume(Uri.parse(&lt;span style="color: #006080"&gt;&amp;quot;content://media/external&amp;quot;&lt;/span&gt;));    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;                 sFolderArtMap.clear();    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;                 MiniThumbFile.reset();    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     };  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;此接收者是用来接收Sdcard卸载的广播。当Sdcard从手机中分离出来的时候，Sdcard中的媒体文件相对应的数据库将无法操作。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; detachVolume(Uri uri) {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;        &lt;span style="color: #008000"&gt;//判断是否是同一个进程&lt;/span&gt;    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Process.supportsProcesses() &amp;amp;&amp;amp; Binder.getCallingPid() != Process.myPid()) {    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SecurityException(    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;                    &lt;span style="color: #006080"&gt;&amp;quot;Opening and closing databases not allowed.&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//此方法只是操作Sdcard的媒体数据库，不支持手机内存的媒体数据库&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;        String volume = uri.getPathSegments().get(0);    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (INTERNAL_VOLUME.equals(volume)) {    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; UnsupportedOperationException(    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;                    &lt;span style="color: #006080"&gt;&amp;quot;Deleting the internal volume is not allowed&amp;quot;&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;        } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!EXTERNAL_VOLUME.equals(volume)) {    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IllegalArgumentException(    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                    &lt;span style="color: #006080"&gt;&amp;quot;There is no volume named &amp;quot;&lt;/span&gt; + volume);    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;        synchronized (mDatabases) {    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;            DatabaseHelper database = mDatabases.get(volume);    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (database == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;            &lt;span style="color: #0000ff"&gt;try&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                &lt;span style="color: #008000"&gt;// touch the database file to show it is most recently used&lt;/span&gt;    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                File file = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; File(database.getReadableDatabase().getPath());    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                file.setLastModified(System.currentTimeMillis());    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;            } &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (SQLException e) {    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;                Log.e(TAG, &lt;span style="color: #006080"&gt;&amp;quot;Can't touch database file&amp;quot;&lt;/span&gt;, e);    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;            }    &lt;span style="color: #606060"&gt;  28:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//移除数据库&lt;/span&gt;    &lt;span style="color: #606060"&gt;  29:&lt;/span&gt;            mDatabases.remove(volume);    &lt;span style="color: #606060"&gt;  30:&lt;/span&gt;            database.close();    &lt;span style="color: #606060"&gt;  31:&lt;/span&gt;        }    &lt;span style="color: #606060"&gt;  32:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  33:&lt;/span&gt;        getContext().getContentResolver().notifyChange(uri, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);    &lt;span style="color: #606060"&gt;  34:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (LOCAL_LOGV) Log.v(TAG, &lt;span style="color: #006080"&gt;&amp;quot;Detached volume: &amp;quot;&lt;/span&gt; + volume);    &lt;span style="color: #606060"&gt;  35:&lt;/span&gt;    }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;注意移除数据库并非删除数据库文件（*.db）,mDatabases是一个HashMap&amp;lt;String,DatabaseHelper&amp;gt;,移除的含义是暂时无法操作，也可以说说是查询返回的数据都是空的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;2.MediaScannerCursor&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;一个自定义游标，用来查询媒体文件的扫描状态。主要有一个volume字段，用来区分是内置媒体数据库还是Sdcard的媒体数据库。&lt;/p&gt;&lt;p&gt;&lt;font color="#333333" size="4"&gt;&lt;strong&gt;3.MediaScannerReceiver&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;此类实现广播接收者。接收到广播的时候对手机的媒体文件进行扫描。&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MediaScannerReceiver extends BroadcastReceiver    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; final &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; String TAG = &lt;span style="color: #006080"&gt;&amp;quot;MediaScannerReceiver&amp;quot;&lt;/span&gt;;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     @Override    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; onReceive(Context context, Intent intent) {    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         String action = intent.getAction();    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         Uri uri = intent.getData();    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         String externalStoragePath = Environment.getExternalStorageDirectory().getPath();    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//系统启动完毕&lt;/span&gt;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (action.equals(Intent.ACTION_BOOT_COMPLETED)) {    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// scan internal storage&lt;/span&gt;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             scan(context, MediaProvider.INTERNAL_VOLUME);    &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (uri.getScheme().equals(&lt;span style="color: #006080"&gt;&amp;quot;file&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// handle intents related to external storage&lt;/span&gt;    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 String path = uri.getPath();    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (action.equals(Intent.ACTION_MEDIA_MOUNTED&lt;span style="color: #008000"&gt;/*Sdcard挂载广播*/&lt;/span&gt;) &amp;amp;&amp;amp;     &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                         externalStoragePath.equals(path)) {    &lt;span style="color: #606060"&gt;  20:&lt;/span&gt;                     scan(context, MediaProvider.EXTERNAL_VOLUME);    &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                 } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE&lt;span style="color: #008000"&gt;/*单个文件扫描广播*/&lt;/span&gt;) &amp;amp;&amp;amp;    &lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                         path != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; path.startsWith(externalStoragePath + &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;)) {    &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                     scanFile(context, path);    &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                 }    &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             }    &lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         }    &lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;扫描分为两种三种情况：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="3"&gt;a,启动完毕扫面手机内存中的媒体文件&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="3"&gt;b.sdcard挂载完毕扫描扩展卡的媒体文件&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="3"&gt;c,扫描单个文件&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;应用实例：我们可以发送不同的广播让系统去扫描媒体文件。当需要扫描单个文件的时候需要设置一些参数，如下：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;/**&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;     * 扫描文件&lt;/span&gt;    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;     * &lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;     * @param filePath 文件路径&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;     * @author http://t.sina.com.cn/halzhang&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;     */&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; scanOneFile(final String filePath) {    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         Intent intent = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         Uri uri = Uri.parse(&lt;span style="color: #006080"&gt;&amp;quot;file://&amp;quot;&lt;/span&gt; + filePath);    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         intent.setData(uri);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         sendBroadcast(intent);    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;接着看一下&lt;strong&gt;&lt;font size="3"&gt;scan&lt;/font&gt;&lt;/strong&gt;和&lt;strong&gt;&lt;font size="3"&gt;scenFile&lt;/font&gt;&lt;/strong&gt;两个方法：&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; scan(Context context, String volume&lt;span style="color: #008000"&gt;/*内置卡或者外置卡*/&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;        Bundle args = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Bundle();    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;        args.putString(&lt;span style="color: #006080"&gt;&amp;quot;volume&amp;quot;&lt;/span&gt;, volume);    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;        context.startService(    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Intent(context, MediaScannerService.&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;).putExtras(args));    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;    }        &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; scanFile(Context context, String path&lt;span style="color: #008000"&gt;/*文件路径*/&lt;/span&gt;) {    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;        Bundle args = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Bundle();    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;        args.putString(&lt;span style="color: #006080"&gt;&amp;quot;filepath&amp;quot;&lt;/span&gt;, path);    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;        context.startService(    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Intent(context, MediaScannerService.&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;).putExtras(args));    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;    }    &lt;/div&gt;&lt;/div&gt;&lt;p&gt;两个方法都是启动MediaScannerService去扫描媒体文件的。&lt;/p&gt;&lt;p&gt;关于MediaScannerSerive且听下回分解。&lt;/p&gt;&lt;p&gt;-------------------END--------------&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1976178.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/03/07/1976178.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/01/18/1938752.html</id><title type="text">Android开发&amp;mdash;&amp;mdash;Android搜索框架（二）</title><summary type="text">上一篇：Android开发——Android搜索框架(一) 距离上一篇文章有段时间了，唉。 接着上一篇文章，现在说说如何在搜索的时候弹出搜索历史提示。 1.创建搜索建议提供者 Android已经为我们创建了一个默认的，我们只需要继承 SearchRecentSuggestionProvider 就稍做修改就可以了。 见代码： 2.配置searchable.xml 参数说明：android:...</summary><published>2011-01-18T15:40:00Z</published><updated>2011-01-18T15:40:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/01/18/1938752.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/01/18/1938752.html"/><content type="html">&lt;p&gt;上一篇：&lt;a href="http://www.cnblogs.com/halzhang/archive/2010/09/13/1825145.html" target="_blank"&gt;Android开发——Android搜索框架(一)&lt;/a&gt; 距离上一篇文章有段时间了，唉。&lt;/p&gt;  &lt;p&gt;接着上一篇文章，现在说说如何在搜索的时候弹出搜索历史提示。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;1.创建搜索建议提供者&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Android已经为我们创建了一个默认的，我们只需要继承 SearchRecentSuggestionProvider 就稍做修改就可以了。&lt;/p&gt;  &lt;p&gt;见代码：&lt;/p&gt;  &lt;div&gt;   &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;     &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; import android.content.SearchRecentSuggestionsProvider;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;/**&lt;/span&gt;    &lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt; * 搜索提示&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt; * &lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt; * @author Hanguo&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt; * http://t.sina.com.cn/halzhang&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000"&gt; * @version 2011-1-5上午11:51:39&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000"&gt; */&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; SearchSuggestionsProvider extends SearchRecentSuggestionsProvider {    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//记住这个哦&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; final &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; String AUTHORITY = &lt;span style="color: #006080"&gt;&amp;quot;searchprovider&amp;quot;&lt;/span&gt;;    &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; final &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; MODE = DATABASE_MODE_QUERIES;    &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;&amp;#160;     &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; SearchSuggestionsProvider() {    &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         setupSuggestions(AUTHORITY, MODE);    &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     }    &lt;span style="color: #606060"&gt;  19:&lt;/span&gt; }  &lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;2.配置searchable.xml&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #800000"&gt;xml&lt;/span&gt; &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;encoding&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;utf-8&amp;quot;&lt;/span&gt;?&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;searchable&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlns:android&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:label&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;@string/search_label&amp;quot;&lt;/span&gt;     &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:hint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;@string/search_hint&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:searchSettingsDescription&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;@string/search_settings_description&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:searchSuggestAuthority&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;searchprovider&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:searchSuggestIntentAction&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;android.intent.action.SEARCH&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:searchSuggestThreshold&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:includeInGlobalSearch&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;android:searchSuggestSelection&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot; ?&amp;quot;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;    &lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;searchable&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;参数说明：&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;android:searchSuggestAuthorith&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;此属性的值就是SearchSuggestAuthorith中的AUTHORITH了。&lt;/div&gt;&lt;div&gt;&lt;strong&gt;android:searchSuggestIntentAction&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;此属性定义了当我们选中搜索提示的内容时发生的目的动作。&lt;/div&gt;&lt;div&gt;&lt;strong&gt;android:searchSuggestThreshold&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;此属性定义了至少输入几个字符时才会弹出提示&lt;/div&gt;&lt;div&gt;&lt;strong&gt;android:includeInGlobalSearch&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;是否将内容加入android的全局搜索。true，加入。&lt;/div&gt;&lt;div&gt;&lt;font color="#333333"&gt;&lt;strong&gt;android:searchSuggestSelection&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;定义搜索时参数的占位符&lt;/div&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;div&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;PS：配置参数不止这些，可以自己看看android的参考手册。&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;font size="4"&gt;3.配置AndroidManifest.xml&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;  &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;provider&lt;/span&gt; &lt;span style="color: #ff0000"&gt;android:name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;.SearchSuggestionsProvider&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;android:authorities&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;searchprovider&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;  &lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;div&gt;注意authorities的属性值哦。o(∩_∩)o&lt;/div&gt;&lt;p&gt;如有问题欢迎邮件交流。&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;转载请注明出处。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;-----------------end-----------------&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1938752.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/01/18/1938752.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2011/01/05/1926771.html</id><title type="text">[转]activity的启动方式（launch mode）</title><summary type="text">在android里，有4种activity的启动模式，分别为： “standard” (默认) “singleTop” “singleTask” “singleInstance” 它们主要有如下不同： 1. 如何决定所属task “standard”和”singleTop”的activity的目标task，和收到的Intent的发送者在同一个task内，除非intent包括参数FLAG_ACT...</summary><published>2011-01-05T12:55:00Z</published><updated>2011-01-05T12:55:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2011/01/05/1926771.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2011/01/05/1926771.html"/><content type="html">&lt;p&gt;在android里，有4种activity的启动模式，分别为：    &lt;br /&gt;“standard” (默认)     &lt;br /&gt;“singleTop”     &lt;br /&gt;“singleTask”     &lt;br /&gt;“singleInstance”&lt;/p&gt;  &lt;p&gt;它们主要有如下不同：&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1. 如何决定所属task&lt;/strong&gt;     &lt;br /&gt;“standard”和”singleTop”的activity的目标task，和收到的Intent的发送者在同一个task内，除非intent包括参数FLAG_ACTIVITY_NEW_TASK。     &lt;br /&gt;如果提供了FLAG_ACTIVITY_NEW_TASK参数，会启动到别的task里。     &lt;br /&gt;“singleTask”和”singleInstance”总是把activity作为一个task的根元素，他们不会被启动到一个其他task里。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. 是否允许多个实例&lt;/strong&gt;     &lt;br /&gt;“standard”和”singleTop”可以被实例化多次，并且存在于不同的task中，且一个task可以包括一个activity的多个实例；     &lt;br /&gt;“singleTask”和”singleInstance”则限制只生成一个实例，并且是task的根元素。     &lt;br /&gt;singleTop要求如果创建intent的时候栈顶已经有要创建 的Activity的实例，则将intent发送给该实例，而不发送给新的实例。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. 是否允许其它activity存在于本task内&lt;/strong&gt;     &lt;br /&gt;“singleInstance”独占一个task，其它activity不能存在那个task里；如果它启动了一个新的activity，不管新的activity的launch mode 如何，新的activity都将会到别的task里运行（如同加了FLAG_ACTIVITY_NEW_TASK参数）。     &lt;br /&gt;而另外三种模式，则可以和其它activity共存。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;4. 是否每次都生成新实例&lt;/strong&gt;     &lt;br /&gt;“standard”对于没一个启动Intent都会生成一个activity的新实例；     &lt;br /&gt;“singleTop”的activity如果在task的栈顶的话，则不生成新的该activity的实例，直接使用栈顶的实例，否则，生成该activity的实例。     &lt;br /&gt;比如现在task栈元素为A-B-C-D（D在栈顶），这时候给D发一个启动intent，如果D是 “standard”的，则生成D的一个新实例，栈变为A－B－C－D－D。     &lt;br /&gt;如果D是singleTop的话，则不会生产D的新实例，栈状态仍为A-B-C-D     &lt;br /&gt;如果这时候给B发Intent的话，不管B的launchmode是”standard” 还是 “singleTop” ，都会生成B的新实例，栈状态变为A-B-C-D-B。&lt;/p&gt;  &lt;p&gt;“singleInstance”是其所在栈的唯一activity，它会每次都被重用。&lt;/p&gt;  &lt;p&gt;“singleTask”如果在栈顶，则接受intent，否则，该intent会被丢弃，但是该task仍会回到前台。&lt;/p&gt;  &lt;p&gt;当已经存在的activity实例处理新的intent时候，会调用onNewIntent()方法    &lt;br /&gt;如果收到intent生成一个activity实例，那么用户可以通过back键回到上一个状态；如果是已经存在的一个activity来处理这个intent的话，用户不能通过按back键返回到这之前的状态。&lt;/p&gt;  &lt;p&gt;--------END-------&lt;/p&gt;  &lt;p&gt;原文链接：&lt;a title="http://liubin.nanshapo.com/2010/12/23/activity-launch-mode/" href="http://liubin.nanshapo.com/2010/12/23/activity-launch-mode/"&gt;http://liubin.nanshapo.com/2010/12/23/activity-launch-mode/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1926771.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2011/01/05/1926771.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/halzhang/archive/2010/12/05/1896791.html</id><title type="text">Android开发&amp;mdash;&amp;mdash;09Google I/O之让Android UI性能更高效(1)</title><summary type="text">一、前言 前几天发现09年Google IO大会关于移动应用方面的主题有一些不错的PPT，对移动应用开发很有帮助。自己看了一些，边看边和大家分享。既然是PPT就很简化了，我会根据实际情况写一些Demo供大家参考。 Android在UI优化方面可以从以下五个方面入手： Adapter优化 背景和图片优化 绘图优化 视图和布局优化 内存分配优化 二、Adapter优化 什么是Adapter，可以...</summary><published>2010-12-05T03:14:00Z</published><updated>2010-12-05T03:14:00Z</updated><author><name>HalZhang</name><uri>http://www.cnblogs.com/halzhang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/halzhang/archive/2010/12/05/1896791.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/halzhang/archive/2010/12/05/1896791.html"/><content type="html">&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/Windows-Live-Writer/374571620b9d_D566/googleio_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="googleio" border="0" alt="googleio" src="http://images.cnblogs.com/cnblogs_com/halzhang/Windows-Live-Writer/374571620b9d_D566/googleio_thumb.png" width="857" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;一、前言&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;前几天发现09年Google IO大会关于移动应用方面的主题有一些不错的PPT，对移动应用开发很有帮助。自己看了一些，边看边和大家分享。既然是PPT就很简化了，我会根据实际情况写一些Demo供大家参考。&lt;/p&gt;  &lt;p&gt;Android在UI优化方面可以从以下五个方面入手：&lt;/p&gt;  &lt;li&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Adapter优化&lt;/font&gt;&lt;/strong&gt; &lt;/li&gt;  &lt;li&gt;背景和图片优化 &lt;/li&gt;  &lt;li&gt;绘图优化 &lt;/li&gt;  &lt;li&gt;视图和布局优化 &lt;/li&gt;  &lt;li&gt;内存分配优化    &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;二、Adapter优化&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;什么是Adapter，可以先看看我的上一篇文章，&lt;a href="http://www.cnblogs.com/halzhang/archive/2010/11/28/1890637.html" target="_blank"&gt;Android开发——说说Adapter那点事&lt;/a&gt; Adapter与View的连接主要依靠getView这个方法返回我们需要的自定义view。ListView是Android app中一个最最最常用的控件了，所以如何让ListView流畅运行，获取良好的用户体验是非常重要的。对ListView优化就是对Adapter中的getView方法进行优化。09年的Google IO大会给出的优化建议如下：&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" size="2"&gt;&lt;strong&gt;Adapter优化示例代码：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;div&gt;     &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;       &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; @Override      &lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; View getView(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; position, View convertView, ViewGroup parent) {      &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     Log.d(&lt;span style="color: #006080"&gt;&amp;quot;MyAdapter&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Position:&amp;quot;&lt;/span&gt; + position + &lt;span style="color: #006080"&gt;&amp;quot;---&amp;quot;&lt;/span&gt;      &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;             + String.valueOf(System.currentTimeMillis()));      &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     ViewHolder holder;      &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (convertView == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {      &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         final LayoutInflater inflater = (LayoutInflater) mContext      &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);      &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         convertView = inflater.inflate(R.layout.list_item_icon_text, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);      &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         holder = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ViewHolder();      &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         holder.icon = (ImageView) convertView.findViewById(R.id.icon);      &lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         holder.text = (TextView) convertView.findViewById(R.id.text);      &lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         convertView.setTag(holder);      &lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     } &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; {      &lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         holder = (ViewHolder) convertView.getTag();      &lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     }      &lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     holder.icon.setImageResource(R.drawable.icon);      &lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     holder.text.setText(mData[position]);      &lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; convertView;      &lt;span style="color: #606060"&gt;  20:&lt;/span&gt; }      &lt;span style="color: #606060"&gt;  21:&lt;/span&gt;&amp;#160;       &lt;span style="color: #606060"&gt;  22:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ViewHolder {      &lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     ImageView icon;      &lt;span style="color: #606060"&gt;  24:&lt;/span&gt;&amp;#160;       &lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     TextView text;      &lt;span style="color: #606060"&gt;  26:&lt;/span&gt; }    &lt;/div&gt;  &lt;/div&gt;  &lt;div&gt;以上是Google io大会上给出的优化建议，经过尝试ListView确实流畅了许多。&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;    &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;      &lt;span style="color: #606060"&gt;   1:&lt;/span&gt; @Override      &lt;span style="color: #606060"&gt;   2:&lt;/span&gt;  &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; View getView(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; position, View convertView, ViewGroup parent) {      &lt;span style="color: #606060"&gt;   3:&lt;/span&gt;      Log.d(&lt;span style="color: #006080"&gt;&amp;quot;MyAdapter&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Position:&amp;quot;&lt;/span&gt; + position + &lt;span style="color: #006080"&gt;&amp;quot;---&amp;quot;&lt;/span&gt;      &lt;span style="color: #606060"&gt;   4:&lt;/span&gt;              + String.valueOf(System.currentTimeMillis()));      &lt;span style="color: #606060"&gt;   5:&lt;/span&gt;          final LayoutInflater inflater = (LayoutInflater) mContext      &lt;span style="color: #606060"&gt;   6:&lt;/span&gt;                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);      &lt;span style="color: #606060"&gt;   7:&lt;/span&gt;          View v = inflater.inflate(R.layout.list_item_icon_text, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);      &lt;span style="color: #606060"&gt;   8:&lt;/span&gt;          ((ImageView) v.findViewById(R.id.icon)).setImageResource(R.drawable.icon);      &lt;span style="color: #606060"&gt;   9:&lt;/span&gt;          ((TextView) v.findViewById(R.id.text)).setText(mData[position]);      &lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; v;      &lt;span style="color: #606060"&gt;  11:&lt;/span&gt;  }    &lt;/div&gt;  &lt;/div&gt;  &lt;div&gt;以上是不建议的做法！！&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;不过我们还是要怀疑一下，SO，我们还是来测试对比一下。&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;&lt;font color="#dfce04" size="3"&gt;&lt;strong&gt;测试说明：&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;  &lt;div&gt;大家可以看到在getView的时候我们通过log打印出position和当前系统时间。我们通过初始化1000条数据到Adapter显示到ListView，然后滚动到底部，计算出position=0和position=999时的时间间隔。&lt;/div&gt;  &lt;div&gt;测试机子：HTC Magic&lt;/div&gt;  &lt;div&gt;测试实录：打开测序，让ListView一直滚动底部。:-)&lt;/div&gt;&lt;/li&gt;&lt;li&gt;  &lt;div&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/halzhang/Windows-Live-Writer/374571620b9d_D566/device_2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="device" border="0" alt="device" src="http://images.cnblogs.com/cnblogs_com/halzhang/Windows-Live-Writer/374571620b9d_D566/device_thumb.png" width="324" height="484" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;&lt;font color="#dfce04" size="3"&gt;&lt;strong&gt;测试结果：&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;  &lt;p&gt;两种情况在操作过程中体验明显不同，在优化的情况下流畅很多很多！&lt;/p&gt;  &lt;p&gt;1、优化建议测试结果：&lt;/p&gt;  &lt;p&gt;12-05 10:44:46.039: DEBUG/MyAdapter(13929): Position:0---1291517086043     &lt;br /&gt;12-05 10:44:46.069: DEBUG/MyAdapter(13929): Position:1---1291517086072     &lt;br /&gt;12-05 10:44:46.079: DEBUG/MyAdapter(13929): Position:2---1291517086085&lt;/p&gt;  &lt;p&gt;……&lt;/p&gt;  &lt;p&gt;12-05 10:45:04.109: DEBUG/MyAdapter(13929): Position:997---1291517104112     &lt;br /&gt;12-05 10:45:04.129: DEBUG/MyAdapter(13929): Position:998---1291517104135     &lt;br /&gt;12-05 10:45:04.149: DEBUG/MyAdapter(13929): Position:999---1291517104154&lt;/p&gt;  &lt;p&gt;    &lt;br /&gt;&lt;strong&gt;&lt;font color="#0000ff" size="4"&gt;耗时：17967&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;2、没优化的测试结果&lt;/p&gt;  &lt;p&gt;12-05 10:51:42.569: DEBUG/MyAdapter(14131): Position:0---1291517502573     &lt;br /&gt;12-05 10:51:42.589: DEBUG/MyAdapter(14131): Position:1---1291517502590     &lt;br /&gt;12-05 10:51:42.609: DEBUG/MyAdapter(14131): Position:2---1291517502617&lt;/p&gt;  &lt;p&gt;……&lt;/p&gt;  &lt;p&gt;12-05 10:52:07.079: DEBUG/MyAdapter(14131): Position:998---1291517527082     &lt;br /&gt;12-05 10:52:07.099: DEBUG/MyAdapter(14131): Position:999---1291517527108     &lt;br /&gt;    &lt;br /&gt;&lt;font color="#ff0000" size="3"&gt;&lt;strong&gt;耗时：24535&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;在1000条记录的情况下就有如此差距，一旦数据nW+，ListView的Item布局更加复杂的时候，优化的作用就更加突出了！&lt;/p&gt;  &lt;p&gt;OK，欢迎大家交流学习，Gtalk：&lt;a href="mailto:ghanguo@gmail.com"&gt;ghanguo@gmail.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;转载请注明出处！&lt;/p&gt;  &lt;p&gt;示例代码： &lt;a href="http://files.cnblogs.com/halzhang/GoogleIO%e7%b3%bb%e5%88%97%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b(1).zip" target="_blank"&gt;GoogleIO示例代码&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;p&gt;---------EOF------------------&lt;/p&gt;&lt;img src="http://www.cnblogs.com/halzhang/aggbug/1896791.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/halzhang/archive/2010/12/05/1896791.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
