APN symbian手機上的接入點編程

特定接入點的查找/創建
1.   Overview

特定接入點的查找/創建應該是這樣的一個過程。首先你從一個配置文件裏面讀出你要選擇的AP的名字(一般情況下我們是知道要用那個接入點的,而且爲 了方便配置一般也把它寫到配置文件中去)。在得到這個名字後,我們就遍歷機器上所有的接入點,查找是否有我們需要的,如果有我們就返回那個接入點的索引, 如果沒有就要在設備上創建一個AP,創建這個AP的參數也存在配置文件中,成功創建後返回其索引以備後用。


2.   Code


// 從配置文件中讀出接入點的名稱

TBuf<64> apnConnName;

GetAPNnameFromConfig(apnConnName);

apnConnName.LowerCase();


// 遍歷通信數據庫,尋找對應的接入點的索引

TUint32 iapId(-1);

CCommsDatabase* commDb = CCommsDatabase::NewL();

CleanupStack::PushL(commDb);

CCommsDbTableView* view = commDb->OpenTableLC(TPtrC(IAP));

TFileName iapName;

User::LeaveIfError(view->GotoFirstRecord());

do

{

    view->ReadTextL(TPtrC(COMMDB_NAME), iapName);

    iapName.LowerCase();

    if (!iapName.Compare(*apName))

    {

       view->ReadUintL(TPtrC(COMMDB_ID), iapId);

       break;

    }

}

While (KErrNone == view->GotoNextRecord());


CleanupStack::PopAndDestroy(2); // view, commDb

CleanupStack::PopAndDestroy(apName);

// 找到就返回

if (iapId != -1)

    return iapId;


// 沒有找到就創建一個,從配置文件中讀出參數

TInt apnDataBearer;

TBuf<64> apnAccessPointName;

TBool apnAuthentication;

TBuf<64> apnProxyNameAddr;

TInt apnProxyPortNumber;


GetAPNBearerFromConf(apnDataBearer);

GetAPNnameFromConf(apnAccessPointName);

GetAPNAuthFromConf(apnAuthentication);

GetAPNProxyNameFromConf(apnProxyNameAddr);

GetAPNProxyPortFromConf(apnProxyPortNumber);


//創建一個接入點

CApAccessPointItem* apn = CApAccessPointItem::NewLC();


apn->SetNamesL( apnConnName );

apn->SetBearerTypeL( (TApBearerType)apnDataBearer );

apn->WriteLongTextL( EApGprsAccessPointName, apnAccessPointName );


if( apnAuthentication )

{

    apn->WriteBool( EApGprsDisablePlainTextAuth, ETrue );

    apn->WriteBool( EApGprsDisablePlainTextAuth, ETrue );

}

else

{

    apn->WriteBool( EApGprsDisablePlainTextAuth, EFalse );

}


if( apnProxyNameAddr.Length() )

{

    apn->WriteLongTextL( EApProxyServerAddress, apnProxyNameAddr );

    apn->WriteUint( EApProxyPortNumber, (TUint)apnProxyPortNumber );

}


CCommsDatabase* commDb = CCommsDatabase::NewL();

CleanupStack::PushL( commDb );

CApDataHandler* handler = CApDataHandler::NewLC( *commDb );

TInt commErr = commDb ->BeginTransaction();

newApId = (TInt32)handler->CreateFromDataL( *apn );

commErr = commDb->CommitTransaction();


CleanupStack::PopAndDestroy( handler );

CleanupStack::PopAndDestroy( commDb );

CleanupStack::PopAndDestroy( apn );

return newApId;

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

 
 
 
1. Overview: The management interface for a network connection or subconnection. Provides clients with the following functionality:

     - Opening and closing the connection

     - Starting a connection, which means associating it with a new underlying interface

     - Attaching the RConnection instance to an existing interface

     - Stopping the connection, which means disassociating it from the underlying interface

     - Obtaining progress information and notification during connection start-up

     - Notifying when subconnections come up and go down

     - Notifying when there is a service change for the connection

     - Notifying when a given amount of data has been sent or received on a connection or subconnection

     - Reading CommDB fields specific to an active connection

     - ......

Note that several of the new functions are asynchronous. It is essential for these calls that the client ensures that the parameters they pass to the RConnection API remain in scope for the duration of the asynchronous call.


這個類就如同RFile一樣,在你打開一個文件的使用的,你的首先用RFs,然後在用RFile,這裏也是一樣的道理,你首先的用 RSsocketServ去建立一個Session,然後用RConncetion來打開這個session被你所用。API也是對應 的,open/close, start(attach)/stop等等。


2. Methods

     - IMPORT_C TInt Open(RSocketServ &aSocketServer, TUint aConnectionType=KConnectionTypeDefault);

    - Opens a new RConnection instance.

打開一個Socket server的連接。


     - IMPORT_C void Start(TRequestStatus &aStatus)

    - Starts a connection asynchronously using the existing connection preferences in CommDb.

    - Note that this may or may not result in a dialog prompt, depending on the connection preference settings.


     - IMPORT_C void Start(TConnPref &aPref, TRequestStatus &aStatus);

    - Starts a connection asynchronously by overriding connection preference settings in CommDb.

    - The settings which can be overridden are: IAP Id, Network Id, Dialog Preference, Direction, Bearer Set.


     - IMPORT_C TInt Start();

    - Starts a connection synchronously using the connection preference settings in CommDb.

    - There is no overriding of settings (such as IAP Id, Network Id, Dialog Preference, Direction, Bearer Set).

    - This may or may not result in a dialog prompt, depending on the connection preference settings.


     - IMPORT_C TInt Start(TConnPref &aPref);

    - Starts a connection synchronously by overriding connection preference settings in CommDb.

    - The settings which can be overridden are: IAP Id, Network Id, Dialog Preference, Direction, Bearer Set.


start()有四個重載的方法,按同步和異步分類或是按用CommDb中存在的connection preference還是按照自己設置的分類。第一個是異步的,使用CommDb中存在的connection preference來連接,所以他不保證能夠彈出對話框來。第二個也是異步的,但是他覆蓋了CommDb中的connection preference的部分或是全部參數(可以設置的參數有5個:IAP Id, Network Id, Dialog Preference, Direction, Bearer Set;對應的類是Class TCommDbConnPref,其方法是:SetBearerSet(), SetDialogPreference(), SetDirection(), SetIapId(), SetNetId() 各種取值的範圍參考SDK)。如果我們想同步選擇的話就可以用第三個,其返回值表明連接是否成功,依然是用CommDb中存在的connection preference來連接,不保證能夠彈出對話框來。第四個就是用自己設置的connection preference來連接的同步版本。所以方法是很周全的,根據自己的要求來選擇。主要考慮是不是彈出對話框,還是slient的進行連接,是否自己有 特殊的鏈接屬性設置等等。

 

     - IMPORT_C TInt Stop();

    - Stops the entire connection by disconnecting the underlying network interface immediately, regardless of whether other clients are using it or not.

    - IMPORT_C TInt GetIntSetting(const TDesC &aSettingName, TUint32 &aValue);

    - Pre-Condition An attached connection: as a result of performing either a Start() or an Attach()

    - Reads current CommDb settings for the active connection.

    - const TDesC &aSettingName The CommDb table name and field name to be accessed. Of the form "<table name>/<field name>" (for example "IAP/Id" or "ModemBearer/PortName").

    - TUint32 &aValue On return, the value of the table/field pair.


    - IMPORT_C TInt GetDesSetting(const TDesC &aSettingName, TDes8 &aValue);

    - IMPORT_C TInt GetDesSetting(const TDesC &aSettingName, TDes16 &aValue);


在我們調用的start之後,用戶選擇了接入點,我們就可以用上面的API來取得用戶所選擇的接入點的信息,可以是所選接入點的索引或是8/16位的名稱。因爲在start之前,我們可以設置IAP Id,這裏用的是一個索引,所以一般我們用第一個API。

 

    - IMPORT_C void ProgressNotification(TNifProgressBuf &aProgress, TRequestStatus &aStatus, TUint aSelectedProgress=KConnProgressDefault);  

    - TNifProgressBuf &aProgress - A buffer to receive progress notification.

    - Requests asynchronous progress notification for the connection.


aProgress.iStage參數可以告訴我們現在的連接狀態:KConnectionOpen, KConnectionClosed, KLinkLayerOpen, KLinkLayerClosed, KConnectionFailure等等(nifvar.h文件中)


    - IMPORT_C void Close();

    - Closes the connection.

          - The connection will not be dropped immediately: it will be dropped when there is no more data traffic on the connection. So if a client needs to graciously shutdown the connection, Close(), not Stop(), needs to be used after shutting down the socket.
 
 
