青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

franksunny的個人技術空間
獲得人生中的成功需要的專注與堅持不懈多過天才與機會。 ——C.W. Wendte

Symbian OS中的消息存儲與常用操作

說明:本文前面消息的基本知識主要參考《Series60應用程序開發》中的有關內容,后面是前段做MTM開發中用到的代碼。

一、消息存儲基本知識

Symbian OS提供的消息傳送架構基于Client/Server機制,服務器負責管理手機上的各種消息,在進行消息相關操作之前我們需要了解Symbian OS是如何組織和存儲消息的。

手機中的各種消息都是以數據項(Entry)形式供程序操作,數據項有4種類型,SymbianOS為每種數據項提供了相應的常量標識UID,這些UID保存在msvuids.h文件中:

Ø         文件夾類型,,對應常量UIDKUidMsvFolderEntry,和PC上的文件系統一樣,每個文件夾可以包含其它數據項也可能是其它數據項的子數據項。

Ø         消息類型,對應常量UIDKUidMsvMessageEntry,它表示該數據項是一條消息。

Ø         附件類型,對應常量UIDKUidMsvAttachmentEntry,它表示該數據項是某條信息的附件。

Ø         服務類型,對應常量UIDKUidMsvServiceEntry,服務數據項包含某個消息服務的配置信息,在一般情況還擁有通過該服務收發的消息數據項。  

除了上面提到的四種類型UID還有常用到的UIDKUidMsvRootEntrymsvids.h),它指的是根數據項,根數據項包含了4個標準文件夾數據項,分別是收件箱(KMsvGlobalInBoxIndexEntryId)、發件箱(KMsvGlobalOutBoxIndexEntryId)、草稿箱(KMsvDraftEntryId)和已發送項(KMsvSentEntryId),另外根數據項下面還包含有各種消息服務的服務項,Symbian OS中消息存儲如下圖所示:

Symbian OS中的消息服務器負責保存各種類型的數據項,這里有兩個基本概念需要了解:消息存儲和消息索引。消息存儲保存了數據項的數據,保存的數據格式取決于消息服務,服務數據項使用消息存儲保存服務配置信息,文件夾數據項不使用消息存儲(即存儲為空),Symbian 提供了CMsvStore類來訪問數據項的消息存儲;為了節省內存和快速檢索消息,消息服務器把數據項的一些概要信息(標題,日期,類型,ID等)寫到消息索引中,當消息服務器啟動時將索引裝載到RAM中直到消息服務器關閉,Symbian提供了TMsvEntry類表示數據項的索引。

操作消息常用的類和數據類型:

CMsvSession

該類代表客戶端(客戶端MTM、用戶接口MTM或者客戶端消息應用程序)與消息服務器端的通訊通道即C/S架構中客戶端與消息服務器的會話。每一個客戶端線程對應一個該類的實例,使用它獲得下面將要提到的CMsvEntry上下文對象。一個消息客戶端應用必須在正常使用任何MTMCMsvEntry對象前,使用OpenSyncL()或者OpenASyncL()來新建一個session對象。

CClientMtmRegistry

Registry掌握了客戶端所有目前可用的MTM有關的細節,消息客戶端可以使用該類獲得從CBaseMtm繼承的對象。

CBaseMtm

這個類主要用來操作消息條目,比如可以新建、修改、發送消息條目。

TMsvId

它只是一個TInt32typedef,消息服務器為每個數據項分配一個惟一的數值做為標識,除了上面提到的幾個固定的標識,其它的標識都是動態分配的。想要對某個消息進行操作必須先得到它的ID,Symbian中消息相關的大部分函數都會用到TMsvId

CMsvEntrySelection

CMsvEntrySelection是一個可以存儲TMsvId的數組,在使用CMsvEntryCMsvServerEntry)的許多操作中都會做為參數或者返回對象。

TMsvEntry

