android学习笔记之客户端与服务端保持session登录状态

来源:互联网 发布:淘宝店运营工作职责 编辑:程序博客网 时间:2024/06/02 07:30

刚进公司不久,也没有具体项目任务,只有一个混合开发模式,使用AppCan开发的项目。

虽然混合开发很便捷、很高效,使用html和js就可以完成。

但我依然对android原生开发有着极高的热情,尤其是在体验了Android 5.0版本之后,更是对原生体验着迷。

所以,我利用空闲时间,使用Android原生开发,实现以下简单任务:

用户登录,查看用户信息,查看用户和领导的谈话列表。

难点:因为缺乏http通信基础,并不知道session和cookie的作用,所以在开发中绕了很多弯路,因为虽然我登录成功了,但是在查询谈话列表时,就会请求失败。

原因:经过一番学习,大概了解了session和cookie的作用,只有让服务器识别出当前登录用户的状态,才能给予其权限进行其他请求操作。


用到的知识点很多,总结一下重要的:

1、关于Volley框架

Volley框架是谷歌官方通信框架,适合小数据传输使用,之前使用都很顺手,可是其没有方法获取httpResponse中的header信息,即无法获取JSESSIONID,JSESSIONID是session的一个独一无二的标识,需要重写框架的方法才可以,故放弃之。

2、使用HttpUrlConnection

使用HttpUrlConnection进行网络请求,涉及网络请求的操作不能在UI线程即主线程执行,需要创建内部类继承自AsyncTask异步任务处理类。

其中最重要的就是通过 conn.getHeaderField("set-cookie")  方法得到返回头部的cookie部分;

然后通过 cookie.substring(0, cookie.indexOf(";"))  方法取出"JSESSIONID=XXXXXX"

private class LoginASyncTask extends AsyncTask<String, Void, String> {@Overrideprotected String doInBackground(String... params) {mSharedPreferences = getSharedPreferences("cookie", MODE_PRIVATE);// 用来存储服务器响应cookiemEditor = mSharedPreferences.edit();String urlPath = "http://192.168.0.31:8080/jxyy/login/check";String result = null;try {URL url = new URL(urlPath);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("POST"); // 设置请求方法为postconn.setUseCaches(false); // 禁止用户缓存conn.setDoOutput(true); // 必须设置:允许输出流DataOutputStream dos = new DataOutputStream(conn.getOutputStream());// 实例化输出流对象,用于写入参数StringBuffer paramsBuffer = new StringBuffer();paramsBuffer.append("&username=" + params[0]);paramsBuffer.append("&password=" + params[1]);paramsBuffer.append("&flag=" + "android");System.out.println("paramsBuffer=" + paramsBuffer.toString());dos.writeUTF(paramsBuffer.toString());// 使用UTF格式输出该参数dos.flush();// 输出缓冲dos.close();// 输出关闭if (conn.getResponseCode() == 200) {<strong>String cookie = conn.getHeaderField("set-cookie");// 获取服务器响应cookieString sessionId = cookie.substring(0, cookie.indexOf(";"));mEditor.putString("cookie", sessionId);mEditor.commit();// 将cookie存入mSharedPreferences中</strong>BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));StringBuffer sb = new StringBuffer();String temp = "";while ((temp = br.readLine()) != null) {sb.append(temp);}result = sb.toString();}} catch (Exception e) {e.printStackTrace();}return result;}}


再次请求网络时,需要从SharedPreferences中取出该JSESSIONID

然后使用conn.setRequestProperty方法传入该cookie参数进行网络请求

URL url = new URL(urlPath);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestProperty("cookie", sharedPreferences.getString("cookie",""));

3、处理返回的JSONArray数据

服务端把每个谈话内容封装为一个JSONObject对象,将满足条件的所有谈话装入一个JSONArray中,以字符串返回客户端。

再看客户端,要以ListView来显示这些谈话内容,而ListView不能识别JSON格式的数据,需要将JSON转化为List<Map<String,String>>对象方可。

具体思路是 :

·循环遍历JSONArray依次取出每个谈话的JSONObject

·在每个JSONObject中,遍历key,value对,存入map对象中

·将map对象依次存入List<Map>中

·使用SimpleAdapter将该List<Map>与ListView绑定


下面是将JSONArray转为List<Map<String,String>>对象详细实现代码:

private List<HashMap<String, String>> jsonArrayToMapList(String result) {List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();// 实例化要绑定的List对象HashMap<String, String> talk = new HashMap<String, String>();// 用于存储单个谈话会议的map对象try {JSONArray ja = new JSONArray(result);for (int i = 0; i < ja.length(); i++) { // 遍历JSONArray,依次取出JSONObjectJSONObject jo = ja.getJSONObject(i);Iterator<String> it = jo.keys(); // 遍历JSONObject的keyswhile (it.hasNext()) {String key = String.valueOf(it.next());String value = (String) jo.get(key);talk.put(key, value);// 将JSONObject中key,value转存如map}data.add(talk);// 把所有map存入list中}} return data;}

下面是List<Map<String,String>>对象绑定至ListView的详细实现代码

private void bindToListView(List<HashMap<String, String>> data) {SimpleAdapter adapter = new SimpleAdapter(this, data,R.layout.list_talk, new String[] { "talktitle","personName", "personOrg","targetName", "targetOrg", "talkState" },new int[] { R.id.talkTitle, R.id.talkPerson,R.id.personOrg, R.id.talkTarget,R.id.targetOrg, R.id.talkState });lv_talks.setAdapter(adapter);}


其中,SimpleAdapter的参数依次是:

this:上下文context,用this即可

data:List<Map<String,String>>类型的要显示的数据

R.layout.list_talk:要用于显示的list布局资源

new String [ ] { "aa", "bb", "cc" }:要显示的map中的key值

new int [ ] { R.id.aa, R.id.bb, R.id.cc } :要显示到的具体的控件资源对应id





0 0
原创粉丝点击