改动步骤如下:
(Android版本:2.3, 文件路径:/frameworks/base/media/libmedia/MediaScannerClient.cpp)
1.MediaScannerClient类构造函数中本地编码初始值设为:kEncodingGBK
mLocaleEncoding(kEncodingGBK)
2.MediaScannerClient::endFile()函数中
加入下面的代码:
// add {
// if the possible encoding is judged as an only one, use it instead of default(GBK).
if(encoding == kEncodingShiftJIS || encoding == kEncodingGBK
|| encoding == kEncodingBig5 || encoding == kEncodingEUCKR) {
convertValues(encoding);
} else
// add end }
// if the locale encoding matches, then assume we have a native encoding.
if (encoding & mLocaleEncoding)
convertValues(mLocaleEncoding);
后面可以继续加入自己需要的逻辑,如把GBK的优先级设为高于ShiftJIS:
else if ((encoding & kEncodingGBK) > 0 && (encoding & kEncodingShiftJIS) > 0)
convertValues(kEncodingGBK);
这样就OK了。下面大概解释一下:
(路径:\frameworks\base\media\libstagefright\StagefrightMediaScanner.cpp)
StagefrightMediaScanner::processFile()是对扫描到的文件中的多媒体文件里的字串数据进行转换处理的过程:
1. client.setLocale(locale());
这个函数会根据手机设置的语言来设置mLocaleEncoding的值,mLocaleEncoding默认值是kEncodingNone,如果语言用户设置了英文,那么中文字串就会因为这个函数导致mLocaleEncoding的值没有变成kEncodingGBK,进而产生乱码。
2.从for循环中的client.addStringTag(kKeyMap.tag, value); 可以看到,只有mLocaleEncoding != kEncodingNone才会去对文件中读到的字串进行判断,然后如果不是ascii码才会压进client.beginFile();中创建的名值对(名:如"Aritist",值:如"李宗盛")的栈,否则直接调用handleStringTag()扔给Client,结束处理。这就是需要进行改动1的原因。
3.client.endFile();首先对栈里的所有的“值”字串的值进行区间判断,得到这些字串的可能编码,并取“与”,就是不断缩小可能编码范围:
encoding &= possibleEncodings(mValues->getEntry(i));
然后判断如果得到的可能编码范围中有mLocaleEncoding的,就以mLocaleEncoding为栈中所有“值”字串的编码进行转换:
if (encoding & mLocaleEncoding)
convertValues(mLocaleEncoding);
这对于有中文的字串没有问题,但如果是日文歌曲并且文件里面的字串是纯日文编码(ShiftJIS)的,那还是乱码,因为没有执行convertValues()进行转换。所以加入了改动2,也就是如果分析得到的可能编码只有一种,则选择这种编码。
对于其它的可能情况,比如字串的可能编码判断出不只一种,而且其中没有mLocaleEncoding的,没有进一步处理,所以逻辑上还是有一定漏洞的,大家可以自己根据需要修改。
--- frameworks/base/media/libmedia/MediaScannerClient.cpp 2011-06-09 14:48:27.000000000 +0800
+++ frameworks/base/media/libmedia/MediaScannerClient.cpp.new 2012-05-10 17:10:40.000000000 +0800
@@ -27,7 +27,7 @@
MediaScannerClient::MediaScannerClient()
: mNames(NULL),
mValues(NULL),
- mLocaleEncoding(kEncodingNone)
+ mLocaleEncoding(kEncodingGBK)
{
}
@@ -206,9 +206,16 @@
for (int i = 0; i < mNames->size(); i++)
encoding &= possibleEncodings(mValues->getEntry(i));
+ // if the possible encoding is judged as an only one, use it instead of default(GBK).
+ if(encoding == kEncodingShiftJIS || encoding == kEncodingGBK
+ || encoding == kEncodingBig5 || encoding == kEncodingEUCKR) {
+ convertValues(encoding);
+ } else
// if the locale encoding matches, then assume we have a native encoding.
if (encoding & mLocaleEncoding)
convertValues(mLocaleEncoding);
+ else if ((encoding & kEncodingGBK) > 0 && (encoding & kEncodingBig5) > 0)
+ convertValues(kEncodingGBK);
// finally, push all name/value pairs to the client
for (int i = 0; i < mNames->size(); i++) {
转自:http://www.eoeandroid.com/thread-95847-1-1.html