上面已經提到過了它表示數據項的索引,只包含消息的一些概要信息,主要會用到Id()成員函數得到數據項的標識ID和公有數據成員iDetails、iDescriptioniDate,前面兩個成員可以用來獲取和設置索引的概要信息,iDate成員可以獲取和設置數據項的日期及時間。

CMsvEntryCMsvServerEntry

CMsvEntryCMsvServerEntry可以理解為數據項的上下文(Context),這兩個類非常類似,只不過CMsvEntry用于客戶端,CMsvServerEntry用于實現消息的服務器端。它包含兩個部分的功能:一是可以允許訪問與這個entry關聯的,不同類型的數據(比如可以根據指定ID定位數據項、獲得消息存儲和消息索引);二是運行訪問它的子entry和父entry(當然對新得條目又可以進行一功能)。

CMsvStore

上面已經提到過它表示數據項的存儲,可以通過CMsvEntryCMsvServerEntry)的 EditStoreL(),ReadStoreL()函數取得可編輯存儲或只讀存儲。 

 

二、數據項常用操作

因為消息處理建立C/S架構上,所以在消息操作之前,先要進行一些預處理,大致步驟如下:

1、通過消息會話類CMsvSession連接到消息服務器,建立會話。因為通常連接都采用異步方式,所以為了獲取連接的事件通知,實例化CMsvSession對象的類需要繼承自MMsvSessionObserver

2、構造客戶端MTM注冊表對象(通過CClientMtmRegistry::NewL(CMsvSession &aMsvSession)來實現)

3、構造具體的客戶端MTM對象(通過CClientMtmRegistry::NewMtmL(TUid aMtmTypeUid)這里的MtmTypeUIDTMsvEntry內的消息類型ID是一致的)

4、接下來的操作就是根據具體的需求創建、編輯、驗證、發送消息條目(如果只是創建和編輯消息條目,則不用如上這么復雜,可省略MTM對象構造)。

下面的消息操作使用了一個CMsvEntry CMsvServerEntry的指針對象,這兩個類提供的功能基本一樣,但有一部分函數名會不一樣,可以查一下SDK。

1 獲得當前數據項索引和ID

TMsvEntry oldEntry = iServerEntry->Entry(); //這里iServerEntry應該是CMsvServerEntry

TMsvId oldContext = oldEntry.Id(); //如果使用CMsvEntry可以直接使用Id()

 

2 定位到指定數據項

在更換當前數據項之前通常先保存當前數據項索引ID,更換數據項并完成相關操作后再更換回原來的數據項,這可以避免影響其它函數,是一個很好的習慣。

TMsvId oldContext = iServerEntry->Entry().Id();

//使用SetEntry()更換當前數據項到root

iServerEntry->SetEntry(KMsvRootIndexEntryId);

//具體操作后更換回原來數據項

iServerEntry->SetEntry(oldContext);

 

3 查找數據項

下面的三個CMsvEntry成員函數都能完成在當前數據項下進行查找的功能:

CMsvEntrySelection* ChildrenWithMtmL(TUid aMtm) const;

根據消息服務(MTM)進行查找,查找消息索引對象(TMsvEntry)的成員iMtm等于aMtm的數據項ID。

CMsvEntrySelection* ChildrenWithServiceL(TMsvId aId) const;

根據消息服務ID進行查找,查找消息索引對象(TMsvEntry)的成員iServiceId等于aId的數據項ID。

CMsvEntrySelection* ChildrenWithTypeL(TUid aEntryType) const;

根據數據項類型進行查找,查找消息索引對角的(TMsvEntry)的成員iType等于aEntryType的數據項ID

CMsvServerEntry與之相對應的三個函數為GetChildrenWithMtm(), GetChildrenWithService(), GetChildrenWithType(),注意的一點是CMsvEntry的三個函數都返回一個CMsvEntrySelection對象的指針,使用完之后我們要負責釋放,使用CMsvServerEntry的三個函數需要事先構造一個CMsvEntrySelection對象,用完之后也需要釋放。

找出POP3郵箱個數的代碼

iMsvEntry->SetEntryL( KUidMsgTypePop3 );

