quick_recipes (779892), страница 19
Текст из файла (страница 19)
It alsomeans that your file will be getting bigger. It is recommended thatfrom time to time you compact the store file by calling CPermanentFileStore::CompactL(). This method will defragment your filestore.The following code shows the method to read all the employees to anarray:void CFileStoreAppUi::ReadEmployeesWithMultiStreamsL(RFs& aFs,const TDesC& aFileName,RPointerArray<CEmployee>& aArray){// Open the new file store.CFileStore* store = CDirectFileStore::OpenLC(aFs,aFileName, EFileWrite);// Read stream dictionaryCStreamDictionary* dictionary = CStreamDictionary::NewLC();RStoreReadStream dictionaryStream;dictionaryStream.OpenLC(*store, store->Root());dictionaryStream >> *dictionary;CleanupStack::PopAndDestroy(&dictionaryStream);// Get the identifier of each stream in this store.TStreamId headerId = dictionary->At(KHeaderUid);TStreamId employeesId = dictionary->At(KEmployeesUid);CleanupStack::PopAndDestroy(dictionary);// Read header information.RStoreReadStream headerStream;headerStream.OpenLC(*store, headerId);104SYMBIAN C++ RECIPESHBufC* signature = HBufC::NewLC(headerStream, KMaxBuffer);// If needed, check the signature here.CleanupStack::PopAndDestroy(signature);TUint32 version;headerStream >> version;TUint32 numberOfEmployees;headerStream >> numberOfEmployees;CleanupStack::PopAndDestroy(&headerStream);// Read the employees streams.RStoreReadStream employeeStream;employeeStream.OpenLC(*store, employeesId);for (TUint32 i = 0; i < numberOfEmployees; i++){CEmployee* employee = new(ELeave) CEmployee();CleanupStack::PushL(employee);employeeStream >> *employee;aArray.Append(employee); // ownership is transferredCleanupStack::Pop(employee);}CleanupStack::PopAndDestroy(&employeeStream);// Commit the change to the store and close the store.CleanupStack::PopAndDestroy(store);}4.1.3.2Share Files between ProcessesAmount of time required: 20 minutesLocation of example code: \Files\FileSharingCreator and\Files\FileSharingClientRequired library(s): efsrv.libRequired header file(s): f32file.hRequired platform security capability(s): NoneProblem: You want to share files with another process without giving thatprocess AllFiles capability.
For example, you have a file stored in theprivate folder that needs to be read by another process.Solution: As explained in Chapter 3, a data-caging mechanism preventsa process from accessing files stored in the private folder of anotherprocess. There is actually a way of sharing files between processes. A filehandle can be passed from one process to another process. Furthermore,a file handle can be passed from a client to a server or vice versa.The following RFile member methods support file handles sharingbetween processes:• RFile::TransferToClient(),• RFile::AdoptFromClient(),FILE HANDLING105• RFile::TransferToServer(),• RFile::AdoptFromServer(),• RFile::TransferToProcess(),• RFile::AdoptFromCreator().The TranferToXyz() methods are used to transfer the file handleto another process, which includes another server or client.
The AdoptFromXyz() methods are used to read the file handle that is shared byanother process.The following example shows how to transfer a file handle, filesharing.txt, from a process to another process:// CONSTANTS_LIT(KDataFileName,"filesharing.txt");_LIT(KClientFileName, "FileSharingClient.exe");const TInt KFileServerSlot = 1;const TInt KFileHandleSlot = 2;void CFileSharingCreatorAppUi::DoTransferFileL(){// Connect to the file server session and share it.RFs fs;User::LeaveIfError(fs.Connect());CleanupClosePushL(fs);User::LeaveIfError(fs.ShareProtected());// Get the file name that is located in the private folder.TFileName privatePath;User::LeaveIfError(fs.PrivatePath(privatePath));TParsePtrC parseAppPath(Application()->AppFullName());TParse parse;User::LeaveIfError(parse.Set(parseAppPath.Drive(), &privatePath,&KDataFileName));// Open the file to be shared.RFile file;User::LeaveIfError(file.Open(fs, parse.FullName(), EFileRead));CleanupClosePushL(file);// Create the process that will use the file.RProcess process;User::LeaveIfError(process.Create(KClientFileName, KNullDesC));CleanupClosePushL(process);// Transfer to process storing the RFs handle into// environment slot KFileServerSlot and// the RFile handle into slot KFileHandleSlot.User::LeaveIfError(file.TransferToProcess(process, KFileServerSlot, KFileHandleSlot));// Resume the process, which means start it.process.Resume();106SYMBIAN C++ RECIPES// Cleanup the resources.CleanupStack::PopAndDestroy(3, &fs); // close p, file, and fs}Discussion: The second and third parameters of TransferToProcessare indexes in the TIpcArgs/RMessage2 couple used for Inter-ProcessCommunication.
See Chapter 5 for more information on the subject. Notethat you cannot use slot 0, since this is reserved.The following code shows how we can adopt the shared file handle inthe FileSharingClient.exe process:GLDEF_C TInt E32Main(){// Adopt the file using the RFs handle into// environment slot KFileServerSlot// and the RFile handle into slot KFileHandleSlotRFile file;TInt err = file.AdoptFromCreator(KFileServerSlot, KFileHandleSlot);// If there is no error, read the file.if (KErrNone == err){TBuf8<KMaxBuffer> buffer;file.Read(buffer);// Use the buffer here.}return EikStart::RunApplication(NewApplication);}The code above adopts the file handle from the creator.
It will thenread the entire contents of the file to a buffer.4.1.4 Resources• Symbian Developer Library:◦ Symbian OS Guide > Base > File Services (F32) > File serverclient side.◦ Symbian OS Guide > System Libraries > Using Store.• Harrison and Shackman, Symbian C++ for Mobile Phones, Volume 3,Symbian Press, 2007. See chapter 7 for additional information abouthow to use the file system on Symbian OS.4.2 Contacts and CalendarThese recipes will teach you how to use the Contact and Calendar engines.These are part of the personal information management (PIM) services,CONTACTS AND CALENDAR107and are accessed through APIs delivered by the Application Enginessubsystem. More information can be found in the Symbian DeveloperLibrary documentation in your SDK or online on the Symbian DeveloperNetwork.
The Application Engines section of the Symbian OS Guide is agood place to start, with information about specific APIs available in theSymbian OS Reference.There is a split across three distinct modules:• The data itself is stored using the Symbian OS database managementsystem to allow for atomic updates (see the System Libraries section ofthe Symbian Developer Library for more information about databaseson Symbian OS).• A Symbian OS application engine contains the code that configuresthe database, supports standard data formats and links to other partsof the system.• Each UI platform (UIQ and S60) defines an application that usesthe appropriate application engine.
The application is split into aplatform-specific reusable module that exports graphical componentsand the application executable that uses it.We are going to spend some time discussing both the Contacts andCalendar application engines, and the most useful basic operations thateach makes available to you. The UI applications that use the engines lieoutside the scope of this book (although Chapter 5 gives you a head-starton the useful graphical components you may want to reuse).The usual Symbian platform security model needs to be consideredwhen using the Contacts and Calendar APIs since the data needs tobe protected from unauthorized use. Most applications using any PIMfunctionality will require the ReadUserData and WriteUserDatacapabilities.4.2.1 Before You Start with ContactsUnsurprisingly, the Contacts database contains contact items.
They areeither cards or groups. Each item has an identifier during its lifetime inthe database, and each item contains fields. The fields each contain:• A content type, which identifies the meaning of the informationcontained in the field (such as a phone number or an address). Thiscan be a combination of several types to reduce data duplication.For example, email and instant messaging fields could have the samevalue.• A storage type, which identifies the kind of data stored in the field: aninteger, a string, and so on.108SYMBIAN C++ RECIPES• The actual data.• An identifier.
An item can have several fields with the same mappingand label; for example, several home landline numbers, and these aredistinguished by identifier.• An optional ‘mapping’, which is used when exporting the contact toa vCard.• An optional label, which can be used to further specify the meaningof the data. For example, a ‘home’ phone number, a ‘work’ address,and so on.You can find the mappings for the contact fields in your SDK (inepoc32\include\cntdef.h) or search for KUidContactField inthe Symbian Developer Library.On your handset, each contact card can belong to one or more groups,to represent particular collections of contacts. You can create as manygroups as you like. A contact can be a friend, a colleague, a memberof your family or belong to no group, or one or more. While you areable to add your own contact groups to the database, there may be somesystem groups that you will not be able to remove.
In addition, do notconfuse groups with a folder hierarchy: deleting a group will not deletethe contact cards in the group.To speed up the execution of your code, views and filters can beused to retrieve a limited amount of data when accessing the database.Indexing and other internal configuration options allow each database tobe optimized for specific common operations, such as sorting contactsby first or last names.For testing purposes, the code samples of this book contain \PIM\PopulateContact, which makes sure that your development environment contains a Contact database initialized with a few contactitems.4.2.2 Before You Start with CalendarSymbian OS v9.1 deprecated the original Agenda Model API and addeda new Calendar Interim API, to reflect the push toward the iCalendarstandard.