S60 3rd上的MTM框架提供了MMsvAttachmentManager(附件管理器)这个接口类管理各种不同消息的附件,它把操作各种附件的实现交给各MTM,使用者只需要简单通过附件管理器提供的方法就可以操作消息的附件。附件管理器基于CMsvAttachment管理各类型的附件,而CMsvAttachment是消息框架中提供的用来表现任何类型附件的对象,通过它不用实际加载或检索附件就可得到附件的许多属性。消息管理器支持下面几种不同类型的附件:
1. 文件附件:被拷贝或创建在消息存储(Message Store)中的文件。
2. 文件链接附件:附件是链接到磁盘中的文件,没有拷贝到消息存储(Message Store)中。
3. 消息条目(Entry):系统中的消息可以注册为别一个消息的附件。
下面的代码演示了如何通过MMsvAttachmentManager提取消息中的附件:
//Extract attachments to specified path
void CMsgEngine::ExtractAttachmentL( const TDesC &aNewPath, CDesCArray &aFileNameArray, TMsvId aEntryId )
{
aFileNameArray.Reset();
CMsvEntry* msvEntry = iSession->GetEntryL( aEntryId );
CleanupStack::PushL( msvEntry );
if( !msvEntry->HasStoreL() )
{
CleanupStack::PopAndDestroy( msvEntry );
return;
}
CMsvStore *store = msvEntry->ReadStoreL();
CleanupStack::PushL( store );
MMsvAttachmentManager& attachManager = store->AttachmentManagerL();
RFs fileSession;
User::LeaveIfError( fileSession.Connect() );
CleanupClosePushL( fileSession );
for( TInt i = 0; i < attachManager.AttachmentCount(); ++i )
{
CMsvAttachment *attachment = attachManager.GetAttachmentInfoL( i );
CleanupStack::PushL( attachment );
TPtrC8 mime = attachment->MimeType();
CMsvAttachment::TMsvAttachmentType type = attachment->Type();
if( type != CMsvAttachment::EMsvMessageEntry )
{
TFileName newPath( aNewPath );
newPath.Append( attachment->AttachmentName() );
aFileNameArray.AppendL( attachment->AttachmentName() );
RFile file = attachManager.GetAttachmentFileL( i );
TInt size(0);
file.Size( size );
HBufC8 *buf = HBufC8::NewLC( size );
TPtr8 ptrBuf( buf->Des() );
file.Read( ptrBuf, size );
RFile newFile;
User::LeaveIfError ( newFile.Replace( fileSession, newPath, EFileWrite ) );
newFile.Write( ptrBuf );
newFile.Close();
CleanupStack::PopAndDestroy( buf );
}
CleanupStack::PopAndDestroy( attachment );
}
CleanupStack::PopAndDestroy( 3, msvEntry );
}
有人可能会注意到CMsvAttachment已经提供了AttachmentName()和FilePath()方法来提供附件的名称与路径,那为什么不使用BaflUtils:: CopyFile()等API直接复制?测试一下就可以发现这些附件是存储在私有目录下的,其它程序没有AllFiles是不能访问的,所以需要使用MMsvAttachmentManagerr::GetAttachmentFileL()返回的RFile来读取文件数据,另外注意返回的RFile是以只读的形式打开文件,所以不能对附件进行修改。