网络连接获取并解析数据——OKHTTP(仿12306软件)

网络连接获取数据——OKHTTP3(仿12306软件)

仿12306软件使用OKHTTP3网络连接获取数据部分。

前期准备

OkHttp官网地址:http://square.github.io/okhttp/

OkHttp GitHub地址:https://github.com/square/okhttp
在线JSON解析地址:https://www.json.cn/

导入OKHTTP3依赖

compile 'com.squareup.okhttp3:okhttp:3.4.1'

申请网络访问权限

    <uses-permission android:name="android.permission.INTERNET"/>

登陆部分

API文档分析

POST请求,需要两个参数,分别是用户名和密码
服务器端默认的用户名/密码:dong/dong

okhttp同步请求

需要手动启动一个线程,因为线程之间的运行是同步的所以需要用handle来进行线程之间通信。
不管是同步还是异步请求都有四个关键的步骤:

  1. 创建OkhttpClient 对象
  2. 创建请求的Request 对象
  3. 在Okhttp中创建Call 对象,将request和Client进行绑定
  4. 执行Call对象(call 是interface 实际执行的是RealCall)中的execute()或enqueue()方法

同步和异步请求唯一区别是,最后调用的Call对象的方法不同, 同步调用是execute()方法,而异步调用的是enqueue()。

//创建OkhttpClient 对象
final OkHttpClient client = new OkHttpClient();
//    网络访问
    private void postRequest() {
    
	//构造请求正文
        RequestBody formBody = new FormBody.Builder()
                .add("username",user.getText().toString())
                //密码需要通过MD5加密
                .add("password",md5Utils.MD5(password.getText().toString()))
                .build();
	
	//构造Request(请求)
       //每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。
        request = new Request.Builder()
                .url(url+"/My12306/Login")
                .post(formBody)
                .build();

        new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = handler.obtainMessage();
                
                //Responses(响应)
                Response response = null;
                
                try {
                //在Okhttp中创建Call 对象,将request和Client进行绑定,并用 execute()启动
                    response = client.newCall(request).execute();
                    //判断响应是否成功
                    if (response.isSuccessful()){
                    
                    	//获得响应体
                     	String result = response.body().string();
                     	//解析获得的响应内容(xml)
                      	parseXMLWithPull(result);
			
			//把解析完成后的值通过Message发送给Handle
                        msg.obj = value;
                        msg.what = 1;
                        msg.arg1 = Integer.parseInt(flag);

                    }else {
                        throw new IOException("Unexpected code" + response);

                    }
                }catch (Exception e){
                    e.printStackTrace();
                    msg.what = 2;
                }
                handler.sendMessage(msg);
            }
        }).start();
    }

解析数据(XML)

//    解析XML
    private String  parseXMLWithPull(String result) {
        try {
            //获取解析器
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new StringReader(result));
	    //获取产生事件类型
            int eventType = parser.getEventType()//开始解析
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = parser.getName();
                switch (eventType){
                    case XmlPullParser.START_DOCUMENT:
//                        初始化
                        flag = "0";
                        Log.i("---flag",flag);
                        break;
                    case XmlPullParser.START_TAG:
                    //按照节点名字查找,获取需要的数据
                        if ("result".equals(nodeName)){
                            flag = parser.nextText();
                        }
                        break;
                    case XmlPullParser.END_TAG://完成解析
                        if ("data".equals(nodeName)) {
                            Log.i("---result", "result : " + flag);
                        }
                        break;
                    default:
                        break;
                }

                eventType=parser.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

使用handle对UI线程进行修改

Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg){
            switch (msg.what){
                case 1:
                    int result = msg.arg1;
                    if (0 == result){
                        user.selectAll();
                        user.setError("账号或者密码错误");
                        password.setError("账号或者密码错误");
                        user.requestFocus();
                    }else if (1 == result){
                        Intent intent = new Intent();
                        intent.setClass(LoginActivity.this,HomeActivity.class);
                        startActivity(intent);
                    }
                    break;
                case 2:
                    Toast.makeText(LoginActivity.this, "服务器错误,请重试",
                            Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };

获取cookie并保存

使用cookieJar()自动管理cookie
final OkHttpClient client = new OkHttpClient.Builder().cookieJar(new CookieJar() {
    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        cookieStore.put(url.host(),cookies);
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        List<Cookie> cookies = cookieStore.get(url.host());
        return cookies != null ? cookies : new ArrayList<Cookie>();
    }
}).build();
从Response中获取Cookie
//从登录成功后的Response中获取所有的Cookie
Headers loginHeaders = response.headers();
HttpUrl loginUrl = request.url();
List<Cookie> cookies1 = Cookie.parseAll(loginUrl,loginHeaders);
if(cookies1!=null){
    //将登录成功的Url对应的所有的Cookie通过Cookiejar的方法保存到cookieStore中去,方便我们下次根据登录成功的url来获取对应的cookie
    client.cookieJar().saveFromResponse(loginUrl,cookies1);
}
记录JSESSIONID,并保存到本地
//		记录JSESSIONID

                            String value = "";
                            List<Cookie> cookies = client.cookieJar().loadForRequest(loginUrl);
                            for(Cookie cookie : cookies){

                                if ("JSESSIONID".equals(cookie.name())){
                                    value = cookie.value();
                                    Log.i("--va",value);
                                }
                            }
                            msg.obj = value;
String jsessionid = (String) msg.obj;
SharedPreferences sharedPreferences = getSharedPreferences("user", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("JSESSIONID",jsessionid);
editor.commit();

我的账号部分

API文档

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
POST请求但是需要添加请求头,需要获得登录时的cookie。

okhttp异步请求

不需要手动新建一个线程,更简单

private void getInfo(final String action) {
    SharedPreferences sharedPreferences = getSharedPreferences("user", MODE_PRIVATE);
    String value = sharedPreferences.getString("JSESSIONID", "");

    RequestBody formBody = new FormBody.Builder()

            .add("action", action)
            .add("tel", "13812345678")
            .add("type", "成人")
            .build();

    final Request request = new Request.Builder()
            .header("cookie", "JSESSIONID=" + value)
            .post(formBody)
            .url("http://100.0.101.13:8080/My12306/otn/Account")
            .build();
     //同步和异步请求唯一区别是,最后调用的Call对象的方法不同, 同步调用是execute()方法,而异步调用的是enqueue()
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            System.out.println(e.getMessage());
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                String result = response.body().string();
                if ("请重新登陆!".equals(result)){
                    Toast.makeText(PersonalActivity.this,"请重新登陆!",Toast.LENGTH_LONG);
                }else {
                    parseJSON(result,action);
                }

            }
        }
    });
}

解析数据(JSON)

private void parseJSON(String result,String action){
    try {
        JSONObject  jsonObject = new JSONObject(result);

        if ("query".equals(action)){
            username.setText(jsonObject.getString("username"));
            id.setText(jsonObject.getString("id"));
            name.setText(jsonObject.getString("name"));
            idType.setText(jsonObject.getString("idType"));
            Tel.setText(jsonObject.getString("tel"));
            Type.setText(jsonObject.getString("type"));
        }else {

            EditText name_edit =  (EditText)personalDialog.findViewById(R.id.username_dialog);
            name_edit.setText(jsonObject.getString("username"));
            EditText tel_edit =  (EditText)personalDialog.findViewById(R.id.tel_dialog);
            tel_edit.setText(jsonObject.getString("tel"));
        }
    }catch (JSONException e){
        e.printStackTrace();
    }

}

遇见的坑

  1. 如果用同步请求一定要handler来接收消息
  2. 不记得了,等我想起吧
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值