本人是矿大学信息安全的大三狗,混了两年日子之后幡然醒悟决定做些自己早就想做的事情,学校的联通宽带是按时长收费的,但是每次查询已用时长和所扣费用步骤都十分的繁琐,大二的时候都想着要自己做一个APP来帮助大家减少这些繁琐的步骤,终于拖了半年多才开始做。从只有一点Java基础到最后做出来可用的APP只用了一个星期的时间,以下是干货内容。

我们最先要上的是成果图,还有在学校发的帖子:http://tieba.baidu.com/p/4233858160?pid=81256661492&cid=0#81256661492

首先我们先看一下正常的查询步骤,第一步,登陆网上营业厅,还要输入繁琐的宽带账户,的确是比较麻烦。

第二步以及以后,反正就是点点点,就不讲解了。

(加载比较慢不好意思,一月份因为没有用所以没有数据,就拿去年12月的代替吧。)

然后我要怎么做呢,首先我知道应该用网络爬虫,我就百度怎么用Java写一个爬虫,然后知道了服务器传输数据都是用的post和get方法,然后在浏览器里面使用合适的工具来将想要的包抓取一下,我学习使用的是火狐浏览器的插件firebug,真的是非常好用的工具推荐给大家。

至于在实际动手写的过程中走过许多许多弯路,最后真正实现了以后才发现其实是很简单。以下开始讲电脑上Java的具体实现。

先讲一下最基本的原理,我们用一个httpclient包中的httpclient帮我们处理cookies,cookies就是一个网站的通用登录凭证,一次登录凭借cookie访问其他页面不用再次登录。我们首先在登录界面登录,再访问查询的页面,应该就能得到想要的数据,这是基本思想。

首先我们先观察登陆的时候是怎么给服务器发送数据的。

其中几个参数意义不明,我换其他账号用相同的参数get过去是一样的,所以我们构造一个url传送给服务器进行验证即可。

以下是Java代码中构造的一段代码(Android中自带的org.apache包中好像没有这个构造函数了,所以还是直接写一个url上去比较方便。)

/**

*登陆

*生成uri用get方法传递过去即可

*/

URIuri=new URIBuilder()

.setScheme("https")

.setHost("uac.10010.com")

.setPath("/portal/Service/MallLogin")

.setParameter("callback","jQuery17204165900954174946_1450622603532")

.setParameter("redirectURL","http%3A%2F%2Fwww.10010.com")

.setParameter("userName","051602198839")//用户名

.setParameter("password","xxxxxx")//密码

.setParameter("pwdType","01")

.setParameter("productType","04")

.setParameter("redirectType","01")

.setParameter("areaCode","350")

.setParameter("arrcity","%E5%BE%90%E5%B7%9E")

.setParameter("_","1450622609168")

.build();//生成想要的URL

HttpGethtg0=new HttpGet(uri);

接下来我们再看我们想要的数据是怎么来的。

很明显是通过一系列的post方法从服务器的response中以json的形式返回的。其中flowfee就是费用,totalflow时长。

这里有一个问题难住了很久,百度了好久最后才实验出来一个解决方法,那就是我直接模拟这个post包向服务器的地址post数据并没有获得想要的返回,而是提示500错误,最后的解决办法是这样的。从上图可以看到我们psot过去的还有很多不明意义的东西,我点开都看了看完全不知道是干嘛的,但是事实就是我们把前面那几条不明意义的数据向服务器post过去后就可以正常返回我们想要的数据了。至于应该怎么解析json之类的小问题百度一下就好啦。

在本文最后会附上电脑的Java源码,记得要导入几个jar包才可以运行。

接下来就是神一般的三天安卓速成大法了,我在网上找了几本Android开发教程,从目录里找我需要用到的章节,只学需要用到的地方,所以才能只用了三天就写出来这个安卓程序。实际上也很简单,只有一个Activity,布局上直接拖得控件也没做什么设计。真正的难点是多线程的使用。因为在Android中需要处理网络任务的时候不能再主线程中处理,主线程只能进行UI的处理。所以在如何使用handler这方面百度了很多很多例子,最终成功的实现了多线程的编写。除了最主要的抓取数据的程序外,剩下就是一些记住密码啊,从系统中读取当前日期之类的小地方的细节,最终写出来了这个APP并且先给同学试用了一下,最终上传到百度云通过贴吧和空间稍微推广一下希望能够帮到更多的同学。

其实做完之后自己的感想就是,现在网络上资源十分丰富,也有各种前辈写的各种blog能够给你提供详细的讲解和实例,你真正需要挑战的是自己的耐性。能不能够静下心来决心去做好这件事,然后在试错的道路上坚持下来一直走到你最终找到了正确的道路的那一刻。

