手机来电通核心模块——归属地数据库设计(Winsym原创)「建议收藏」

手机来电通核心模块——归属地数据库设计(Winsym原创)「建议收藏」说到Symbian,确实让人头痛。不仅开发平台和SDK版本众多,难以选择,而且对程序员确实要求很高,光是SymbianC++的熟悉就要花上很长时间,更麻烦的是测试和调试。模拟器只能提供一部分功能,和电话通信有关的全部要在真机上测试。很多时候,在模拟器上能跑的代码,放到真机上就不行了,这其中的心酸想必开发过得朋友深有体会。小弟我因为工程实践项目的要求,和几位嵌入式的高手一起搞了Symbian来电通项目。其实来电通项目已经有很多人做了,比较有名的是CallMaster和柳丁,但是这方面的关键技术和源码至今没有

大家好,又见面了,我是你们的朋友全栈君。

 

说到Symbian,确实让人头痛。不仅开发平台和SDK版本众多,难以选择,而且对程序员确实要求很高,光是Symbian C++的熟悉就要花上很长时间,更麻烦的是测试和调试。模拟器只能提供一部分功能,和电话通信有关的全部要在真机上测试。很多时候,在模拟器上能跑的代码,放到真机上就不行了,这其中的心酸想必开发过得朋友深有体会。

小弟我因为工程实践项目的要求,和几位嵌入式的高手一起搞了Symbian来电通项目。其实来电通项目已经有很多人做了,比较有名的是CallMaster和柳丁,但是这方面的关键技术和源码至今没有人公开,这在很大程度上增加了这个项目的难度,我们只好白手起家,也算是一次真正的项目历练(因为很多项目的关键技术和源码一般都不会给你,只有自己研究,^_^)。我在项目中负责两个核心模块的实现。一个是监听模块,另一个就是归属地查询模块。我把这一个多月的成果全部总结了一下,写成技术文章,提供给大家参考。希望想从事这方面开发的朋友能有一些借鉴作用,少走一些弯路,我就感到非常欣慰了。

以下是最核心的部分,归属地数据库的设计和实现,文中可能存在不少问题,欢迎高手们指正,向Symbian高手学习。

 

说明,我们的开发环境是Carbide C++

SDK s60 FP2 CW

 

 

归属地查询模块

归属地模块的主要功能可以划分为两个部分:一是当监听模块获取号码后,自动查找归属地数据库;二是由用户在本地自由查找,可自由选择组合(手机,固话等归属地)。但是两个功能的核心和难点都在于归属地数据库的建立,下面结合图例重点阐述。

整个数据库的建立大致分为三个步骤,见图示:

 

 

 数据库建立

 

一、原始数据的采集,整理。这一步骤主要从网上下载我国目前手机号码的归属地数据库原始数据,我们选用的是access格式的原始数据,但其只有一张表且存在大量冗余信息,原始数据截图如下:

 原始数据表

 二、对原始数据进行分析和总结不难看出,citycardtype字段中存在大量冗余信息。例如:北京市和北京联通GSM卡被存取了很多次,造成了大量的重复。所以,我们必须要设计出一种优秀的表结构格式(在满足功能的前提下,最大限度地消除冗余信息,采用数据库设计相关理论,达到3范式设计要求)。共设计四张表:

1 Phone

2 CityName

3 CardName

4 Zone

 

具体字段如下:

  

 

表名

字段名

类型

长度

说明

Phone

number

     int

 

手机号码段,主码唯一标示

 

cityid

  int

 

归属城市编号

 

cardid

  int

 

卡类型编号

CityName

cityid

int

 

归属城市编号,主码

 

cityname

text

50

归属城市名称

CardName

cardid

int

 

卡类型编号,主码

 

cardname

text

50

卡类型名称

Zone

zonecode

text

10

二级城市归属地区号 联合主码

 

zonename

text

50

二级城市归属地名称 联合主码

 

 

在实际应用过程中,查找效率和安全问题是我们必须要考虑的两个主要问题,为此我们采取了以下解决方案:

对于查找效率问题,我们采用了建立索引机制。由于Phone表中的记录的规模(大约有15万条记录),为了提高查找效率,对表Phone中的字段numberCityNamecityid字段,CardNamecardid字段分别建立索引。相应Sql语句可参考以下:

CREATE unique INDEX numIndex ON Phone(number)

CREATE unique INDEX cardidIndex ON CardName(cardid)

CREATE unique INDEX cityidIndex ON CityName(cityid)

 

对于安全问题,我们使用了S60 2nd DBMS专有的权限加密机制,相当于SQL Server数据库的登录密码,最大限度的保护数据库访问的安全和数据库设计专利。具体实现可参考以下代码片段:

// Open the contacts database using the Encrypted format

    _LIT(KPassword, “I Fu le you”);

    //useing decrypted database

    CSecurityBase* securityBase = Security::NewL ();

    securityBase->SetL (TPtrC (), KPassword); //Set the password for decryption

    //Get the key

    CSecurityDecryptBase* decryptBase = securityBase->NewDecryptL (TPtrC8 ());

    CleanupStack::PushL (securityBase);

    User::LeaveIfError ( myDatabase.Open (myDbs, KFile, TPtrC (), decryptBase,myDatabase.EReadOnly));

 

为了方便Sql脚本的提取,以上设计均在SqlServer2000数据库中完全实现。四张表之间的关系可参考以下截图:

 

 数据库表关系

 

三、最后一步是将SqlServer2000平台上的归属地数据库顺利地导入到Symbian专用的 DBMS中。这里存在两个难点,一是Symbian数据库的建立,API的使用;二是海量数据的导入。

对于第一个问题,Symbian为我们提供了两组API
1. RDbStoreDatabase 提供了专有的创建和打开数据库的接口,这样的数据库是不能共享的,数据库以文件的形式存在,所以它又称为客户端访问。
2. RDbNamedDatabase 提供了用名字和格式标识的创建和打开数据库的接口,这个类允许客户端(专有)和服务的共享数据库访问。

考虑到程序的兼容和开发的方便,我们使用的是RDbNamedDatabase,他可以轻松地创建我们想要的数据库,并利用Symbian支持的SQL子集,进行相应的建表,建立索引,查询等操作,完成相应功能需求。代码片段如下:

RFs myDbs;

    // handle for our database

    RDbNamedDatabase myDatabase;

    // we have to connect to the DBMS server first

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

    myDbs.MkDirAll(KDirName);

    //handles use the cleanup stack

    CleanupClosePushL(myDbs);

    _LIT(KPassword, “I Fu le you”);

    //useing encrypted database

    CSecurityBase* securityBase = Security::NewL();

    securityBase->SetL(TPtrC(), KPassword); //Set the password for encryption

 

    // Get the key

    CSecurityEncryptBase* encryptBase = securityBase->NewEncryptL(TPtrC8());

   

    User::LeaveIfError( myDatabase.Create(myDbs,KFile,TPtrC(),encryptBase));

    //handles use the cleanup stack

    CleanupClosePushL(myDatabase);

   

    _LIT(KSQLCreatePhone, “CREATE TABLE Phone(number  integer ,cityid  unsigned smallint,cardid  unsigned smallint)”);

    _LIT(KSQLIndex,”CREATE unique INDEX numIndex ON Phone(number) “);

    _LIT(KSQLIndex1,”CREATE unique INDEX cardidIndex ON CardName(cardid) “);

    _LIT(KSQLIndex2,”CREATE unique INDEX cityidIndex ON CityName(cityid) “);

   

    _LIT(KSQLCreateCardName,”Create Table CardName(cardid unsigned smallint,cardtype varchar)”);

    _LIT(KSQLCreateCityName,”Create Table CityName(cityid unsigned smallint,cityname varchar)”);

    _LIT(KSQLCreateZone,”Create Table Zone(zonecode varchar,zonename varchar)”);

   

    //create Master tables

    User::LeaveIfError(myDatabase.Execute(KSQLCreatePhone));

    User::LeaveIfError(myDatabase.Execute(KSQLCreateCardName));

    User::LeaveIfError(myDatabase.Execute(KSQLCreateCityName));

    User::LeaveIfError(myDatabase.Execute(KSQLCreateZone));

 

    User::LeaveIfError(myDatabase.Execute(KSQLIndex));

    User::LeaveIfError(myDatabase.Execute(KSQLIndex1));

    User::LeaveIfError(myDatabase.Execute(KSQLIndex2));

 