CMsvEntrySelection* sel = NULL;

sel = entry->ChildrenWithMtmL( KPkiSmtpTechnologyTypeUid );

TInt cnt = sel->Count();  //獲得集合中數據項的個數

delete sel;

 

4 更改消息索引

TMsvEntry entry = iMsvEntry->Entry();

entry.iDetails.Set( _L( “New details” ) );

iMsvEntry->ChangeL( entry );  //把更改后的數據項索引寫回消息索引中去(相當于commit提交)

  這里最后的ChangeL很重要,如果不進行該步調用,那么未將修改的消息索引寫回到消息存儲中。

5 數據項的讀寫

在進行數據項的讀寫之前需要使用EditStoreL(),ReadStoreL()函數得到相應的存儲CMsvStore通過它提供的接口進行操作。

void CMessageView::ViewMessageL(TMsvId aId)

{     

       // Construct the CMsvEntry

       CMsvEntry* entry = iSession->GetEntryL(aId);

       CleanupStack::PushL(entry);

       // Get the messaging store

       CMsvStore* store = entry->ReadStoreL();

       CleanupStack::PushL(store);

       // Construct the CRichText and restore the body text

       CParaFormatLayer* paraLayer = CParaFormatLayer::NewL();

       CleanupStack::PushL(paraLayer);

       CCharFormatLayer* charLayer = CCharFormatLayer::NewL();

       CleanupStack::PushL(charLayer);

       CRichText* body = CRichText::NewL(paraLayer, charLayer);

       CleanupStack::PushL(body);

 

       store->RestoreBodyTextL(*body);

       // Extract body text from CRichText

       TInt len = body->DocumentLength();  //get length

       HBufC *buf = HBufC::NewL( len );

       TPtr ptrBuf = buf->Des();

       body->Extract( ptrBuf, 0, len );  //get data

//因為不同的消息的存儲格式不同,還可能需要對ptrBuf進行相應的解碼才能正常

//顯示

       delete buf;

       buf = NULL;

       CleanupStack::PopAndDestroy(5, entry);

}

 

三、關于SMS的一些特殊操作

1.讀取消息條目

       //讀取發件箱消息條目索引

       TMsvSelectionOrdering sort;

       //全部內容排序,包括隱藏

       sort.SetShowInvisibleEntries(ETrue);

       //設置入口為outbox,也就是發信箱

       CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvGlobalOutBoxIndexEntryId,sort);

       CleanupStack::PushL(entry);

       //選擇全部內容

       CMsvEntrySelection* entries = entry->ChildrenL();

       CleanupStack::PushL(entries);

       //讀取消息索引信息,At(0)代表首信息,取其他的可以給出相應的index

       TMsvId aEntryId = entries->At(0);

       //得到消息索引的時間

       TTime time;

       time = entry->ChildDataL(aEntryId).iDate;

       iSmsMtm->SwitchCurrentEntryL(aEntryId);//iSmsMtmCSmsClientMtm類型的指針變量,它已經初始化

       iSmsMtm->LoadMessageL(); // load the message

       CRichText& body = iSmsMtm->Body(); //sms的內容存到CRichText控件對象中

       TPtrC msg(body.Read(0));

       //彈出對話框,提示短信內容

       CAknInformationNote* informationNote = new (ELeave) CAknInformationNote;

       informationNote->ExecuteLD(msg);

       CleanupStack::PopAndDestroy();

 

2.刪除消息條目

       //刪除草稿箱中的消息條目

       TMsvSelectionOrdering sort;

       sort.SetShowInvisibleEntries(ETrue);

       CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvDraftEntryId,sort);

       CleanupStack::PushL(entry);

       CMsvEntrySelection* entries = entry->ChildrenL();

       CleanupStack::PushL(entries);

       TInt i = entries->Count();

       for(TInt ncount=0;ncount<i;ncount++)

       {

              entry->DeleteL(entries->At(ncount));

       }

       // information to the user

       iEikonEnv->InfoMsg(_L("DeleteAll Done!"));

       CleanupStack::PopAndDestroy(2);

 