我一开始不知道httpclient,试图自己处理cookies,下载安卓的开发软件和环境也是个挑战,后来Android开发的时候导入jar包也出了很多问题(最后用的本身SDK带的org.apache包),调试的时候不知道断点怎么用的,多线程试图模仿着写了3个都没能用,还有好多乱七八糟的问题,但是现在都想不起来了,只是记得当时自己哪怕很烦,哪怕半夜断网我开着流量下sdk,我都没有放弃,可能总共花了5,60个小时做这个事,其中估摸着除了十个小时是在做正确的事,其他时候都是在做无用功,但是我还是做出来了。

这是我上大学以来做出的最有成就感的事情了,完全独立的解决(好吧,Android调试我问了问做过开发的同学)一个问题,真的很有成就感。这个算是教程也算是心得的东西早就想写了,但是自己又犯了拖延症一直到放假都没有写出来。现在发出来望各位大学迷茫的it狗们共勉。

附:

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
importorg.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import net.sf.json.JSONObject;
public class HelloWorld {public static void main(String[] args) throws Exception{// TODO Auto-generated method stubCloseableHttpClienthttpclient = HttpClients.createDefault();/***登陆*生成uri用get方法传递过去即可*/URIuri=new URIBuilder().setScheme("https").setHost("uac.10010.com").setPath("/portal/Service/MallLogin").setParameter("callback","jQuery17204165900954174946_1450622603532").setParameter("redirectURL","http%3A%2F%2Fwww.10010.com").setParameter("userName","051602198839")//用户名.setParameter("password","xxxxxx")//密码.setParameter("pwdType","01").setParameter("productType","04").setParameter("redirectType","01").setParameter("areaCode","350").setParameter("arrcity","%E5%BE%90%E5%B7%9E").setParameter("_","1450622609168").build();//生成想要的URLHttpGethtg0=new HttpGet(uri);HttpResponseresponse0 = httpclient.execute(htg0);System.out.println(htg0.getURI());System.out.println(response0.getStatusLine());Stringconfirm = EntityUtils.toString(response0.getEntity(),"utf-8");if (confirm.contains("resultCode:\"0000\""))      System.out.println("登陆成功");   /** 依次向服务器post* 前面这些貌似必须先请求响应,会自动生成cookie* 均为不带post实体内容的*/HttpPostpostU=new HttpPost();List<String>postUri=new ArrayList<>();postUri.add("http://iservice.10010.com/e3/static/check/checklogin/?_=1450697102496");postUri.add("http://iservice.10010.com/e3/static/common/info?_=1450697103996");postUri.add("http://iservice.10010.com/e3/static/header");postUri.add("http://iservice.10010.com/e3/static/query/newsAssistant/search?_=1450697104007");postUri.add("http://iservice.10010.com/e3/static/check/checklogin?_=1450697104017");postUri.add("http://iservice.10010.com/e3/static/check/checklogin?_=1450697104361");for(Stringpost:postUri){URIpoU=new URIBuilder(post).build();postU.setURI(poU);response0=httpclient.execute(postU);System.out.println(response0.getStatusLine());System.out.println("执行完成");Stringresult0=EntityUtils.toString(response0.getEntity(),"utf-8");System.out.println(result0);}System.out.println("准备完成");/** 最后post能够得到想要数据的那条*/HttpPosthtp=new HttpPost("http://iservice.10010.com/e3/static/query/callFlow?_=1450697104585&menuid=000100030004");List<NameValuePair>parameters =new ArrayList<NameValuePair>();//请求体parameters.add(new BasicNameValuePair("pageNo","1")); parameters.add(new BasicNameValuePair("pageSize","20"));parameters.add(new BasicNameValuePair("beginDate","2015-12-01"));//parameters.add(new BasicNameValuePair("endDate","2015-12-25"));UrlEncodedFormEntity urlEntity = newUrlEncodedFormEntity(parameters,"UTF-8"); htp.setEntity(urlEntity); CloseableHttpResponseresponse1 =httpclient.execute(htp);System.out.println(response1.getStatusLine());String result = EntityUtils.toString(response1.getEntity(),"utf-8");System.out.println(result);JSONObject ob = JSONObject.fromObject(result);String totalflow=ob.get("totalflow").toString();System.out.println(totalflow);} }
附2(Android源码):
package com.example.sunyang.myapplication;import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MulticastSocket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class MainActivity extends AppCompatActivity {TextView res;HttpClient httpClient;SharedPreferences preferences;SharedPreferences.Editor editor;/*主线程中构造handler,更新UI的请求用sendMessage发送,在下面完成.*/Handler handler=new Handler(){public void handleMessage(Message msg){if (msg.what==0x123){res.append(msg.obj.toString()+"\n");}}};public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);httpClient=new DefaultHttpClient();preferences=getSharedPreferences("userInfo",MODE_WORLD_READABLE);editor=preferences.edit();res=(TextView) findViewById(R.id.result);Button bn=(Button) findViewById(R.id.button);final EditText username=(EditText) findViewById(R.id.userName);final EditText password=(EditText) findViewById(R.id.password);final CheckBox checkBox=(CheckBox) findViewById(R.id.checkBox);if (preferences.getBoolean("AUTO_ISCHECK",true)){username.setText(preferences.getString("userName", ""));password.setText(preferences.getString("password", ""));}bn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {final String name=username.getText().toString();final String pwd=password.getText().toString();if(checkBox.isChecked()){editor.putString("userName", name);editor.putString("password", pwd);editor.putBoolean("AUTO_ISCHECK", true).commit();//存储用户名密码在xml文件}else editor.putBoolean("AUTO_ISCHECK",false).commit();new Thread(){/*用于网络的线程*/public void run(){try{/*用于登陆的代码*/String url="https://uac.10010.com/portal/Service/MallLogin?callback=jQuery17204165900954174946_1450622603532&redirectURL=http%253A%252F%252Fwww.10010.com" +"&userName=" +name+"&password=" +pwd+"&pwdType=01&productType=04&redirectType=01&areaCode=350&arrcity=%25E5%25BE%2590%25E5%25B7%259E&_=1450622609168";HttpGet get=new HttpGet(url);HttpResponse response=httpClient.execute(get);String confirm = EntityUtils.toString(response.getEntity(), "utf-8");Message msg = new Message();msg.what=0x123;if (confirm.contains("resultCode:\"0000\"")){msg.obj="登陆成功";handler.sendMessage(msg);}else {msg.obj="用户名或者密码错误";handler.sendMessage(msg);}/*发送post请求的代码*/List<String> postUri=new ArrayList<>();postUri.add("http://iservice.10010.com/e3/static/check/checklogin/?_=1450697102496");postUri.add("http://iservice.10010.com/e3/static/common/info?_=1450697103996");postUri.add("http://iservice.10010.com/e3/static/header");postUri.add("http://iservice.10010.com/e3/static/query/newsAssistant/search?_=1450697104007");postUri.add("http://iservice.10010.com/e3/static/check/checklogin?_=1450697104017");postUri.add("http://iservice.10010.com/e3/static/check/checklogin?_=1450697104361");for(String post:postUri){HttpPost postU=new HttpPost(post);HttpResponse response0=httpClient.execute(postU);}Message msg1=new Message();msg1.what=0x123;msg1.obj="发送请求";handler.sendMessage(msg1);SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM");String endDate=sdf.format(new Date());String beginDate=sdf1.format(new Date())+"-01";Message msg2=new Message();msg2.what=0x123;msg2.obj="开始日期:"+beginDate+"\t截止日期:"+endDate;handler.sendMessage(msg2);HttpPost htp=new HttpPost("http://iservice.10010.com/e3/static/query/callFlow?_=1450697104585&menuid=000100030004");List<NameValuePair> parameters = new ArrayList<NameValuePair>();//请求体parameters.add(new BasicNameValuePair("pageNo", "1"));parameters.add(new BasicNameValuePair("pageSize", "20"));parameters.add(new BasicNameValuePair("beginDate", beginDate));parameters.add(new BasicNameValuePair("endDate", endDate));UrlEncodedFormEntity urlEntity =  new UrlEncodedFormEntity(parameters, "UTF-8");htp.setEntity(urlEntity);HttpResponse result=httpClient.execute(htp);String s = EntityUtils.toString(result.getEntity(), "utf-8");//处理结果JSONObject ob = new JSONObject(s);String totalflow=ob.get("totalflow").toString();String fee=ob.get("flowfee").toString();int total=Integer.parseInt(totalflow)/3600;Message msg3=new Message();msg3.what=0x123;msg3.obj="时长合计:"+totalflow+"秒\n"+"大约为"+total+"小时\n"+"费用合计:"+fee;handler.sendMessage(msg3);}catch (Exception e){e.printStackTrace();}}}.start();}});}
}
												

从零开始学会做一个简单的APP相关推荐

  1. 如何做一个简单的APP

    应研究生毕业论文章节所需,以及找工作方面所面临的技术需求,在学习了部分JAVA技术的基础下,决定自己动手做一个有应用背景的Application.写点博客记录下"所作所为",比手写 ...

  2. 做一个简单的“远程”开关 ESP8266 + APP

    简单的远程开关制作(纯代码.无解析版.UDP通信) 引言 本篇文章,我们将做一个超级简单的开关,当你学会该操作后,就可以自己进行一些简单的添加.修改从而实现一些自定义的功能.你可以做一个简单的远程开关 ...

  3. 使用环信sdk做一个简单的聊天APP

    使用环信sdk做一个简单的即时聊天APP,实现简单的通讯 感悟 在很早以前就想做一个简单的即时聊天app.可能自己对即时聊天的三方SDK了解的不是特别深,在进行了一段时间的学习以后感觉自己的能力达到了 ...

  4. 老滚5初始化python失败_五分钟学会怎么用python做一个简单的贪吃蛇

    Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.我们今天将利用它来制作一款大家基本都玩过的小游戏--贪吃蛇. 一.需要导入的包 import pygame ...

  5. android sdk build-tools_从零开始仿写一个抖音App——视频编辑SDK开发(一)

    本文首发于微信公众号--世界上有意思的事,搬运转载请注明出处,否则将追究版权责任.交流qq群:859640274. 大家好久不见,又有一个多月没有发文章了.不知道还有哪些读者记得我的 从零开始仿写抖音 ...

  6. 从零开始仿写一个抖音App

    点击上方"何俊林",马上关注,每天早上8:50准时推送 真爱,请置顶或星标 本文转载自公号开发者技术前线,原文:https://juejin.im/post/5b9e9bf1e51 ...

  7. 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)

