首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> Symbian >> 多媒体 >> 文章正文
如何调用S60的系统摄像头功能进行拍照与摄像
作者:AlwaysOn…    文章来源:http://blog.csdn.net/alwaysonline/archive/2006/09/26/1287665.aspx    更新时间:2006-9-30 9:51:39

nokia的论坛上提供了调用S60系统摄像头的示例代码,但在使用中我们发现,(1)需要指定系统摄像头appUID,因为不同型号的S60手机系统摄像头appUID可能不同,就需要开发者跟据不同手机的摄像头ID进行适配;(2)没有提供拍照后的文件信息,当完成拍照或录像后没法知道所对应的影像文件;(3)完成摄像后没有关闭摄像头,这样在某些手机上(如N70)无法第二次启动摄像头;针对存在的这三个问题,我们做了如下工作:

Ø        自动查找摄像头appUID

Ø        打开摄像头

Ø        查找完成操作后的相关影像文件;

Ø        关闭摄像头的系统调用;

 

一、自动查找摄像头appUID

 

    通过RApaLsSessionGetAllApps接口可以得到所有系统上应用程序的信息,包括UIDFull path nameCaption ,在其中一一比对系统摄像头所在的文件路径,找到其UID

 

具体代码见附录二中的CLaunchCamera::FindCamera

 

其中对KCameraAppString定义说明如下:

1KCameraAppString定义了系统摄像头在设备上的路径

模拟器及大部分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:查找文件选项,这里使用KEntryAttNormal

anEntrySortKey:查找结果的排序选项,这里使用ESortByDate|EDescending,即按时间进行降序排序

anEntryList:查找到的文件例表;

aDirList:查找到的文件目录例表;

 

具体查找代码见附录二中的CLaunchCamera::GetLastFileLaunchCamera::GetLastNewFile

 

四:关闭摄像头的系统调用
 

   在使用完摄像头后要调用CEikProcessDestroyDocument接口,删除对系统摄像头的调用,否则在有些手机上无法第二次调用摄像,但要注意的时DestroyDocument接口不能在回调通知函数NotifyExit中调用,否则程序会crash,我们的变通方法是CLaunchCamera的外部调用启动一下timer,在timer中轮询调用EnableCloseCamera来判断当前的摄像头是否可以关闭。

 

附录一:CLaunchCamera的类定义:

 

#include <e32std.h>
#include 
<apparc.h> //for MApaEmbeddedDocObserver
#include <eikproc.h> //for CEikProcess
//////////////////////////////////////////////////////////////////////

enum Camera_File_Type
{
        CFT_NoFind 
= 0x0,
        CFT_Image 
= 0x1 ,
        CFT_Video 
= 0x2 ,
}
;

typedef Camera_File_Type   enCameraFileType ;

class MCameraEvenCallBack
{
public:
    
virtual void Camera_HandleFile(enCameraFileType enFileType , const TDesC & aFilePath) = 0 ;
        
virtual void Camera_UpdateData(TBool bUpdate = TRUE ) = 0;
}
;

//////////////////////////////////////////////////////////////////////

class CApaDocument ;
class CEikonEnv ;

class CLaunchCamera  : public MApaEmbeddedDocObserver
{
public:
        CLaunchCamera();
        
virtual ~CLaunchCamera();

    
static CLaunchCamera * NewL(MCameraEvenCallBack * pEvenCallBack,CEikonEnv * pEikonEnv );
    
static CLaunchCamera * NewLC(MCameraEvenCallBack * pEvenCallBack,CEikonEnv * pEikonEnv);
        TBool OpenCamera() ;

        
//注意些接口不能在MCameraEvenCallBack的回调中调用,否则设备会crash
        void  CloseCamera() ;

        TBool EnableCloseCamera() ;

private:
        
void ConstructL(MCameraEvenCallBack * pEvenCallBack,CEikonEnv * pEikonEnv) ;
        
        
//From MApaEmbeddedDocObserver
        void  NotifyExit(TExitMode aMode) ;

        
void FindNewFile() ;

        TBool GetLastFile(TFileName 
& filePath , TTime & fileTime) ;
        TBool GetLastNewFile(TFileName 
& filePath , TTime & fileTime)  ;
        TBool FindCamera( TApaAppInfo 
& appInfo) ;

private:
        CEikonEnv    
*   m_pEikonEnv ;        
        MCameraEvenCallBack 
* m_pCallBack ;

        CApaDocument 
*        m_pAppdoc;
        CEikProcess 
* m_pProcess ;

        TBool  m_bCloseCamera ;

}
;

 附录二:CLaunchCamera类实现

#include <eikenv.h> //for CEikProcess

#include <eikproc.h> //for CEikProcess

#include <PathInfo.h> //for PathInfo

#include <apgcli.h>  //for RApaLsSession

#include <apacln.h>  // 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 FALSE

TBool 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 aMode

void 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                : void

 

void 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()) ;