3.創建消息條目

創建消息條目部分在收件箱和草稿箱兩個地方是不一樣的,具體代碼如下:

       //在草稿箱中創建短信

       const TInt LEN = 12;

       //轉入收件箱

       iSmsMtm->SwitchCurrentEntryL(KMsvDraftEntryId);

       //構建消息索引

       TMsvEntry newIndexEntry;

       newIndexEntry.iDate.HomeTime();

       newIndexEntry.iMtm = KUidMsgTypeSMS;

       newIndexEntry.iType = KUidMsvMessageEntry;

       //in 3rd edition crashes here if capabilities are wrong

       newIndexEntry.iServiceId = iSmsMtm->ServiceId();

       newIndexEntry.iDetails.Set(aName);//aName為收件人名稱

       newIndexEntry.iDescription.Set(aContent.Left(LEN));

       newIndexEntry.SetUnread(ETrue);

       iSmsMtm->Entry().CreateL(newIndexEntry);

       TMsvId smsId = newIndexEntry.Id();

       iSmsMtm->SwitchCurrentEntryL(smsId);

       //填充消息存儲區

       iSmsMtm->AddAddresseeL(aAddr);//aAddr為收件人號碼,信息位于消息頭中

       CRichText& body = iSmsMtm->Body();//消息正文

       body.Reset();

       body.InsertL(0, *iSmsContext);

       //提交保存

       iSmsMtm->SaveMessageL();

注:當然如果要發送的短信,還需要進行具體的設定,這部分將在發送消息里面詳述,這里只是做為普通的創建消息,與收件箱中消息進行比較,具體見下面代碼示例。

 

       //在收件箱中創建短信

       const TInt LEN = 12;

       //轉入收件箱

       iSmsMtm->SwitchCurrentEntryL(KMsvGlobalInBoxIndexEntryId);

       //構建消息索引

       TMsvEntry newIndexEntry;

       //newIndexEntry.iDate.HomeTime();//收件箱短信索引頭在CSmsHeader中設置

       newIndexEntry.iMtm = KUidMsgTypeSMS;

       newIndexEntry.iType = KUidMsvMessageEntry;

       //in 3rd edition crashes here if capabilities are wrong

       newIndexEntry.iServiceId = iSmsMtm->ServiceId();

       newIndexEntry.iDetails.Set(aAddr);

       newIndexEntry.iDescription.Set(aContent.Left(LEN));

       newIndexEntry.SetUnread(ETrue);

       iSmsMtm->Entry().CreateL(newIndexEntry);

       TMsvId smsId = newIndexEntry.Id();

       iSmsMtm->SwitchCurrentEntryL(smsId);

       //填充消息存儲區

       //CSmsHeader& header = iSmsMtm->SmsHeader();

       //header.SetFromAddressL(aAddr);//這里我采用了兩種方法,均不能正確設置發件人號碼

       //iSmsMtm->AddAddresseeL(aAddr);//后來才知道這里為收件人號碼,所以必須在以后修改

       CRichText& body = iSmsMtm->Body();

       body.Reset();

       body.InsertL(0, *iSmsContext);

       //提交保存

       iSmsMtm->SaveMessageL();

       //完善消息頭,設置發件人號碼和發送時間

       CMsvStore* messageStore = iSmsMtm->Entry().EditStoreL();

       CleanupStack::PushL( messageStore );

       CSmsHeader* hdr = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, body );

       CleanupStack::PushL( hdr );

       hdr->SetFromAddressL(iNumber);

       TTime nowTime;

       nowTime.HomeTime();

       hdr->Deliver().SetServiceCenterTimeStamp(nowTime);

       hdr->StoreL(*messageStore);      

       messageStore->CommitL();

       CleanupStack::PopAndDestroy(hdr);    

       CleanupStack::PopAndDestroy(messageStore);

    // 修改當前消息索引為只讀,這樣收件箱列表處瀏覽會有回復選項

       //但是如果在之前就設置ReadOnly就會導致SaveMessageL出錯 

       newIndexEntry.SetReadOnly(ETrue);

       //消息索引提交更改

       iSmsMtm->Entry().ChangeL(newIndexEntry);