//////////////////////////////////////////////////////////////////////////////////////////////


3. Example

接入點選擇的思路:首先應該有個配置文件定義了你要選擇的接入點的名稱,然後你根據這個名稱在CommDb中去查找,如果找到了就取其索引就沒問題 了。如果找不到就得創建一個APN,創建AP的參數可以在另一個配置文件中定義,成功創建後我們就知道了我們要的AP的索引了。然後在根據需要(同步或是 異步)來實現。

同步方法:

TInt CConnectionManager::SelectIAPSyn()

{

    iConnection.Stop();

    User::LeaveIfError(iConnection.Start());


    _LIT( KIAPIdSetting, "IAP//Id" );

    aConn.GetIntSetting( KIAPIdSetting, iIAPId);

    iConnection.ProgressNotification( iProgress, iStatus );

    SetActive();

    return iIAPId;

}


void CConnectionManager::RunL()

{

    switch ( iProgress().iStage )

    {

       case KConnectionClosed:

       case KLinkLayerClosed:

       {

       }

}


這裏雖然也用的AO 但是是用來檢測連接過程的,而不是選擇連接的。

異步方法:

void CConnectionManager::SelectIAPAsyn()

{

    if ( !IsActive() )

    {

       iConnection.Stop();

       iConnection.Start( iStatus );

       SetActive();

       iIAPFlag = EFalse;  

       return;

    }

}


void CConnectionManager::RunL()

{

    if ( !iIAPFlag )

    {

       if ( KErrNone != iStatus.Int() )

       {

           iIAPFlag = EFalse;

           return iObserv.Event( KErrCouldNotConnect, ... )

       }

       iIAPFlag = ETrue;

       _LIT( KIAPIdSetting, "IAP//Id" );

       aConn.GetIntSetting( KIAPIdSetting, iIAPId);

       iObserv.Event( iIAPId, ...);

    }

}

異步方法有Preference:

void CConnectionManager::SelectIAPSynWithPref()

{

        TCommDbConnPref connectPref;

        connectPref.SetDialogPreference(ECommDbDialogPrefPrompt);

        connectPref.SetDirection(ECommDbConnectionDirectionOutgoing);

        connectPref.SetBearerSet(ECommDbBearerUnknown);

        iConnection.Stop();

    iConnection.Start(connectPref);

    _LIT(KIAPIdSetting, "IAP//Id");

    iConnection.GetIntSetting(KIAPIdSetting, iSelectedIap);

}

同步方法有Preference:

void CConnectionManager::SelectIAPAsynWithPref()

{

        TCommDbConnPref connectPref;

        connectPref.SetDialogPreference(ECommDbDialogPrefPrompt);

        connectPref.SetDirection(ECommDbConnectionDirectionOutgoing);

        connectPref.SetBearerSet(ECommDbBearerUnknown);

        iConnection.Stop();

        iConnection.Start(connectPref,iStatus);

}


void CConnectionManager::RunL()

{

    if ( !iIAPFlag )

    {

       if ( KErrNone != iStatus.Int() )

       {

           iIAPFlag = EFalse;

           return iObserv.Event( KErrCouldNotConnect, ... )

       }

       iIAPFlag = ETrue;

       _LIT( KIAPIdSetting, "IAP//Id" );

       aConn.GetIntSetting( KIAPIdSetting, iIAPId);

       iObserv.Event( iIAPId, ...);

    }

}


結合特定接入點的查找/創建我們在後臺選擇接入點進行連接:


void CConnectionManager::SelectIAPSynWithPref(Tint aIAPid)

{

        TCommDbConnPref connectPref;

connectPref.SetIapId( aIAPId );

        connectPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);

        connectPref.SetDirection(ECommDbConnectionDirectionOutgoing);

        iConnection.Stop();

        iConnection.Start(connectPref);

}

這種方法是在我們選定了接入點後不彈出接入點對話框自動進行連接的。通常的做法是我們第一個進行連接,彈出對話框,之後如果由於信號原因或是其他原因導致了接入點的丟失,我們就應該在進行連接,此時的連接完全是可以用隱性連接,不通知用戶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章