[转]总结开发中的19个问题+若干问题

1 、获取IMSI号、手机版本等
   CTelephony:GetSubscriberId()
   CTelephony:GetPhoneId()
   CTelephony:Version()
2、获取屏幕尺寸
   TSize CEikConsoleScreen::ScreenSize
3、更改ListBox字体  
   方法1:
       _LIT(KFontName,"Courier");
       TFontSpec fontSpec;
       fontSpec.iTypeface.iName=KFontName;
       fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       fontSpec.iHeight=100;
       CFont * iFont;
       CCoeEnv::Static()->ScreenDevice()->GetNearestFontInTwips(iFont,fontSpec);
       CColumnListBoxData * data =
       ( static_cast<CColumnListBoxItemDrawer*>
       (iListBox->ItemDrawer()))->ColumnData();
       data->SetColumnFontL(1,iFont);
   方法2:
       data->SetColumnFontL(1,LatinPlain12());
   方法3:
       const CFont * iFont1;
       const CFont * iFont2;
       iFont1 = AknLayoutUtils::FontFromId(EAknLogicalFontPrimaryFont);//大字体
       iFont2 = AknLayoutUtils::FontFromId(EAknLogicalFontPrimarySmallFont);//小字体
       data->SetColumnFontL(1,iFont2);
   注意以上方法都必须在ActiveL()后面(也就是必须List创建好了)再使用.
4UID范围说明
      Protected Range
        0  0x00000000 - 0x0FFFFFFF        Development use only
        0x01000000 - 0x0FFFFFFF               用作测试
       1  0x10000000 - 0x1FFFFFFF    Legacy UID allocations
       2  0x20000000 - 0x2FFFFFFF    V9 protected UID allocations
       3  0x30000000 - 0x3FFFFFFF    Reserved
       4  0x40000000 - 0x4FFFFFFF    Reserved
       5  0x50000000 - 0x5FFFFFFF    Reserved
       6  0x60000000 - 0x6FFFFFFF         Reserved
       7   0x70000000 - 0x7FFFFFFF    Vendor IDs Unprotected Range
       8     0x80000000 - 0x8FFFFFFF        Reserved
       9  0x90000000 - 0x9FFFFFFF         Reserved
       A   0xA0000000 - 0xAFFFFFFF      V9 unprotected UID allocations
       B     0xB0000000 - 0xBFFFFFFF        Reserved
       C  0xC0000000 - 0xCFFFFFFF       Reserved
       D     0xD0000000 - 0xDFFFFFFF      Reserved
       E     0xE0000000 - 0xEFFFFFFF      Development use only
       F     0xF0000000 - 0xFFFFFFFF        Legacy UID compatibility range