4.發送消息條目

其實發送消息可以使用客戶端MTM方法,但是一般都是在活動對象中實現,或者實現Send-As APICSendAppUi類來實現。以下代碼簡單給出客戶端Mtm的方法,具體可以下載諾基亞論壇liuxg大大編寫的SmsSendTest例子,在這里給出其下載連接http://www.shnenglu.com/Files/franksunny/SmsSendTest.rar

       //發送消息

       //iMtm是在新建sms階段設定

       TMsvEntry msvEntry = iMtm->Entry().Entry();

       //重新設定TMsvEntry

       msvEntry.iDetails.Set(iRecipient->Des());  // set recipient info in details

       msvEntry.SetInPreparation(EFalse);         // set inPreparation to false

       msvEntry.SetSendingState(KMsvSendStateWaiting);   // set the sending state (immediately)

       msvEntry.iDate.HomeTime();                        // set time to Home Time

       // 得到sms內容

       CRichText& mtmBody = iMtm->Body();

       mtmBody.Reset();

       mtmBody.InsertL(0, KGDSMSTag);   //插入我們的短信內容

       // 使用CSmsClientMtm類處理sms

       CSmsClientMtm* smsMtm = STATIC_CAST(CSmsClientMtm*, iMtm);

       smsMtm->RestoreServiceAndSettingsL();

       //CSmsHeader封裝sms消息的參數,像服務中心號碼和發送設定

       CSmsHeader& header = smsMtm->SmsHeader();

       //CSmsSettings類用來詳細設定sms Header

       CSmsSettings* sendOptions = CSmsSettings::NewL();

       CleanupStack::PushL(sendOptions);

       sendOptions->CopyL(smsMtm->ServiceSettings());

       sendOptions->SetDelivery(ESmsDeliveryImmediately);//設定立即發送

       header.SetSmsSettingsL(*sendOptions);

       //檢查服務中心號碼有效性

       if(header.Message().ServiceCenterAddress().Length() == 0)

       {

              // 如果沒有設定,則查找默認中心號碼

              CSmsSettings* serviceSettings = &(smsMtm->ServiceSettings());

              //中心號碼列表為空

              if(!serviceSettings->NumSCAddresses())

              {

                   // 錯誤消息

                     iEikonEnv->InfoWinL(_L("No service center number"),_L("cannot send this one."));

              }

             else

              {

                     // 設定為默認服務中心號碼

                     CSmsNumber* sc = 0;

                     sc = &(serviceSettings->SCAddress(serviceSettings->DefaultSC()));

                     header.Message().SetServiceCenterAddressL(sc->Address());

              }

       }

       CleanupStack::PopAndDestroy();

      ... ...

       CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;

       CleanupStack::PushL(selection);

       selection->AppendL(movedId); // 添加我們要發送的sms,movedId在省略部分有定義,是TMsvId型變量

       // 調用的這個函數是用于發送的,具體的代碼后面介紹

       SetScheduledSendingStateL(selection);  

       CleanupStack::PopAndDestroy(); // selection

       return ETrue; // 到這里sms已被發送

---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------

       void SetScheduledSendingStateL(CMsvEntrySelection* aSelection)

       {

              CBaseMtm* smsMtm = iMtm;

              // 添加entry到任務列表

              TBuf8<1> dummyParams;

              CCommandAbsorbingControl::NewLC();

              CMsvOperationWait* waiter = CMsvOperationWait::NewLC();

              waiter->Start();

              // 這個函數是關鍵

              CMsvOperation* op= smsMtm->InvokeAsyncFunctionL(

                            ESmsMtmCommandScheduleCopy,

                            *aSelection,

                            dummyParams,

                            waiter->iStatus);

              CleanupStack::PushL(op);

              CActiveScheduler::Start(); //開始時間表中任務

              CleanupStack::PopAndDestroy(3); // waiter, op, CCommandAbsorbingControl

       }

 

SMS操作補充

在項目開發過程中會時不時爆發些問題,為此一旦遇到問題后得以解決都會在這里進行知識點與實踐的積累

關于CSmsClientMtm::LoadMessageL

在調用CSmsClientMtm::LoadMessageL之前,必須調用SwitchCurrentEntryL(TMsvId aId)SetCurrentEntryL(CMsvEntry* aEntry)將客戶端Mtm轉到當前項,然后才能順利調用,由于有時短信在Sim卡上,故調用時可能會產生KErrAccessDenied-21)的錯誤,這種情況下我們通常采用如下代碼實現

TInt error = KErrNone;

for (TInt i; i<KNumRetries; ++i)

{

    TRAP(error, iSmsMtm->LoadMessageL());

    if (error == KErrAccessDenied) // something is still busy with this entry

    {

        User::After(KDelayPeriod);

    }

    else

    {

        break;

    }

}

User::LeaveIfError(error);

后來還發現一種情況,就是如果當前的消息是彩信,則在正確使用如上代碼的時候,在調用CSmsClientMtm::LoadMessageL會遇到KErrNotFound-1)的錯誤,這個問題還是需要值得注意一下的。

關于短信時間問題

在短信中用到的時間,都是UTC時間,也即總所周知的GMT時間,系統的短信程序在顯示時間是會將這個UTC時間轉化為手機當前所設時區的本地時間,在發送短信的時候,因為存在草稿箱和發件箱中的短信只有一個時間,所以問題不大,我們只要在創建短信時調用TMsvEntry::iDate.UniversalTime()函數即可。

在收件箱中的短信則有兩個時間,一個跟上面一樣,簡單表示接受時的本地時間,而另外一個時間則在信息詳情中才能看到,這是服務中心的時間,也即短信具體何時經服務中心發出到手機的時間。我們在測試過程中發現,中國移動在099月份,所有139號段發過來的短信在這個服務中心時間上存在錯誤,其GMT時間變成了北京時間,其時區變成了格林尼治的零時區。當時因為這個問題還花了一天時間來進行測試驗證。

另外畫蛇添足下,有一個UTC時間轉為本地時間的簡單函數如下:

#include <tz.h>

#include <tzconverter.h> //tzclient.lib

void ConvertTimeToLocal(TTime& aTime)

{

       RTz tzServer;

       User::LeaveIfError(tzServer.Connect());

       CleanupClosePushL(tzServer);

       CTzConverter* tzConverter = CTzConverter::NewL(tzServer);

       CleanupStack::PushL(tzConverter);

       tzConverter->ConvertToLocalTime(aTime);

       CleanupStack::PopAndDestroy(2);

}

關于客戶端MTM對象讀取和發送注意事項

在工程代碼中發現當只實例化一個CSmsClientMtm對象,而要用該對象進行讀取短信和發送短信操作時,未調用讀取操作時,發送正常,但是一旦調用讀取短信操作,就會在語句CSmsClientMtm::AddAddresseeL設置收件人號碼時報-5KErrNotSupported)功能不支持的錯誤提示。

具體原因是為什么暫不知道,只是看到newlc論壇有該問題的解決方案,采用創建兩個客戶端MTM對象的方法來實現,具體代碼是

iSmsMtmR = static_cast(iMtmReg->NewMtmL(KUidMsgTypeSMS)); // used for receive

iSmsMtmS = static_cast(iMtmReg->NewMtmL(KUidMsgTypeSMS)); // used for send

驗證的確可以,如果要看原帖具體地址則在http://nioulk.newlc.com/topic-10736

 

 

致謝:本文其實本人并非原創,只是將Beover1984的原文《Symbian OS中的消息存儲與常用操作》和網上流傳的《SMS故事》做了學習后,結合工作中的實際而整理得到,非常感謝以上兩位作者的指點。

 

 





