您的位置:首页 > 其它

MediaScanner扫描自定义文件说明文档

2012-03-05 12:03 411 查看
Pvr改造使用MediaScanner扫描说明文档

主要修改点以及说明如下:
1.MediaFile增加一个PVR(自定义)文件类型
publicstatic final int FILE_TYPE_PVR = 51;

private static final intFIRST_PVR_FILE_TYPE = FILE_TYPE_PVR;

privatestatic final int LAST_PVR_FILE_TYPE = FILE_TYPE_PVR;
FIRST和LAST是在用来判断一个文件是否属于PVR类型时用到

//这个方法是用来判断一个文件是否属于PVR类型
publicstatic boolean isPVRFileType(int fileType) {

return(fileType >= FIRST_PVR_FILE_TYPE &&

fileType <=LAST_PVR_FILE_TYPE);

}

添加
addFileType("PVR",FILE_TYPE_PVR,"PVR/PVR");
这行是将文件扩展名,文件typeid和MIME_TYPE关联,存入sFileTypeMap,sMimeTypeMap中

2MediaScanner.java

privatestatic final String[] PVR_PROJECTION = new String[] {

"_id",// 0

"_data",// 1

"date_modified",// 2

};

privatestatic final int ID_PVR_COLUMN_INDEX = 0;

privatestatic final int PATH_PVR_COLUMN_INDEX = 1;

privatestatic final int DATE_MODIFIED_PVR_COLUMN_INDEX = 2;

这块是在建立文件缓存的时候读取的数据库字段。

privateString device;
这个是代表文件存储的设备。
device= null; //清理缓存的时候置为Null

