手机来电通核心模块——归属地数据库设计(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)


相关推荐

  • Commit message 和 Change log 编写指南

    Commit message 和 Change log 编写指南

  • MLP综述

    MLP综述MLP整体思路反向传播算法梯度下降算法

  • usb转485驱动

    usb转485驱动usb转485驱动是官方提供的一款USB驱动,本站收集提供高速下载,用于解决USB接口不能正常识别,无法正常使用的问题,本动适用于:WindowsXP/Windows7/Windows8/Windows1032/64位操作系统。有需要的朋友可以来本站下载安装。usb转485驱动http://www.equdong.net/qtrj/usbdrv/16155.html…

  • 用python实现植物大战僵尸(游戏截图+动态演示+源码分享)「建议收藏」

    用python实现植物大战僵尸(游戏截图+动态演示+源码分享)「建议收藏」大家好,我是梦执,对梦执着。希望能和大家共同进步!下面给大家带来python实现植物大战僵尸的的源码分享,只含有冒险模式。截图+动态演示+源码分享游戏截图动态演示源码分享state/tool.pystate/constants.pystate/main.py主执行文件main.py游戏截图动态演示源码分享state/tool.pyimportosimportjsonfromabcimportabstractmethodimportpygameaspg..

  • 服务器安全-使用ipset 和iptables禁止国外IP访问[通俗易懂]

    服务器安全-使用ipset 和iptables禁止国外IP访问[通俗易懂]服务器遭受ddos攻击,发现发部分IP来自国外……IPSET安装yuminstallipset//安装ipsetipsetcreatechinahash:nethashsize10000maxelem1000000//创建地址表ipsetaddchina172.18.0.0/16ipsetlistchina获取国内IP地址段并导入viipset_china.sh#!/bin/bashrm-rfcn.zonewget..

  • linux如何停掉计划任务,Linux系统的任务计划

    linux如何停掉计划任务,Linux系统的任务计划Linux系统的计划任务Linux系统运维工程师大部分管理工作都是通过定期自动执行某一脚本来完成的。Cron功能很重要,牢记!!!计划功能Crontab:-u:(user)表示指定某个用户,不加-u则为当前用户-e:表示指定计划任务-l:(list)表示列出计划任务-r:(remove)表示删除计划任务#crontab-e011005063echo”ok”>/root/cr…

发表回复

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

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