对于第二个问题,我们采取的方法是,将所有Sql Server2000数据库各表格的数据,全部转成sql脚本,并利用Symbian提供的文件系统相关的API,读取每一行sql语句并执行,最终在电脑模拟器上生成数据库文件dbms.db。经实际操作,这种方法比在手机上生成可以大大节省数据库生成时间,效果显著。相应的sql脚本截图如下:

 

 数据sql脚本

 

读取的代码片段如下:

RFile myfile;

    //open file with RFile

    User::LeaveIfError(myfile.Open(myDbs,KFileName1,EFileRead));

    CleanupClosePushL(myfile);

   

    //Reads  single lines of text to or from a file

    txt.Set(myfile);

    TBuf16<60> textsql;

    //TDesC16 sqlRow;

    while(txt.Read(textsql) != KErrEof  )

    {

       //console->Printf(textsql);

       User::LeaveIfError(myDatabase.Execute(textsql));

       //console->Printf(_L(“/n”));

       textsql.Delete(0,textsql.Length());

    }

全部完成后,就可以利用SQL语句查询了,哈哈,好爽啊!

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163156.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • python程序设计实践题EXP01-求圆面积、温度转换和绘制五角星

    python程序设计实践题EXP01-求圆面积、温度转换和绘制五角星一、计算圆的面积思路:根据圆面积的计算公式进行求解。程序代码:1importmath2radius=253area=math.pi*radius**2#**是幂运算4p

  • vs实现用户注册登录_用户注册和登录的实现

    vs实现用户注册登录_用户注册和登录的实现publicstaticUserInfoGetUser(stringname,stringpwd){//填写搜索姓名和密码的sql语句stringsql=string.Format(“select*fromUserInfowhereLoginName='{0}’andPassword='{1}'”,name,pwd);DataTabledt=DBHelper.ExcuteTab.

  • 堆和栈的区别

    堆和栈的区别转:https://my.oschina.net/aofe/blog/267882堆和栈的区别:·1>堆空间的内存是动态分配的,一般存放对象,并且需要手动释放内存。需要程序员自

  • initramfs-kernel_deepin initramfs

    initramfs-kernel_deepin initramfsOtherlanguages:一些基于Linux的计算机系统系统需要一个intramfs才能正常启动。在本指南中,将说明initramfs的概念,以及如何正确地创建和管理initramfs。Initramfs是什么介绍许多用户是没有必要关心initramfs系统的。他们的系统使用了简单的分区方案,而且没有奇奇怪怪的驱动程序或者设置(如加密的文件系统),因此Linux内核完全能够把…

  • python进阶(4)文件操作[通俗易懂]

    python进阶(4)文件操作[通俗易懂]文件操作文件操作主要包括对文件内容的读写操作,这些操作是通过文件对象实现的,通过文件对象可以读写文本文件和二进制文件open(file,mode='r',buffering=-

  • 进程调度有可抢占 哪种开销更大_什么时候用多线程什么时候用多进程

    进程调度有可抢占 哪种开销更大_什么时候用多线程什么时候用多进程线程调度为什么比进程调度更少开销?在对比进程调度与线程调度的开销前,我们需要明白两点:进程与线程的差异任务调度的开销进程与线程的差异我们首先要明白,线程和进程有什么关系?从概念上来讲,线程是进程的一部分,只是任务调度相关的部分,所以我们才说,“线程是调度的最小单位”。进程拥有着资源,这些资源不属于某一个特定线程,因为所有线程共享进程拥有的资源,所以我们才说,“进程是资源分配的最小单位…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号