5、关于真机文件目录
       在*.pkg文件中,'-'前面是PC上的文件目录,请确认PC上对应目录下存在这些文件。
   '-'后面是手机上的目录,采用相对路径,如“resource/apps/*.mbm”
   注意:程序中若加载*.mbm文件中图片,需要使用“resource//apps//*.mbm”,注意'//'。
6、经常出现的SetRect(aRect);ActivateL();出现错误
       需要注意控件是否成功构造。
       通常是由于构造函数中的代码次序问题。控件的构造应该在 ActiveL前完成。
7、申请开发证书将支持能力
       Capabilities for the certificate
   LocalServices   Location   NetworkServices   PowerMgmt   ProtServ
   ReadDeviceData   ReadUserData   SurroundingsDD   SwEvent
   TrustedUI   UserEnvironment   WriteDeviceData   WriteUserData
8、打包常用命令
打包:makesis *.pkg *.sis
签名:signsis *.sis *.sisx *.cer *.key 111111
产生自签名证书:makekeys -cert -password 111111 -len 1024 -dname "CN=China OU=Develo
pment OR=Datang mobile Ltd [email protected]" lsg.key lsg.cer
 
9、代码移植注意能力选项
移植第三方代码的时候注意能力选项,如获取手机IMSI号需要ReadDeviceData能力。
 
10、修改了rss文件后必须全部重新编译项目
修改rss文件后保存了需要重新编译项目,否则可能出现增量编译导致程序运行时加载字符串等资源出错。
 
11、以类对象作为成员变量
直接将类对象作为另外某个类的成员变量,而不是将该类对象指针作为类的成员变量,那么如果该类的构造函数是Protected/Private的,则新的对象无法成功构造!
12Symbian不支持全局变量
13RArray<Templete>定义时Templete的大小不能超过640
报告User 129错误, 127错误也是由RArray引起。
14、修改了类头文件后需要重新编译工程
15、获取手机剩余内存字节数
TMemoryInfoV1Buf info;
UserHal::MemoryInfo(info);
TInt freeMemory = info().iFreeRamInBytes;
 
16、控制用户输入长数字串
void CTestDlgDialog::PrepareLC(TInt aResourceId)
{
CEikDialog::PrepareLC( aResourceId );
// Pick up the Editor control from the dialog
CEikEdwin* control = static_cast<CEikEdwin*>(ControlOrNull(EMyQuery));
// Set the input mode
control->SetAknEditorInputMode(EAknEditorNumericInputMode);
// Restrict the other input modes
control->SetAknEditorAllowedInputModes(EAknEditorNumericInputMode);
}
 
17、播放wav声音文件
const TInt KSnapSoundId = 2;
CAknKeySoundSystem* iCameraSound;
iCameraSound =    static_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi())->KeySounds();
if (iCameraSound)
        {
        TRAPD(error, iCameraSound->AddAppSoundInfoListL(R_CAMERA_SNAP_SOUND));
        if ((error != KErrAlreadyExists) && (error != KErrNone))
            {
            User::LeaveIfError(error);
            }
        }
iCameraSound->PlaySound(KSnapSoundId);
//以下在rss文件中定义
#define KcameraSoundFile     "Z://system//sounds//digital//Camera1a_2_8kHz.wav"
#define KSnapSoundId 2
RESOURCE AVKON_SOUND_INFO_LIST r_camera_snap_sound
    {
    list =
         {
        AVKON_SOUND_INFO
           {
            sid = KSnapSoundId;
            priority = 45;
            preference = EAknAudioPrefCamera; // defined in avkon.hrh
            file = KCameraSoundFile;
            }
        };
    }
 
18、搜索可用的WLAN网络
#include <rconnmon.h>
void CWlanTest:: ListNetworksAndSignalL(CDesCArraySeg& aNetworks)
{
    _LIT(KNetInfo, "Network: %S/tSignal: %d");
    TBuf<32> netName;
    TBuf<100> line;
    RConnectionMonitor monitor;
    TPckgBuf<TConnMonNetworkNames> pkgNetworks;
    // establish connection with the monitor server
    monitor.ConnectL();
    // prepare leave clean-up
    CleanupClosePushL(monitor);
    TRequestStatus status;
    // get the list of available networks
    monitor.GetPckgAttribute(EBearerIdWLAN, 0, KNetworkNames, pkgNetworks, status);
    // suspend thread until the info is retrieved
    // production code should use active objects
    User::WaitForRequest( status ) ;
    // leave if the asynchronous method returned an error
    User::LeaveIfError(status.Int());
    // reset networks list
    aNetworks.Reset();
    // add retrieved networks to the list
    for(TUint i=0; i<pkgNetworks().iCount; i++)
    {
        netName.Copy(pkgNetworks().iNetwork[i].iName);
        line.Format(KNetInfo, &netName, pkgNetworks().iNetwork[i].iSignalStrength);
        aNetworks.AppendL(line);
    }
    // close server session
    CleanupStack::PopAndDestroy(&monitor);
}
Note:
- Link against: ConnMon.lib
- S60 3rd Edition-specific capability needed: NetworkServices
 
19、有没有播放基于流的视频的方法
参考CVideoPlayerUtility的使用,可以播放流内容,详情参考SDK


 

问题一:更换S60第三版的应用程序图标
在mmp文件中添加
START BITMAP Test_aif.mbm
  TARGETPATH                              /resource/apps
  HEADER                                  
  SOURCEPATH                              ../data
  source                                  c24 icon_lst.bmp
  source                                  c24 icon_lst_mask.bmp
  source                                  c24 icon_cxt.bmp
  source                                  c24 icon_cxt_mask.bmp
END
修改rss文件中LOCALISABLE_APP_INFO
icon_file = "//resource//apps//Test_aif.mbm";
在pkg 文件中增加
"C:/Symbian/9.1/S60_3rd_MR/Epoc32/data/z/resource/apps/Test_aif.mbm"-"!:/resource/apps/Test_aif.mbm"


问题二:模拟器无法启动
可能由于部分注册应用造成,尝试删除些*_reg.*

问题三:图片读取转化及base64解码问题
Base64使用TImCodecB64 类
图片注意DataNewL的数据必须作为成员变量,而不是局部变量,保证在转化之前数据未丢失


问题四:屏蔽HTTP接入点
步骤一:列举接入点
http://www.newlc.com/A-few-notes-about-the-CommDb.html
CCommsDatabase* CommDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
CleanupStack::PushL(CommDb);
CApSelect* ApSelect = CApSelect::NewLC(*CommDb, KEApIspTypeAll ,EApBearerTypeAll ,KEApSortUidAscending);
if (ApSelect->MoveToFirst())
{
   do{
          TUint uid = ApSelect->Uid();
          //put here your IAP stuff
     }while(ApSelect->MoveNext());
}
CleanupStack::PopAndDestroy(ApSelect);
CleanupStack::PopAndDestroy(CommDb);
步骤二:
//头文件
RHTTPSession iSession;
RHTTPTransaction iTransaction;
RConnection iConnection;
RSocketServ iSocketServ;
//构造中
User::LeaveIfError(iSocketServ.Connect());
User::LeaveIfError(iConnection.Open(iSocketServ));
iPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
iPref.SetIapId(IAPId);
iPref.SetBearerSet(KCommDbBearerPSD);
iPref.SetDirection(ECommDbConnectionDirectionOutgoing);
TInt ret;
if( ( ret = iConnection.Start(iPref)) != KErrNone)
{
//成功了
}
//打开会话成功
TRAPD(err, iSession.OpenL());
步骤三:将http绑定到指定SocketServ,在http Post中
http://www.forum.nokia.com/document/Forum_Nokia_Technical_Library/contents/FNTL/Using_the_HTTP_Client_API_with_RConnection.htm
User::LeaveIfError(iSocketServ.Connect());
User::LeaveIfError(iConnection.Open(iSocketServ));
iHttpSession.OpenL();
// Initiate connection
iConnection.Start(iStatus);
//...
RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
RStringPool pool = iHttpSession.StringPool();
// Attach to socket server
connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable()), THTTPHdrVal(iSocketServ.Handle()));
// Attach to connection
TInt connPtr = REINTERPRET_CAST(TInt, &iConnection);
connInfo.SetPropertyL(pool.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable()), THTTPHdrVal(connPtr));
// Open transaction...
iHttpTrans = iHttpSession.OpenTransactionL(iUri, *this, pool.StringF(HTTP::EGET, RHTTPSession::GetTable()));
RHTTPHeaders hdr = iHttpTrans.Request().GetHeaderCollection();

问题五:如何在Container中List控件和图片控件切换
void CMyContainer::Draw(TRect aRect)
{
CWindowGc& gc = SystemGc();
gc.SetPenStyle( CGraphicsContext::ENullPen );
gc.SetBrushColor( KRgbGray );
gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
gc.DrawRect( aRect );
if(iImage)
{
gc.Clear();
gc.BitBit(TPoint(0,0), iImage);
}
}
CCoeControl* CMyContainer::ComponentControl(TInt aIndex) const
{
switch(TInt nIndex)
{
case 0:
if(iImage)
iListBox->MakeVisue(EFalse);
else
iListBox->MakeVisue(ETrue);
}
}
void CMyContainer::ShowImage()
{
iImage = ***;
DrawNow();
}

问题六:关于手机上的Log日志
现在在手机上,用PC套件怎么只能看到手机的Data目录,C:/Logs/MyLogDir/Log.txt看不到
1)退出时读文件内容重写一个新文件到Data目录
2) 安装文件工具FExplorer,http://www.newlc.com/article.php3?id_article=70
3) 使用自定义log http://developer.uiq.com/forum/threa...=1120&tstart=0

问题七:中文字符处理问题
Java String 16 中文 ->> 客户端8bit接受 --> 转化为16bit Tbuf, OKOK!
客户端16bit Tbuf --> 转化为8bit发送 --> Java String接受为乱码?????
解决: 使用utf.h中的C**Convert函数转化,而不是使用Copy函数

问题八:对话框被覆盖
使用CAknInformationNote的R_AKN_INFORMATION_NOTE_WAIT 标志

问题九:制作mask图片
直接将文件存为黑白图片即可

问题十:如何保证让http接收完成后再进行后续操作
1)使用观察器
2)使用等待框

 

2007-10-08

1.通过Uid来获取应用程序的路径
TFileName f = EikAppUi( ).Application( )->AppFullName( );//得到当前应用的全路径名
TParse parse;
parse.Set( f,NULL,NULL );
parse.DriveAndPath( );//得到最终的绝对路径


2.给Symbian的模拟器换皮肤
各诺基亚手机皮肤下载列表:

3650 skin for the Series 60 SDK 
http://www.newlc.com/IMG/zip/N3650_EPOC_skip.zip

6600 Skin for the Series 60 SDK 
http://www.newlc.com/IMG/zip/Nokia6600_EPOC_Skin.zip

N-Gage Skin for the Series 60 SDK 
http://www.newlc.com/IMG/zip/Nokia_NGage_EPOC_Skin.zip

Nokia 6630 for the Series 60 SDK
http://www.newlc.com/IMG/zip/6630.zip

NGage Classic Skin for Series 60 V1.2 SDK
http://www.newlc.com/IMG/zip/6680.zip

NGage Classic Skin for Series 60 V1.2 SDK
http://www.newlc.com/IMG/zip/ngageskin.zip

使用说明:
先把你的当前模拟器的东西备份一下,再把皮肤应用上去,你需要备份。 Symbian/8.0a/S60_2nd_FP2_SC/epoc32/data 目录下面的 epoc.ini 和 epoc.bmp 文件 ,我的SDK是安装在 c:/ 下面,所以我备份了 C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/data/epoc.ini 和C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/data/epoc.bmp 两个文件 ,接着,把你下载到的皮肤中的文件 解压缩到这个目录下,再打开EPOC.INI文件 。。这个模拟器的配置文件 ,我们可能需要更改一些东西让模拟器正常运行, 找到 _EPOC_DRIVE_D  那一行 后面就是模拟器的路径了,当然,我们的路径要依照我们SDK安装的路径而设定,如果没有正确设置的话,模拟器可能会运行不正常或无法正常显示皮肤 。设置完后,打开你的模拟器就成了

手机里主题应用的路径是 C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/wins/c/System/SKINS

3.解决“无法解析的外部符号”错误
用 StringLoader::LoadLC()来读取资源的内容,但老是会失败,代码如下。
 
 #include <stringloader.h>
 #include <Symbian1.rsg>
 
 HBufC* TestStr=StringLoader::LoadLC(R_TEST_STR);

一编译就产生

Symbian1 error LNK2019: 无法解析的外部符号 "public: static class HBufC16 * __cdecl StringLoader::LoadLC(int,class CCoeEnv *)" (?LoadLC@StringLoader@@SAPAVHBufC16@@HPAVCCoeEnv@@@Z) ,该符号在函数 "public: void __thiscall CSymbian1Container::ConstructL(class TRect const &)" (?ConstructL@CSymbian1Container@@QAEXABVTRect@@@Z) 中被引用

SDK中说到,要用到StringLoader::LoadLC的话要在MMP文件中加入对commonengine.lib库的引用,打开 项目属性->链接器->命令行->附加选项 加入了 commonengine.lib 再编译。

4.枚举Symbian可用的字体列表
/**
* Second phase constructor. Initialise the font list.
*/
void CFvModel::ConstructL()
{
 TTypefaceSupport *typeface;
 iFontCount = iCoeEnv->ScreenDevice()->NumTypefaces();
 for( TInt i=0;i<iFontCount;i++)
 {
           typeface = new TTypefaceSupport;
       User::LeaveIfNull(typeface);
           iCoeEnv->ScreenDevice()->TypefaceSupport(*typeface,i);
           User::LeaveIfError(iFont.Append(typeface));
 }


5.关于Symbian平台路径问题
a.取得程序下的文件的绝对路径

#include <AknUtils.h>
TFileName pathname(_L("data.dat")) ;
CompleteWithAppPath (pathname) ;

这样这个 pathname 就会变成带有绝对路径的字符串了,


b.为了增强程序的可移植性,还是不要用绝对路径的好。我们可以在操作前获取当前设备的存储器路径。

例如:
根目录:
PathInfo::PhoneMemoryRootPath() 
存储图片文件目录:
PathInfo::ImagesPath()
存储安装SIS文件目录:
PathInfo::InstallsPath() 
存储声音文件目录:
PathInfo::SoundsPath()

如果想要定位MMC卡这种外加的存储器应该这样:

#include <PathInfo.h> 
TFileName path = PathInfo::MemoryCardRootPath();


c.如果一个路径是写死了,也可以通过下面的方式获得

方法一
_LIT(KBitmapFilename, "c://system//apps//test//xxx.mbm");
const TUint16 KMMCDriveLetter = 'e';
const TUint16 KROMDriveLetter = 'z';
// try 3 locations - application directory in C,E (memory card), and Z drive
TFileName imageLocation(KBitmapFilename);
TInt loadErr = iImageFlag->Load(imageLocation,useFullScreen);
// not found on C, try E & Z
if(loadErr != KErrNone)
        {
        imageLocation[0] = KMMCDriveLetter;    
        loadErr = iImageFlag->Load(imageLocation,useFullScreen);
        if(loadErr != KErrNone)
            {
            imageLocation[0] = KROMDriveLetter; // in emulator, apps usually reside on z
            loadErr = iImageFlag->Load(imageLocation,useFullScreen);
            }
        }


方法二
void GetFullPathName(TDes& aFileName)
{
    // Get default drive and path
    TParse parse;
    TFileName appPath;
    TBuf<5>      appDrive;
    parse.Set(CEikonEnv::Static()->EikAppUi()->Application()->AppFullName(), NULL, NULL);
    appPath.Copy(parse.DriveAndPath());
    appDrive.Copy(parse.Drive());

    // Parse the file name
    parse.Set(aFileName, NULL, NULL);
    if (parse.Drive().Length() == 0)
    {
        if (parse.Path().Length() == 0)
        { // Use default path and drive
            aFileName.Insert(0, appPath);
        }
        else
        { // Use default drive
            aFileName.Insert(0, appDrive);
        }
    }
}


6.Symbian下面访问INI文件的代码
void CMyIniFile::ReadIniFile()
   CDictionaryStore* iniFile = iApplication->OpenIniFileLC(CCoeEnv::Static()->FsSession());
   if (iniFile->IsPresentL(aUid))
   {
      RDictionaryReadStream stream;
      stream.OpenLC(*iniFile,aUid);
      iModeType = stream.ReadInt32L();
      stream >> iTextBuf;
      CleanupStack::PopAndDestroy();
   }
   else
   {
      iModeType = 0; 
      iTextBuf.Copy(_L(""));
   }
   CleanupStack::PopAndDestroy();
}
void CMyIniFile::WriteIniFile()
{
   CDictionaryStore* iniFile = iApplication->OpenIniFileLC(CCoeEnv::Static()->FsSession());
   RDictionaryWriteStream stream;
   stream.AssignLC( *iniFile, aUid );
   stream.WriteInt32L(iModeType);
   stream << iTextBuf;        //要写的内容
   stream.CommitL();
   CleanupStack::PopAndDestroy();
   iniFile->CommitL();
   CleanupStack::PopAndDestroy();
}

