目标手机软件
流量多少 程序统计
模仿功能:流量统计
模仿对象:手机QQ 2008
模仿进度:第二期
开发平台:Java平台
3G来了,可移动、联通收费还是按流量计算,像手机QQ 2008这种需要网络通信的程序就有必要配备流量统计的功能,方便用户实时掌握了流量使用的状况。
流量统计功能设计思路
在手机网络软件使用中,需要产生一定的网络流量,该流量指手机网络软件的上传和下载流量之和。而现在移动运营商在手机上网过程中,都是按照流量计算上网费用的,例如中国移动的自由套餐计费标准是0.01元/KB。
由于使用手机网络软件将产生流量费用,所以手机网络软件产生的流量将是用户比较关心的一个问题,所以在手机网络软件中加入流量统计功能将是一个迫切的选择。
按照手机上网网络流量的定义,该流量包含上传流量和下载流量两部分,所以在软件中加入流量统计功能的思路就是获得手机软件发送给服务器程序的流量,以及服务器程序反馈给客户端的流量,然后将两个流量的数据求和即可。
在本文的设计流量统计功能(该功能模块下载地址:http://www.shudoo.com/bzsoft)中,首先设计了一个简单的界面,实现接收用户输入网址以及发送的内容,然后启动网络线程进行网络数据的发送,在数据发送完毕以后,统计发送产生的流量数据,然后接收服务器端的反馈数据,在服务器端反馈数据接收到以后,统计服务器反馈的数据流量,最后将本次网络通讯产生的流量显示到界面上,并显示累计的流量在界面类中(图1)。
通过HTTP统计流量
目前主流的手机联网的方式是HTTP,下面介绍如何统计使用HTTP协议进行网络编程时的流量统计。统计流量,就是统计每次完整的通信,即客户端发送的流量以及客户端获得的服务器端的反馈流量。
小知识:当前手机联网的方式主要有HTTP(超文本传输协议)方式和Socket(套接字)方式两种。HTTP方式即在手机中实现以HTTP协议的方式实现连接,在传输数据时使用HTTP协议,而Socket方式在传输时使用自定义的协议格式。虽然两者方式在上层的实现区别很大,但是底层都需要加入一些传输控制数据从而实现传输。
例如,访问数动连线(http://www.shudoo.com/bzsoft),会产生固定流量和动态流量,两者之和就是总的流量,也就是统计固定数据与动态数据之和。固定流量就是根据HTTP协议规定必然产生的数据,一般数据大小是固定的。动态流量是用户访问数动连线时实时产生的数据,数据不固定,是统计的核心。
要统计动态流量,就要用到“数组名.length”,利用它可以快速统计出数组的长度,这个长度也就是动态数据。把每次产生的动态数据相加就是总的动态流量。把总的动态流量和固定流量相加就是总的流量。
流量统计功能设计步骤
第一步:创建项目
启动Eclipse环境,选择“File→New→J2ME MIDlet Suit”,设置项目名称为“FlowCapacityCount”,并一路选择“Next”, 完成项目的建立。然后新建一个J2ME入口类,选择“File→New→J2ME MIDlet”,并设置名称为“FlowMIDlet”,点击“Finish”。创建项目的代码下载地址是http://www.shudoo.com/bzsoft。
第二步:设计界面
选择“File→New→Class”,并设置名称为“FlowForm”,点击“Finish”完成界面类的创建。然后在该界面中编写界面实现代码和启动网络通信线程代码。关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):
//初始化流量对象
siSendFlow = new StringItem("本次发送流量(字节):","0");
siReceiveFlow = new StringItem("本次接收流量(字节):","0");
siTotalSendFlow = new StringItem("总计发送流量(字节):","0");
siTotalReceiveFlow = new StringItem("总计接收流量(字节):","0");
append(siSendFlow);
append(siReceiveFlow);
append(siTotalSendFlow);
append(siTotalReceiveFlow);
第三步:设计网络通信类
选择“File→New→Class”,并设置名称为“HttpThread”,点击“Finish”完成该类的创建。然后在该类中实现网络通信代码的编写以及调用流量统计方法实现统计。关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):
其中网络连接部分的代码如下:
//设置头信息
hc.setRequestProperty("name", "value");
//发送数据
os = hc.openOutputStream();
os.write(sendData);
int systemDataLen = 3 + 1 + url.length() + 1 + 7 + 1;
//头信息内容为name:value,一个结束的换行符,总计11
systemDataLen += 11;
//统计总流量
int sendDataLen = FlowCount.countSendFlow(sendData, systemDataLen);
//显示到界面
flowForm.setSendFlow(sendDataLen);
//接收数据
is = hc.openInputStream();
//获得流数据
StringBuffer s = new StringBuffer();
//读取实体数据部分的第一个字节
int data = is.read();
//循环读取后续数据
while(data != -1){
//添加到s中
s.append((byte)data);
//继续读取下一个
data = is.read();
}
//统计接收流量
int receiveDataLen = FlowCount.countReceiveFlow(hc, s);
第四步:设计流量统计类
选择“File→New→Class”,并设置名称为“FlowCount”,点击“Finish”完成该类的创建。然后在该类中实现发送流量统计的方法和接收数据流量的统计方法。关键代码如下所示(完整代码下载地址:http://www.shudoo.com/bzsoft):
//预估响应行数据量为10字节
int responseLineLen = 0;
//统计头信息数量
int headLineLen = 0;
//遍历头信息
String headName = null;
String headValue = null;
try{
//获得响应信息
String responseStr = hc.getResponseMessage();
//统计响应行流量
responseLineLen = 7 + 1 + 3 + 1 + responseStr.length() + 1;
for(int i = 0; ;i++){
//依次获得头信息名称
headName = hc.getHeaderFieldKey(i);
//如果返回值为null,则代表结束
if(headName == null){
break;
}
//根据头信息名称获得头信息数值
headValue = hc.getHeaderField(headName);
//统计头信息流量,这里的2指每个头信息后换行
//字符1字节以及名称和值之间间隔冒号字符1字节的长度和
headLineLen += headName.length() + headValue.length() + 2;
第五步:运行程序
在Eclipse主界面左侧的“Package Explorer”中,选中项目源代码FlowMIDlet.java,单击鼠标右键,选择“Run As→Emulated J2ME Midlet”即可运行程序(图2)。
读者反馈
开发QQ群:想参照上期文章模仿设计,可我在Eclipse中怎么也没有找到J2ME项目,这是为什么?
小编:使用Eclipse开发J2ME程序,需要事先安装插件EclipseMe,该插件的下载地址是http://www.eclipseme.org,下载后点击“Help—Software updates”菜单进行安装。安装完成后就可以建立J2ME项目了。
开发QQ群:看了上期文章,想问问关闭振动具体应该怎么做?
小编:和控制背景灯一样,控制振动功能也只支持特定的手机,在标准的J2ME MIDP API中未实现关闭振动的功能。关闭振动功能手机API没有提供,需要在逻辑上实现。例如程序中加入一个控制振动的boolean变量,当变量不成立时,不执行手机振动的代码即可。
开发QQ群:我按照贵报讲解的原理,编写了实际的网络程序,在手机上每次进行网络通信都会弹出一个提示框,如何去掉网络的信息提示框呢?
小编:如果需要在手机上运行网络程序时,去掉该提示框,一般有两种方法。方法1:手机用户设置该程序。例如在Nokia手机中的操作是:选择该程序,然后选择“操作-应用软件接入-通讯-网络”,选中“仅第一次询问”,这样只在开始的第一次弹出提示框,以后就不在提示了。方法2:对该程序进行数字签名。一般公司才会购买数字证书,然后在程序发布以前对该程序进行数字签名。
开发QQ群:请问手机进入节能模式以后,如何编程实现恢复到正常模式呢?
小编:在上期文章中,文章只介绍了节能模式的实现,其实在源代码中包含了恢复到正常模式时的代码实现。恢复到正常模式时的原理实现为:将屏幕灯调整到正常亮度、开启振动等功能,并且将非核心的网络通信指令继续添加到网络线程中即可实现。
读者提问:我用J2ME调用函数发短信,每次都弹出确认提示,必须点了“确认”才能发送,这是为什么?我不想让用户知道我的程序在往外发短信,该怎么解决?
张凯:这是Java的安全机制,保证软件不做不该做的事情,比如在用户不知情的情况下恶意发送短信浪费用户话费,所以每次调用发送函数时都要求用户确认一下。如果你的发送请求是合理的,用户一般会同意,所以对程序不构成影响,不必过分在意此问题。
如果一定要绕过这种机制,就要去向官方申请认证,购买数字证书了,确认你的软件安全后才能给你饶过安全机制的权限。在这里提醒广大开发者,要时刻把用户利益摆在首位,编程技术是一把双刃剑,切勿用它来制造恶意软件、流氓软件甚至病毒,这种行为将会给用户带来许多麻烦,也会遭到大家的唾弃。
读者问题:我想用Socket方式穿越CMWAP网关,但是CMWAP只支持HTTP方式通信,请问如何实现呢?
你是手机编程的高手吗?你能解答上面这位读者的疑问吗?不要犹豫,来我们这里展示一下你的风采吧,来信请发到pcw-chendx@vip.sina.com(也可以给我们发送问题)。
(河南 陈跃峰)