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

晨曦之光 发布于 2012/03/05 15:34
阅读 641
收藏 0

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;

FIRSTLAST是在用来判断一个文件是否属于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");

这行是将文件扩展名,文件typeidMIME_TYPE关联,存入sFileTypeMapsMimeTypeMap


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表中取出现有的记录列表。


3StagefrightMediaScanner.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相关的改动

mediaProviderupdateDatabase方法中增加建立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中定义2Match

privatestaticfinalintPVR= 700;

privatestaticfinalintPVR_ID= 701;

然后添加UriMatch

URI_MATCHER.addURI("media","*/PVR",PVR);

URI_MATCHER.addURI("media","*/PVR/#",PVR_ID);


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


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



2.扫描文件内容


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


1)创建pvr文件

framework/base/dvb/java/cn/ccdt/pvr/PvrRecordServicestopRecord中调用stPvrFileInfocreateFile()

/**

* 将文件写入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.javaprescan()从数据库中查询文件状态缓存


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.javaendFile();提供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文件。



原文链接:http://blog.csdn.net/jinliang_890905/article/details/7320239
加载中
返回顶部
顶部