在Applocation类里冲在 OpenIniFileLC 函数即可:
 CDictionaryStore* OpenIniFileLC(RFs& aFs) const;

 CDictionaryStore* CYouSymbianApp::OpenIniFileLC(RFs& aFs) const
  {
     return CEikApplication::OpenIniFileLC(aFs);
  }

读取ini文件数据的操作
HBufC* tstr;
TUint aInd=20;
TUid testuid={0x0bdf1365};//定义文本标识, 这个相当于字段名,是一个标识
if (ReadIniFile(testuid,tstr,aInd)) { //处时tstr为读出的字段值了
... 
}

写进ini文件数据的操作
CYouSymbianApp::HandleCommandL(...)
....
case EEikCmdExit:
            {
            _LIT(KBentionText,"bention");//定义文字常量 相当于ini中的字段值
            HBufC* str=KBentionText().AllocLC();//转换为HBUfC16位
            TUint aInd=20;//定义要写入文本的长度
            TUid testuid={0x0bdf1365};//定义文本标识 相当于ini中的字段名
            WriteIniFile(testuid,str,aInd);//写入        
            Exit();
            break;
            }

.....


7.Symbian平台的一些指针调用处理方式
在APPUI类里定义了一个成员变量:imap,在构造函数里new 出来,并load好,
imap = new( ELeave )CFbsBitmap;
User::LeaveIfError( imap->Load( _L("c://system//apps//TestStaP//mymaps.mbm"),EMbmMymapsColor1 ) );
....
//但在类里如果试图改变CAknTitlePane的图标:
tp->SetPicture(imap); 
//在析构函数里用delete
delete(imap);

程序退出会发生错误。
如果这样写:

CFbsBitmap*  ptemp =  new( Eleave )CFbsBitmap;
User::LeaveIfError( imap->Load( _L("c://system//apps//TestStaP//mymaps.mbm"),EMbmMymapsColor1 ) );
....
Tp->SetPicture( ptemp );

注意:这里的ptemp根本没有delete,程序退出不会发生错误。
所以可以判定:当把一 个CFbsBitmap的指针通过SetPicture传递到 CAknTitlePane的时候,CAknTitlePane内部负责delete这个图标的内存,所以上面我们在析构函数里delete,然后CAknTitlePane又delete就有问题 在DEBUG的时候看堆内存的大小也的确如此, CAknTitlePane全权负责它图标内存的释放. 

 

你可能感兴趣的:([转]总结开发中的19个问题+若干问题)