本文有一個圖片沒有顯示出來,但是word文檔中是有的,為此給出word文檔的下載地址:http://www.shnenglu.com/Files/franksunny/SymbianOSMessage.rar
posted on 2008-07-30 21:04 frank.sunny 閱讀(3261) 評論(2)  編輯 收藏 引用 所屬分類: symbian 開發

FeedBack:
# re: [整理]Symbian OS中的消息存儲與常用操作
2009-06-20 11:18 | svyee
非常感謝~~  回復  更多評論
  
# re: [整理]Symbian OS中的消息存儲與常用操作
2011-03-28 17:26 | lovelycheep
非常感謝樓主講解的這么詳細,但是我還是有個問題想向LZ請教一下 關于CSmsClientMtm::LoadMessageL 還是有點問題的

我在TRAP(error, iSmsMtm->LoadMessageL());之后error還是0,沒出現問題,但是我就是取不到信息內容,一下是我的代碼
TInt error = KErrNone;
TRAP(error, iSmsMtm->LoadMessageL());

CRichText& richText= iSmsMtm->Body();
inboxStore->RestoreBodyTextL(richText);
const TInt length = richText.DocumentLength();

length返回值總是0,研究了兩天了,還沒搞懂,請LZ賜教……  回復  更多評論
  

常用鏈接

留言簿(13)

隨筆分類

個人其它博客

