如何调用S60的系统摄像头功能进行拍照与摄像?zz


所属类别:技术博客

文章作者:JianXiong

特别推荐:免费发布信息 承包关键词~~抢爆了!HOT!


在nokia的论坛上提供了调用S60系统摄像头的示例代码,但在使用中我们发现,(1)需要指定系统摄像头app的UID,因为不同型号的S60手机系统摄像头app的UID可能不同,就需要开发者跟据不同手机的摄像头ID进行适配;(2)没有提供拍照后的文件信息,当完成拍照或录像后没法知道所对应的影像文件;(3)完成摄像后没有关闭摄像头,这样在某些手机上(如N70)无法第二次启动摄像头;针对存在的这三个问题,我们做了如下工作:Ø 自动查找摄像头app的UID;Ø 打开摄像头Ø 查找完成操作后的相关影像文件;Ø 关闭摄像头的系统调用;一、自动查找摄像头app的UID 通过RApaLsSession的GetAllApps接口可以得到所有系统上应用程序的信息,包括UID,Full path name,Caption ,在其中一一比对系统摄像头所在的文件路径,找到其UID。具体代码见附录二中的CLaunchCamera::FindCamera其中对KCameraAppString定义说明如下:1、KCameraAppString定义了系统摄像头在设备上的路径模拟器及大部分S60手机上定义如下(测试通过了6681,7610):_LIT(KCameraAppString , "z:\\system\\apps\\camcorder\\camcorder.app") ;但N70手机上,要定义如下:_LIT(KCameraAppString , "z:\\system\\apps\\cammojave\\cammojave.app") ;2、如果FindCamera返回TURE,则找到系统摄像头二、打开摄像头通过系统调用,打开设备的摄像头,具体的代码见附录二中的CLaunchCamera::OpenCamera() :三、查找完成操作后的相关影像文件 当用户完成摄像功能后,会通过MApaEmbeddedDocObserver类的回调函数NotifyExit进行通知,改函数具体定义如下: void NotifyExit(TExitMode aMode)其中:enum TExitMode { EKeepChanges, ERevertToSaved, ENoChanges, EEmpty };EKeepChanges表示用户进行了拍照或摄像操作,ENoChanges表示用户取消了拍照或摄像操作,其它两个不用处理。在这个唯一可以知道用户进行了操作的通知函数中,没有所拍照的图像文件路径信息,因此我们只有通过遍例设备上的图像文件来找到最新的拍照文件。遍例包括对设备存储分区和存储卡分区(即C盘与E盘),PathInfo类提供了对这两个分区的图像文件与影像文件的访问路径,分别是: TFileName PhoneIamgePath ; TFileName PhoneVideoPath ; TFileName MemoryIamgePath ; TFileName MemoryVideoPath ; PhoneIamgePath.Append(PathInfo::PhoneMemoryRootPath()) ; PhoneIamgePath.Append(PathInfo::ImagesPath()); PhoneVideoPath.Append(PathInfo::PhoneMemoryRootPath()) ; PhoneVideoPath.Append(PathInfo::VideosPath()) ; MemoryIamgePath.Append(PathInfo::MemoryCardRootPath()) ; MemoryIamgePath.Append(PathInfo::ImagesPath()) ; MemoryVideoPath.Append(PathInfo::MemoryCardRootPath()) ; MemoryVideoPath.Append(PathInfo::VideosPath()) ;同时还要注意有些手机可能会对拍的图片上边的文件夹中再进行分类存储,所以查找的时候查找到以上目录的二级子目录就可以满足要求。查找使用RFs类的GetDir接口,具体定义如下:TInt GetDir(const TDesC& aName,TUint anEntryAttMask,TUint anEntrySortKey,CDir*& anEntryList) const;TInt GetDir(const TDesC& aName,TUint anEntryAttMask,TUint anEntrySortKey,CDir*& anEntryList,CDir*& aDirList) const;其中:aName:文件夹的完整路径anEntryAttMask:查找文件选项,这里使用KEntryAttNormalanEntrySortKey:查找结果的排序选项,这里使用ESortByDateEDescending,即按时间进行降序排序anEntryList:查找到的文件例表;aDirList:查找到的文件目录例表;具体查找代码见附录二中的CLaunchCamera::GetLastFile与LaunchCamera::GetLastNewFile四:关闭摄像头的系统调用 在使用完摄像头后要调用CEikProcess的DestroyDocument接口,删除对系统摄像头的调用,否则在有些手机上无法第二次调用摄像,但要注意的时DestroyDocument接口不能在回调通知函数NotifyExit中调用,否则程序会crash,我们的变通方法是CLaunchCamera的外部调用启动一下timer,在timer中轮询调用EnableCloseCamera来判断当前的摄像头是否可以关闭。附录一:CLaunchCamera的类定义:#include#include//forMApaEmbeddedDocObserver#include//forCEikProcess/**///////////////////////////////////////////////////////////////////////enumCamera_File_Type...{CFT_NoFind=0x0,CFT_Image=0x1,CFT_Video=0x2,};typedefCamera_File_TypeenCameraFileType;classMCameraEvenCallBack...{public:virtualvoidCamera_HandleFile(enCameraFileTypeenFileType,constTDesC&aFilePath)=0;virtualvoidCamera_UpdateData(TBoolbUpdate=TRUE)=0;};/**///////////////////////////////////////////////////////////////////////classCApaDocument;classCEikonEnv;classCLaunchCamera:publicMApaEmbeddedDocObserver...{public:CLaunchCamera();virtual~CLaunchCamera();staticCLaunchCamera*NewL(MCameraEvenCallBack*pEvenCallBack,CEikonEnv*pEikonEnv);staticCLaunchCamera*NewLC(MCameraEvenCallBack*pEvenCallBack,CEikonEnv*pEikonEnv);TBoolOpenCamera();//注意些接口不能在MCameraEvenCallBack的回调中调用,否则设备会crashvoidCloseCamera();TBoolEnableCloseCamera();private:voidConstructL(MCameraEvenCallBack*pEvenCallBack,CEikonEnv*pEikonEnv);//FromMApaEmbeddedDocObservervoidNotifyExit(TExitModeaMode);voidFindNewFile();TBoolGetLastFile(TFileName&filePath,TTime&fileTime);TBoolGetLastNewFile(TFileName&filePath,TTime&fileTime);TBoolFindCamera(TApaAppInfo&appInfo);private:CEikonEnv*m_pEikonEnv;MCameraEvenCallBack*m_pCallBack;CApaDocument*m_pAppdoc;CEikProcess*m_pProcess;TBoolm_bCloseCamera;};附录二:CLaunchCamera类实现 #include //for CEikProcess#include //for CEikProcess#include //for PathInfo#include //for RApaLsSession#include // for TApaDocCleanupItem#include "LaunchCamera.h"CLaunchCamera* CLaunchCamera::NewL(MCameraEvenCallBack * pEvenCallBack,CEikonEnv * pEikonEnv ){ CLaunchCamera* self = NewLC(pEvenCallBack ,pEikonEnv); CleanupStack::Pop(self); return self;}CLaunchCamera* CLaunchCamera::NewLC(MCameraEvenCallBack * pEvenCallBack,CEikonEnv * pEikonEnv ){ CLaunchCamera* self = new (ELeave) CLaunchCamera; CleanupStack::PushL(self); self->ConstructL(pEvenCallBack,pEikonEnv); return self;}void CLaunchCamera::ConstructL(MCameraEvenCallBack * pEvenCallBack , CEikonEnv * pEikonEnv){ m_pProcess = NULL ; m_pAppdoc = NULL ; m_pCallBack = pEvenCallBack ; m_pEikonEnv = pEikonEnv ; m_bCloseCamera = FALSE ;}CLaunchCamera::CLaunchCamera(){ m_pAppdoc = NULL ;}CLaunchCamera::~CLaunchCamera(){ //CloseCamera() ; m_pEikonEnv = NULL ; m_pCallBack = NULL ;}// Function name : CLaunchCamera::OpenCamera// Description : Open camera and review// Return type : TURE if successful, otherwise FALSETBool CLaunchCamera::OpenCamera(){ if( m_pEikonEnv == NULL ) return FALSE ; TApaAppInfo appInfo; if( FindCamera( appInfo) == FALSE ) return FALSE ; m_pProcess = m_pEikonEnv->Process(); m_pAppdoc = m_pProcess->AddNewDocumentL(appInfo.iFullName, appInfo.iUid); ASSERT( m_pAppdoc != NULL ) ; TApaDocCleanupItem cleanup(m_pProcess, m_pAppdoc); CleanupStack::PushL(cleanup); m_pAppdoc->NewDocumentL(); CleanupStack::Pop(); // cleanup m_bCloseCamera = FALSE ; m_pAppdoc->EditL(this, EFalse ); return TRUE ;}void CLaunchCamera::CloseCamera(){ if( m_pProcess ) { m_pProcess->DestroyDocument(m_pAppdoc) ; m_pProcess = NULL ; m_pAppdoc = NULL ; } m_bCloseCamera = TRUE ;}TBool CLaunchCamera::FindCamera(TApaAppInfo & appInfo){ RApaLsSession apaTmpLs; User::LeaveIfError(apaTmpLs.Connect()); CleanupClosePushL(apaTmpLs); User::LeaveIfError(apaTmpLs.GetAllApps()); TBool bFindCamera = FALSE ; appInfo.iFullName.FillZ(appInfo.iFullName.MaxLength()) ; appInfo.iFullName.Zero() ; while(apaTmpLs.GetNextApp(appInfo) == KErrNone) { appInfo.iFullName.LowerCase() ; TInt nTmpID = appInfo.iFullName.Compare(KCameraAppString) ; if( nTmpID == 0 ) { bFindCamera = TRUE ; break ; } appInfo.iFullName.FillZ(appInfo.iFullName.MaxLength()) ; appInfo.iFullName.Zero() ; } CleanupStack::PopAndDestroy(); // apaTmpLs return bFindCamera ;}// Function name : CLaunchCamera::NotifyExit// Description : when selected "select", frame will call this function// Return type : void// Argument : TExitMode aModevoid CLaunchCamera::NotifyExit(TExitMode aMode){ if( aMode == EKeepChanges ) { //不能在这里调,否则设备为crash //m_pProcess->DestroyDocument(m_pAppdoc) ; FindNewFile() ; } else { //m_pProcess->DestroyDocument(m_pAppdoc) ; if( m_pCallBack ) m_pCallBack->Camera_HandleFile(CFT_NoFind, _L("FileNotSelect")); } m_bCloseCamera = TRUE ;}TBool CLaunchCamera::EnableCloseCamera(){ return m_bCloseCamera ;}// Function name : CLaunchCamera::FindNewFile// Description : Search the last new files//if find the last new file, call Camera_HandleFile to caller// Return type : voidvoid CLaunchCamera::FindNewFile(){ if( m_pCallBack == NULL ) return ; TFileName PhoneIamgePath ; TFileName MemoryIamgePath ; TFileName PhoneVideoPath ; TFileName MemoryVideoPath ; PhoneIamgePath.Append(PathInfo::PhoneMemoryRootPath()) ; PhoneIamgePath.Append(PathInfo::ImagesPath()); MemoryIamgePath.Append(PathInfo::MemoryCardRootPath()) ; MemoryIamgePath.Append(PathInfo::ImagesPath()) ; PhoneVideoPath.Append(PathInfo::PhoneMemoryRootPath()) ; PhoneVideoPath.Append(PathInfo::VideosPath()) ; MemoryVideoPath.Append(PathInfo::MemoryCardRootPath()) ; MemoryVideoPath.Append(PathInfo::VideosPath()) ; TTime tFileTime(0) ; TTime tLastFileTime(0) ; TInt nIndex = -1 ; //查找最新时间的文件 //find phone card image if( GetLastFile(PhoneIamgePath , tFileTime) == TRUE ) { if( tFileTime > tLastFileTime ) { tLastFileTime = tFileTime ; nIndex = 0 ; } } //find memory card image if( GetLastFile(MemoryIamgePath , tFileTime) == TRUE ) { if( tFileTime > tLastFileTime ) { tLastFileTime = tFileTime ; nIndex = 1 ; } } //find phone memory video file if( GetLastFile(PhoneVideoPath , tFileTime) == TRUE ) { if( tFileTime > tLastFileTime ) { tLastFileTime = tFileTime ; nIndex = 2 ; } } //find memory card video files if( GetLastFile(MemoryVideoPath , tFileTime) == TRUE ) { if( tFileTime > tLastFileTime ) { tLastFileTime = tFileTime ; nIndex = 3 ; } } //判断是那个目录下的文件 switch(nIndex) { case 0: m_pCallBack->Camera_HandleFile(CFT_Image , PhoneIamgePath) ; break; case 1: m_pCallBack->Camera_HandleFile(CFT_Image , MemoryIamgePath) ; break; case 2: m_pCallBack->Camera_HandleFile(CFT_Video , PhoneVideoPath) ; break; case 3: m_pCallBack->Camera_HandleFile(CFT_Video , MemoryVideoPath) ; break; default: m_pCallBack->Camera_HandleFile(CFT_NoFind , TFileName(0) ) ; break; }}////////////////////////////////////////////////////////////////////////////查找最新的图像文件,只查找到二级目录//////////////////////////////////////////////////////////////////////////////TBool CLaunchCamera::GetLastFile(TFileName & filePath , TTime & fileTime){ RFs sessionRFs; User::LeaveIfError(sessionRFs.Connect()); CDir* FileList; CDir* dirList ; //读出文件夹下文件信息,并对所有的文件进行降序排列 TInt nError = sessionRFs.GetDir(filePath,KEntryAttNormal, ESortByDateEDescending , FileList , dirList); if( nError != KErrNone ) { //ASSERT(FALSE) ; sessionRFs.Close() ; return FALSE; } else if( nError == KErrNone ) { TFileName tmpFileName(0) ; TTime tmpTime(0) ; TTime tLastFileTime(0) ; TFileName tLastFile(0) ; //file if( FileList->Count() > 0 ) { tmpFileName.FillZ(KMaxFileName) ; tmpFileName.Zero() ; tmpFileName.Append(filePath) ; tmpFileName.Append((*FileList)[0].iName) ; //get file modification time sessionRFs.Modified(tmpFileName , tmpTime ) ; if( tmpTime > tLastFileTime ) { tLastFileTime = tmpTime ; tLastFile.FillZ(KMaxFileName) ; tLastFile.Zero() ; tLastFile.Append(tmpFileName) ; } } delete FileList ; //dir TInt nDirCount = dirList->Count() ; for( int i = 0 ; i< nDirCount ; i++ ) { tmpFileName.FillZ(KMaxFileName) ; tmpFileName.Zero() ; tmpFileName.Append(filePath) ; tmpFileName.Append((*dirList)[i].iName) ; tmpFileName.Append(_L("\\")) ; if( GetLastNewFile( tmpFileName , tmpTime ) == TRUE ) { if( tmpTime > tLastFileTime ) { tLastFileTime = tmpTime ; tLastFile.FillZ(KMaxFileName) ; tLastFile.Zero() ; tLastFile.Append(tmpFileName) ; } } } delete dirList; //是否找到新的文件 if( tLastFileTime > TTime(0) ) { filePath.FillZ(KMaxFileName) ; filePath.Zero() ; filePath.Append(tLastFile) ; fileTime = tLastFileTime ; } else { sessionRFs.Close() ; return FALSE ; } } sessionRFs.Close() ; return TRUE ;}//用KEntryAttNormal只查找目录中的文件TBool CLaunchCamera::GetLastNewFile(TFileName & filePath , TTime & fileTime){ RFs sessionRFs; User::LeaveIfError(sessionRFs.Connect()); CDir* dirList; //读出文件夹下文件信息,并对所有的文件进行降序排列 TInt nError = sessionRFs.GetDir(filePath,KEntryAttNormal, ESortByDateEDescending,dirList); if( nError != KErrNone ) { sessionRFs.Close() ; return FALSE; } else if( dirList->Count() > 0 ) { //get filename filePath.Append((*dirList)[0].iName) ; //get file modification time sessionRFs.Modified(filePath , fileTime ) ; delete dirList; } else { sessionRFs.Close() ; return FALSE; } sessionRFs.Close() ; return TRUE ;}发表于 @ 2006年09月27日 22:26:00评论(loading...AddFeedbackCountStack("1297356"))编辑新一篇:symbian编程的几点注意(未完)旧一篇:symbian中如何检测编辑框的当前输入法类型zz

相关信息

· 在 asp 中结合Scripts脚本

· 将已有的分区挂装到Linux系统的主目录下

·  SNAT和DNAT的区别(☆)

· SQL2008使用LINQ进行数据访问








....

73732 11146