    大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...

  8. java如何做网页_java怎么做一个简单网页?网页包括什么?

    学了java程序之后,大家就可以将这些运用到生活中去,比如做一个简单的网页.正好也可以检测自己学了怎么样,那么接下来,我们就来给大家讲解一下这方面的内容. 用Java语言编写实现一个简单的WEB浏览器 ...

  9. Python开发——做一个简单的【表白墙】网站

    前言 大家早好.午好.晚好吖 ❤ ~ 今天我们要用Python做Web开发,做一个简单的[表白墙]网站. 众所周知表白墙的功能普遍更多的是发布找人,失物招领, 还是一个大家可以跟自己喜欢的人公开表白的 ...

  10. 开始做一个简单的记账工具

    用VScode做一个简单的记账工具 内容保存在 https://leonchan0608.coding.net/public/bookkeeping/bookkeeping/git 下班学习,奋斗一年 ...

最新文章

  1. CentOS 6.x 播放 mp3 音乐 —— 成功
  2. Analysis of the Clustering Properties of the Hilbert Space-Filling Curve 论文笔记
  3. 高德地图-搜索服务-POI搜索
  4. 【转】Android子线程真的不能更新UI么
  5. RabbitMQ高级指南:从配置、使用到高可用集群搭建
  6. HTML特效之团购页面效果
  7. 助力中小企业级连云端,促进工业互联网平台蓬勃发展,全套解决方案。附:技术产品
  8. 浙江省二级计算机vfp,浙江省计算机2级vfp程序调试真题集.doc
  9. 红宝书电子版_N2红蓝宝书电子版PDF(蓝宝书)
  10. 校验php语法是否正确,PHP正则校验email语法详解
  11. 三十款国外IES灯光经典素材整理i
  12. Android Studio Logcat 左边的工具栏不显示了 Show Toolbar
  13. iOS 解决TableView reloadData时cell中图片会闪的问题
  14. mysql中的left_MySQL left()函数
  15. 转盘抽奖角度计算 前端
  16. 打造可用的梅花6硬键盘
  17. [CC2642r1] ble5 stacks 蓝牙协议栈 介绍和理解 TI协议栈下载
  18. 第二集 第一魂环 第十章
  19. 如何在SYSTEM权限下实现屏幕监控
  20. https://developer.aliyun.com/group/cloud?aly_as=stGCd_wh?_k=g6zacxsource=5176.11533457userCode=9fo

热门文章

  1. Internet的点火人:马克.安德森
  2. java 修改图片后缀名,不改变图片前缀名
  3. 显示农历天气时钟小部件下载_玛雅日历安卓版下载|玛雅日历app下载_v5.3.2
  4. 数据结构与算法(十一)哈夫曼树及其应用
  5. Java盲文数据库_汉语盲文首个“数据库”开建
  6. openssl的部分使用例子
  7. 阿里p9就三分钟。。。。。
  8. Android appWidget——每日一句应用开发
  9. springboot使用logback
  10. 致Play Framework开发者们的一封信