SIM連絡人的讀取相對有點麻煩,需要自己添加類庫,包含的檔案有ETELMM{000a0000}.dso、ETELMM.dso、ETELMM.LIB、etelmm.h、etelmmcs.h、et_clsvr.h etelmm_uiq3.rar (119.5 KB, 下載次數: 99, 售價: 資源分 2 ) 。
其中除了最後一個et_clsvr.h自己建立一個標頭檔,放到inc檔案中,其他根據檔案的位置放到相應的位置。
然後相應的修改MMP檔案,
LIBRARY etel.lib
LIBRARY commdb.lib
LIBRARY ETELMM.lib。就可以訪問RMobilePhoneBookStore類庫,調用裡面的函數訪問到SIM連絡人的資料。然而,SIM卡上的通訊錄格式是“ADN”,所以有需要解析 ADN 的資料。
這個函數可以訪問SIM的全部連絡人,這裡只顯示最近建立的連絡人的相關資訊,如果要顯示全部,代碼需要修改一下,在Copy函數下增加相應代碼就可以擷取所以連絡人的資訊。具體實現如下:
void CAknExEditorContainer::ReadSIML()
{
//定義名片,存放電話薄姓名和電話
struct AspContactList
{
TBuf<30> iName;
TBuf<30> iTel;
};
AspContactList aRecords;
RBuf16 buf16;//儲存資料
_LIT(str,"\f");//換行
//建立RTelServer會話
RTelServer telServer;
User::LeaveIfError(telServer.Connect());
CleanupClosePushL(telServer);
TRequestStatus status;
RTelServer::TPhoneInfo info;
telServer.GetPhoneInfo(0, info);
RMobilePhone phone;
User::LeaveIfError(phone.Open(telServer, info.iName));
CleanupClosePushL(phone);
RMobilePhoneBookStore bookStore;
//ETel的 sub-session 的名字從 "S1" 到 "S29"
//sim卡上的通訊錄格式是 "ADN", 下面3個名字包含 ADN
//_LIT(KETelMeAdnPhoneBook,"S1");
//_LIT(KETelTaAdnPhoneBook,"S6");
//_LIT(KETelIccAdnPhoneBook,"S7");
const TInt storenum[] = { 1, 6, 7, };
TUint j = 0;
for ( ; j < sizeof(storenum) / sizeof(storenum[0]); j++ )
{
TBuf<10> storename;
storename.Copy(_L("S"));
storename.AppendNum(storenum[j]);
TInt err = bookStore.Open(phone, storename);
if ( err != KErrNone )
{ //open failed, try next
continue;
}
CleanupClosePushL(bookStore);
RMobilePhoneBookStore::TMobilePhoneBookInfoV1 storeInfo;
RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg storeInfoPckg(storeInfo);
bookStore.GetInfo(status, storeInfoPckg);
User::WaitForRequest(status);
if ( status.Int() != KErrNone )
{
CleanupStack::PopAndDestroy();
continue;
}
TInt alen=storeInfo.iUsedEntries*70;
if ( storeInfo.iUsedEntries < 1 )
{ //not record
CleanupStack::PopAndDestroy();
continue;
}
HBufC8* hbuf = HBufC8::NewLC(storeInfo.iTotalEntries * 100);
TPtr8 recordbuf = hbuf->Des();
// Read the own number entry
status = KRequestPending;
bookStore.Read(status, 1, storeInfo.iTotalEntries, recordbuf);
User::WaitForRequest(status);
if ( status.Int() != KErrNone )
{
CleanupStack::PopAndDestroy(hbuf);
continue;
}
AspContactList record;
TInt pos = 0; //pos
TInt len = recordbuf.Length();
buf16.Create(alen);
while ( pos < len )
{
if ( recordbuf[pos] == RMobilePhoneBookStore::ETagPBNewEntry && pos != 0 )
{ //new record and not is first ETagPBNewEntry
if ( record.iName.Length() != 0 || record.iTel.Length() != 0 )
{
aRecords=record;
}
record.iName.Zero();
record.iTel.Zero();
}
//新的欄位前面應該有個0x00
if ( recordbuf[pos++] != 0x00 )
{
continue;
}
if ( pos >= len - 3 )
{ // not have a full tlv
break;
}
if ( recordbuf[pos] == RMobilePhoneBookStore::ETagPBText )
{ //name
pos++;
TInt namelen = recordbuf[pos] + recordbuf[pos+1] * 256;
pos += 2; //length has 2 bytes
if ( (pos + namelen) > len )
{ //data error
break;
}
namelen = Min(namelen, record.iName.MaxLength() * 2);
record.iName.Copy((const TUint16*)(recordbuf.Ptr() + pos), namelen / 2);
pos += namelen;
}
else
if ( recordbuf[pos] == RMobilePhoneBookStore::ETagPBNumber )
{ //tel number
pos++;
TInt tellen = recordbuf[pos] + recordbuf[pos+1] * 256;
pos += 2;
if ( (pos + tellen) > len )
{ //data error
break;
}
tellen = Min(tellen, record.iTel.MaxLength() * 2);
record.iTel.Copy((const TUint16*)(recordbuf.Ptr() + pos), tellen / 2);
pos += tellen;
}
}
if ( record.iName.Length() != 0 || record.iTel.Length() != 0 )
{ //last record
aRecords=record;
}
}
CleanupStack::PopAndDestroy(2);
buf16.Append(aRecords.iName);
buf16.Append(str);
buf16.Append(aRecords.iTel);
ClearTextL();
iGTextEd->SetTextL(&buf16);
TestSelectedCase(EAknExEditorClearSelection);
}
按照這個方法,一步一步終於實現了symbian v3 v5的sim卡連絡人的讀取,心情特別舒暢,於是轉寄這個文章。
感謝devdiv的Hency,感謝devdiv與csdn論壇提供大量資料,感謝Google百度提供搜尋。