从零开始学会做一个简单的APP

本人是矿大学信息安全的大三狗,混了两年日子之后幡然醒悟决定做些自己早就想做的事情,学校的联通宽带是按时长收费的,但是每次查询已用时长和所扣费用步骤都十分的繁琐,大二的时候都想着要自己做一个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 stub

CloseableHttpClienthttpclient = 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();//生成想要的URL

HttpGethtg0=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() {
            @Override
            public 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();
            }
        });
    }
}
时间: 2025-02-01 12:02:08

从零开始学会做一个简单的APP的相关文章

手把手教你从零开始做一个好看的 APP

前言 从零开始,手把手带你实现一个「专注睡前的 APP」.睡觉之前如果能有一个 APP,能让我们写一写这一天的见闻或者心得,同时又能看一会段子.瞄一会好看的妹子,放松一下疲惫的身心那该多好,这也是我完成这个 APP 的原因.APP 的全部代码我已经分享到?Github?上了,需要的直接 点击这里,如果喜欢的话,麻烦给个 star,谢谢啦. 本文为这一系列文章的总述,如果觉得篇幅过长,请点击下面的连接 手把手教你从零开始做一个好看的 APP - Day one 手把手教你从零开始做一个好看的 AP

使用React并做一个简单的to-do-list

1. 前言 说到React,我从一年之前就开始试着了解并且看了相关的入门教程,而且还买过一本<React:引领未来的用户界面开发框架 >拜读.React的轻量组件化的思想及其visual-dom的这种技术创新,也算是早就有了初步了解.一来没有学的太深入,二来后来在工作中和业余项目中都没有用到,因此慢慢的就更加生疏了. 近期,因为我想把自己的开源项目wangEditor能放在React.angular和vuejs中使用.先从react开始,顺手自己也重试一下React的基础知识,顺便再做一个小d

.Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器

原文:.Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器 目标:使用.net core最新的3.0版本,借助httpclient和本机的host域名代理,实现网络请求转发和内容获取,最终显示到目标客户端! 背景:本人在core领域是个新手,对core的使用不多,因此在实现的过程中遇到了很多坑,在这边博客中,逐一介绍下.下面进入正文 正文: 1-启用httpClient注入: 参考文档:https://docs.microsoft.c

使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)

猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 使用Multiplayer Networking做一个简单的多人游戏例子-1/3 使用Multiplayer Networking做一个简单的多人游戏例子-2/3 使用Multiplayer Networking做一个简单的多人游戏例子-3/3 7. 在网络中控制Player移动 上一篇中,玩家操

[3] 用D3.js做一个简单的图表吧!

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为可缩放矢量图形(Scalable Vector Graphics),SVG 使用 XML 格式定义图像,不清楚什么是SVG的朋友请先在 w3cschools 学习下

用EF DataBase First做一个简单的MVC3报名页面

使用EF DataBase First做一个简单的MVC3报名网站 ORM(Object Relational Mapping)是面向对象语言中的一种数据访问技术,在ASP.NET中,可以通过ADO.NET Entity Framework技术来简化数据访问.在EF里,有Code First,Model First和DataBase First三种方法来实现. 百度百科关于ORM的介绍: http://baike.baidu.com/view/197951.htm?fr=aladdin 1.就像

【Python】 做一个简单的 http 服务器

# coding=utf-8 ''' Created on 2014年6月15日 @author: Yang ''' import socket import datetime # 初始化socket s = socket.socket() # 获取主机名, 也可以使用localhost # host = socket.gethostname() host = "localhost" # 默认的http协议端口号 port = 80 # 绑定服务器socket的ip和端口号 s.bin

Jmeter初步使用二--使用jmeter做一个简单的性能测试

经过上一次的初步使用,我们懂得了Jmeter的安装与初步使用的方法.现在,我们使用Jmeter做一个简单的性能测试.该次测试,提交的参数不做参数化处理,Jmeter各元件使用将在介绍在下一博文开始介绍并使用. 首先,打开Jmeter工具,并建立一个测试计划(测试脚本).启动jmeter后,jmeter会自动生成一个空的测试计划,我们可以基于该测试计划建立自己的测试计划. 步骤: 步骤一:添加线程组 一个性能测试请求负载是基于一个线程组完成的.一个测试计划必须有一个线程组.测试计划添加线程组非常简

【 D3.js 入门系列 — 3 】 做一个简单的图表!

图1. 柱形图 1. 柱形图 前几章的例子,都是对文字进行处理.本章中将用 D3 做一个简单的柱形图.制作柱形图有很多种方法,比如用 HTML 的 <div> 标签,或在 SVG 上绘制 . SVG ,即可缩放矢量图形(Scalable Vector Graphics),使用 XML 格式定义图形,可在 W3School 学习 SVG 的相关语法,不需要记住所有标签,用的时候再查即可. 先看下面的代码: <script src="http://d3js.org/d3.v3.mi