基礎知識鏈接

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99国产麻豆精品| 亚洲另类春色国产| 欧美在线视频免费| 性欧美办公室18xxxxhd| 国内精品久久久久伊人av| 久久婷婷麻豆| 欧美大胆人体视频| 亚洲宅男天堂在线观看无病毒| 亚洲国产婷婷香蕉久久久久久| 国产精品成人一区二区三区夜夜夜| 亚洲在线观看免费视频| 欧美**人妖| 亚洲欧美日韩区| 黄色成人精品网站| 亚洲韩国日本中文字幕| 欧美日韩在线看| 久久久av毛片精品| 欧美精品成人| 久久久久久久尹人综合网亚洲| 另类图片国产| 欧美一区二区三区免费观看视频| 久久视频一区二区| 亚洲在线一区二区| 美女啪啪无遮挡免费久久网站| 亚洲午夜久久久| 久久久久久成人| 亚洲自拍偷拍一区| 美玉足脚交一区二区三区图片| 亚洲欧美一区二区三区久久| 麻豆国产精品va在线观看不卡| 亚洲永久在线| 欧美精品粉嫩高潮一区二区| 久久九九精品| 国产精品欧美日韩一区| 欧美激情五月| 国内久久精品视频| 亚洲先锋成人| 在线视频免费在线观看一区二区| 久久国产日韩| 欧美一区二区三区在线观看 | 中文av一区二区| 久久嫩草精品久久久精品一| 亚洲欧美日韩国产中文| 久久综合电影| 久久精品夜夜夜夜久久| 国产裸体写真av一区二区| 亚洲精品免费网站| 亚洲激情六月丁香| 久久综合久久综合这里只有精品| 亚洲影院在线| 国产精品日韩精品欧美精品| 亚洲电影天堂av| 在线观看欧美黄色| 久久精品综合| 蜜桃精品一区二区三区| 国产午夜精品全部视频播放| 亚洲一区bb| 这里只有精品丝袜| 欧美精品成人| 亚洲精品一区中文| 一区二区av在线| 欧美激情精品久久久久| 亚洲欧洲精品一区二区三区| 亚洲高清资源| 欧美华人在线视频| 亚洲精品一二| 一区二区三区久久久| 欧美日韩亚洲一区二区| 99伊人成综合| 欧美一区二区国产| 国产丝袜美腿一区二区三区| 午夜精品影院在线观看| 久久av在线| 国产亚洲欧美中文| 久久深夜福利免费观看| 亚洲高清不卡在线观看| 一本久久a久久免费精品不卡| 欧美好吊妞视频| 夜夜精品视频一区二区| 亚洲尤物在线| 国产一区二区三区久久悠悠色av| 久久精品午夜| 亚洲国产经典视频| 亚洲综合精品| 好吊日精品视频| 免费一级欧美在线大片| 夜夜嗨网站十八久久| 久久久国产精彩视频美女艺术照福利| 国内精品久久久久久影视8| 免费成人av在线看| 在线亚洲国产精品网站| 久久国产欧美日韩精品| 永久免费精品影视网站| 欧美日韩精品一区二区在线播放 | 亚洲第一精品久久忘忧草社区| 欧美成人免费播放| 亚洲永久在线观看| 欧美aaa级| 亚洲在线中文字幕| 精品电影一区| 欧美日韩国产麻豆| 久久久久久穴| 正在播放欧美一区| 亚洲成人资源| 久久精品国产精品| 在线午夜精品| 91久久精品国产91久久性色tv| 欧美性做爰猛烈叫床潮| 欧美www视频| 欧美在线|欧美| 亚洲免费观看高清完整版在线观看熊| 久久久国产精品一区| 在线视频亚洲欧美| 日韩视频在线观看国产| 亚洲午夜在线视频| 黄网动漫久久久| 国产精品www.| 欧美国产日本| 久久久999国产| 午夜免费日韩视频| 亚洲精品午夜| 亚洲成人直播| 美女黄网久久| 久久久人成影片一区二区三区观看 | 亚洲伊人伊色伊影伊综合网| 91久久精品国产91久久| 免费观看久久久4p| 久久久久久电影| 久久精品理论片| 欧美在线一区二区三区| 欧美伊人久久| 久久aⅴ国产欧美74aaa| 性做久久久久久免费观看欧美| 亚洲无毛电影| 亚洲欧美成人一区二区在线电影 | 亚洲大胆人体在线| 在线精品观看| 91久久精品日日躁夜夜躁国产| 伊人久久大香线| 精品51国产黑色丝袜高跟鞋| 国产一区二区三区日韩| 狠狠久久亚洲欧美| 影院欧美亚洲| 亚洲三级视频在线观看| 99国产一区| 亚洲一区二区三区成人在线视频精品| 日韩亚洲欧美一区| 一区二区三区不卡视频在线观看 | 最新国产精品拍自在线播放| 亚洲国产成人高清精品| 欧美激情一区二区三区蜜桃视频 | 亚洲福利在线视频| 亚洲另类一区二区| 亚洲专区在线视频| 久久精品人人| 免费观看一区| 国产精品白丝av嫩草影院| 国产精品美女久久久久久免费| 国产精品久久二区| 国产亚洲二区| 亚洲人成欧美中文字幕| 一区二区三区欧美| 亚洲综合另类| 卡通动漫国产精品| 亚洲电影观看| 亚洲影院色无极综合| 久久精品99国产精品日本| 欧美成人免费小视频| 国产精品久久久久久户外露出| 国产日韩在线视频| 亚洲精选大片| 久久精品99无色码中文字幕| 农夫在线精品视频免费观看| 亚洲乱码国产乱码精品精| 亚洲欧美日韩久久精品| 免费成人av资源网| 国产日韩精品一区观看| 亚洲精品乱码久久久久久蜜桃91| 亚洲女人天堂成人av在线| 欧美成人高清视频| 91久久精品美女| 欧美二区不卡| 欧美freesex交免费视频| 亚洲六月丁香色婷婷综合久久| 性亚洲最疯狂xxxx高清| 欧美日韩国产免费观看| 国内不卡一区二区三区| 亚洲在线国产日韩欧美| 欧美大片专区| 久久er99精品| 国产精品久久久久一区| 日韩一区二区久久| 免费观看在线综合| 欧美一区视频| 国产精品入口日韩视频大尺度| 亚洲欧洲一区| 欧美成人精品| 欧美一区二区三区视频| 国产精品v亚洲精品v日韩精品 | 国产综合视频在线观看|