在handleStringTag里增加一个if判断
}else if (name.equalsIgnoreCase("filepath")) {

Stringfilepath = value.trim();

int index =filepath.lastIndexOf("/");

mTitle =filepath.substring(index+1,filepath.len

int fIndex =filepath.indexOf("/",1);

int sIndex =filepath.indexOf("/",fIndex+1);

device =filepath.substring(0,sIndex+1);

}
这个方法是底层读到文件的相关属性时的回调方法。filepath是我在底层返回的属性,可以自己定义需要返回的属性。方法内做了一个简单的字符串处理
取出文件路径的前2个单词。

在toValues方法里增加一个
elseif (MediaFile.isPVRFileType(mFileType)) {
map.put("device",device);
}
这个方法是把要存储的属性放到一个ContentValues里

在endFile中添加
如下代码:
booleanisPVR = MediaFile.isPVRFileType(mFileType);

elseif (isPVR) {
tableUri= Uri.parse("content://media/external/PVR");

这个方法是文件扫描完成后往数据库中添加的的过程。。先判断文件类型是否是PVR,
是的话给出对应的uri.

在prescan中添加如下代码:
c= mMediaProvider.query(Uri.parse("content://media/external/PVR"),PVR_PROJECTION, null, null, null);

if(c != null) {
try{
mOriginalCount =c.getCount();
while(c.moveToNext()) {
longrowId = c.getLong(ID_PVR_COLUMN_INDEX);
String path =c.getString(PATH_PVR_COLUMN_INDEX);
longlastModified = c.getLong(DATE_MODIFIED_PVR_COLUMN_INDEX);

//Only consider entries with absolute path names.
//This allows storing URIs in the database without the
//media scanner removing them.
if(path.startsWith("/")) {
String key = path;
if(mCaseInsensitivePaths) {
key =path.toLowerCase();
}
mFileCache.put(key, newFileCacheEntry(Uri.parse("content://media/external/PVR"),rowId, path,
lastModified));
}
}
}finally {
c.close();
c= null;
}
}

这个方法是做一些扫描前的准备工作,主要是把数据库中相应的记录做一个缓存。扫描完成后与缓存做对比,然后进行数据库的更新操作。这里是从数据库的PVR表中取出现有的记录列表。

3在StagefrightMediaScanner.cpp里添加PVR文件类型
".mkv",".mka", ".webm" ,".pvr"
最终负责处理单个文件的是这个文件。。所以需要增加文件类型到这里。
staticstatus_t HandlePVR(const char *path,MediaScannerClient *client){
LOGE("enterhandlePVR");
if(!client->addStringTag("filepath",path)){
LOGE("add String Tag failed");

}
returnOK;
}

增加一个处理PVR文件的方法,里面简单的回调了上层的方法。

在processFile里增加一个PVR的判断
if(!strcasecmp(extension,".PVR")) {
returnHandlePVR(path,&client);
}

4 MediaProvider相关的改动
在mediaProvider的updateDatabase方法中增加建立PVR表的代码

db.execSQL("CREATETABLE IF NOT EXISTS PVR ("
+
"_idINTEGER PRIMARY KEY," +
"titleTEXT," +
"deviceTEXT," +
"mime_typeTEXT," +
"date_modified INTEGER,"+
"_dataTEXT," +
"_sizeINTEGER" +
");");

在quey方法中增加一个case
casePVR:
qb.setTables("PVR");
break;
在inertInternal方法中增加一个case:
casePVR:{
rowId =db.insert("PVR","device",initialValues);
if(rowId > 0) {
newUri =ContentUris.withAppendedId(uri, rowId);
}
break;
}
这个是最终负责将底层传上来的ContentValues插入到数据库中的方法
在getTableAndWhere方法中增加一个case;
casePVR_ID:
out.table=
"PVR";
where =
"_id="+ uri.getPathSegments().get(2);
break;
这里主要是底层调用Provider删除方法时,通过这个方法给出表名和删除条件

在mediaProvider中定义2个Match值
privatestaticfinalintPVR=
700;
privatestaticfinalintPVR_ID=
701;

然后添加UriMatch
URI_MATCHER.addURI("media","*/PVR",PVR);
URI_MATCHER.addURI("media","*/PVR/#",PVR_ID);

以上就是在pvr改造中所涉及的修改之处。

注意:测试时直接在路径下touch**.PVR,是搜不到的,可能是size为0的文件搜不到,可以将其他格式文件改为.PVR的文件可以搜到

2.扫描文件内容

以上是如何根据文件扩展名扫描文件,pvr在改造时还添加了扫描文件内容的功能,在录制完成时在Pvr的系统服务中会将当前录制完成的节目信息(包括节目名称,录制时间,时长,音量,等)写入一个pvrInfor.pvr文件中.同时发送扫描广播,让系统MediaScanner扫描系统文件,将pvrInfor.pvr中存储的信息扫描出来存入数据库pvr中,同时扫描出当前录制的节目流文件,信息存在数据ts中。具体实现如下:

(1)创建pvr文件
framework/base/dvb/java/cn/ccdt/pvr/PvrRecordService的stopRecord中调用stPvrFileInfo的createFile()
/**
*
将文件写入pvrInfor.xpp
*/
publicvoidcreateFile(){
Log.v("stPvrFIleInfo","###@@@####start
create xpp file!!! path="+path);
//检查路径
Filefile =
newFile(path);
if(!file.exists()){
file.mkdir();
}
//创建文件
FilefileDoc =
newFile(path,"pvrInfor.pvr");
try{
fileDoc.createNewFile();
//写文件
File fileWrite =
newFile(fileDoc.getAbsolutePath());
if(fileWrite.exists()){
FileOutputStream fos =
newFileOutputStream(fileWrite);
OutputStreamWriter os =
newOutputStreamWriter(fos,
"utf-8");
BufferedWriter bw =
newBufferedWriter(os);
//bw.write(serviceIdent + "\n");
bw.write(newString(name.getBytes("utf-8"),"GBK")+
"\n");
bw.write(path+
"\n");
bw.write(storageDevicePath+
"\n");
bw.write(beginTime+
"\n");
bw.write(totalTime+
"\n");
bw.write(lastPlayTime+
"\n");
bw.write(volume+
"\n");
bw.write(recordType+
"\n");
bw.flush();//写入
Log.v("stPvrFIleInfo","###@@@####
create xpp file ok !!! ");
}
}catch(IOException e) {
e.printStackTrace();
}

}

(2)扫描文件:

1>framework/base/media/java/android/media/MediaScanner.java中
prescan()从数据库中查询文件状态缓存

2>扫描文件内容:
framework/base/media/libstagefright/StagefrightMediaScanner.cpp中

添加函数:
staticstatus_t
HandlePvr(constchar
*path,MediaScannerClient *client){
LOGE("@@@@enter HandlePvr %s",path);

/*读取文件*/
FILE *pFile = fopen(path,"rb");

long lSize;

char * buffer;

size_t result;

if (pFile == NULL){

LOGE("HandlePvr @@@@@@ !pFile fopen faild! path=%s",path);

return UNKNOWN_ERROR;

}

/*获取文件大小*/

fseek (pFile , 0 ,SEEK_END);

lSize = ftell (pFile);

rewind (pFile);

staticconst char *allColumnName[] = {

"name", "path", "device", "begin_time","total_time",
"lastplay_ime", "volumn", "record_type"

};

charbuffer_line[512];

inti = 0;

for(;i< 8 ; i++){

fgets(buffer_line,512,pFile);
/*上发扫描值*/
if(!client->addStringTag(allColumnName[i],buffer_line)){

LOGE("add String Tag failed");

}
}
fclose(pFile);
returnOK;

}

3> framework/base/media/java/android/media/MediaScanner.java中
endFile();提供uri将数据插入数据库

提供插入和查询Mediascanner扫描到的数据:
framework/base/package/providers/MediaProvider/src/com/android/provider/media/MediaProvider.java

在query方法中添加我们自定义文件格式的case:
casePVR:
Log.w(TAG,">>>>>>>>>>>>>>>>>>>MediaProvierYOU
QUERY PVR qb "+qb);
qb.setTables("pvr");
break;
casePVR_ID:
Log.w(TAG,">>>>>>>>>>>>>>>>>>>MediaProvierYOU
QUERY PVR_ID index= "+uri.getLastPathSegment());
qb.setTables("pvr");
qb.appendWhere("_id="+ uri.getLastPathSegment());
break;
caseTS:

Log.w(TAG,">>>>>>>>>>>>>>>>>>>MediaProvierYOU
QUERY ts qb "+qb);
qb.setTables("ts");
break;
caseTS_ID:
Log.w(TAG,">>>>>>>>>>>>>>>>>>>MediaProvierYOU
QUERY TS_ID index= "+uri.getLastPathSegment());
qb.setTables("ts");
qb.appendWhere("_id="+ uri.getLastPathSegment());
break;

在insertInternal中添加插入代码
casePVR:
Log.d(TAG,">>>>>>>>insertpvr
data");
rowId = db.insert("pvr","device",initialValues);
if(rowId > 0) {
newUri =ContentUris.withAppendedId(uri, rowId);
}
break;
caseTS:

Log.d(TAG,">>>>>>>>insertts
data");
rowId = db.insert("ts","device",initialValues);
if(rowId > 0) {
newUri =ContentUris.withAppendedId(uri, rowId);
}
break;

以上操作中只对.pvr文件进行了文件内容扫描,ts文件只是记录一些通用信息。

注意:修改了.cpp文件要重新编译so文件替换nfs中的so。这里我们修改了StagefrightMediaScanner.cpp在编译framework.jar的时候会一同编译出一个libstagefright.so文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: