标签:
项目地址: https://github.com/hwding/AeolosXDUWidget
求支持(╭ ̄3 ̄)╭?
本小白所在的学校虽身为某某电子科技大学, 但是网络基础设施实在是...用于查询的各个网页根本用的不是一套系统...也就是说, 如果你想很方便地获取你的实验成绩\体育打卡次数\校内一卡通的流水情况和余额以及水电费的使用情况\图书馆借还信息等等, 你得登录很多不同的网页使用多套不同的系统输入不同的账户与密码...(不想吐槽某些系统居然还外包给另外一个某某电子科大...)
所以能不能用一种便捷的方法将重要的信息及时呈现和刷新呢?
根据这个需求给自己做了一个小部件放在手机桌面上, 真的很方便! 真的很方便! 真的很方便!
下面放两张预览图
这样一来小部件的功能就一目了然了
只要绑定相关账号就能自动获取最新的数据
原理很简单, 无非是登录之后拿到cookie然后去解析相关的页面, 最后呈现数据
由于用了以前自己造过的一个小轮子, 就是一个用于查询各个模块数据的接口, 所以这个部件的代码量大幅缩减
接口项目地址: https://github.com/hwding/libXDUQuery
下面说一些零碎的知识点
关于验证码:
制作中遇到的一大困难就是查询一卡通流水的系统必须要输个验证码
首先打开登录页面的时候服务器会塞一个Cookie过来, key为JSessionID, 用于当前会话的凭证
带着这个Cookie去访问一个用于返回验证码的页面, 会得到一张验证码图片, 此时服务器端当前会话的验证码也刷新了
提交用户名密码的时候带着这个验证码, 只要服务器端的验证码与你提交的验证码是一致的就可以返回一个有效的Cookie
然后再用这个Cookie去访问查询页面就OK了
当然还有验证码图片缓存的问题, 需要 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 这个权限
缓存方法:
1 public void getCaptcha(File file) throws IOException { 2 URL url = new URL(HOST + CAPTCHA_SUFFIX); 3 URLConnection urlConnection = url.openConnection(); 4 urlConnection.setRequestProperty("Cookie", "JSESSIONID="+JSESSIONID); 5 urlConnection.connect(); 6 InputStream inputStream = urlConnection.getInputStream(); 7 byte[] bytes = new byte[1024]; 8 FileOutputStream fileOutputStream = new FileOutputStream(file); 9 int LENGTH; 10 while ((LENGTH = inputStream.read(bytes)) != -1){ 11 fileOutputStream.write(bytes, 0, LENGTH); 12 } 13 inputStream.close(); 14 fileOutputStream.close(); 15 }
设置页面用于Download验证码的线程:
1 package xdu.hwding.aeolosxdu; 2 3 import android.os.Handler; 4 import android.os.Message; 5 import java.io.File; 6 import java.io.IOException; 7 import FooPackage.ECard; 8 9 public class CaptchaLoaderThread extends Thread{ 10 File file; 11 ECard eCard; 12 Handler handler; 13 14 CaptchaLoaderThread(File file, Handler handler) throws IOException { 15 this.file = file; 16 this.handler = handler; 17 } 18 19 public void run() { 20 try { 21 eCard = new ECard(); 22 eCard.getCaptcha(file); 23 Message message = new Message(); 24 message.obj = eCard; 25 handler.sendMessage(message); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } 29 } 30 }
缓存成功后通知主线程通过BitMap方式显示:
1 Handler generateHandler(final ImageView imageView, final File file) { 2 return new Handler() { 3 @Override 4 public void handleMessage(Message msg) { 5 Bitmap bitmap = BitmapFactory.decodeFile(String.valueOf(file)); 6 imageView.setImageBitmap(bitmap); 7 findViewById(R.id.add_button).setEnabled(true); 8 findViewById(R.id.add_button).setOnClickListener(generateOnClickListener((ECard) msg.obj)); 9 } 10 }; 11 }
关于HTML解析:
分析结果页面抽取有效信息是最重要的部分, 程序归根结底是一个爬虫
JSoup无疑是第一选择, 参见: Java中解析HTML数据 (利用第三方库Jsoup)
这里不做赘述
桌面部件(Widget)的更新周期:
创建桌面部件的时候AndroidStudio会自动生成一个XML配置文件, 里面定义了部件的某些属性
1 <?xml version="1.0" encoding="utf-8"?> 2 <appwidget-provider 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:configure="xdu.hwding.aeolosxdu.NewAppWidgetConfigureActivity" 5 android:initialKeyguardLayout="@layout/new_app_widget" 6 android:initialLayout="@layout/new_app_widget" 7 android:minHeight="215dp" 8 android:minWidth="250dp" 9 android:previewImage="@drawable/preview" 10 android:resizeMode="vertical" 11 android:updatePeriodMillis="1800000" 12 android:widgetCategory="home_screen"> 13 </appwidget-provider>
minHeight 和 minWidth 属性分别定义了部件的最小尺寸
resizeMode 定义可以缩放的方向
注意这里最坑的来了!!!
没有看过文档的本小白天真的认为这里可以让 updatePeriodMillis 低至60000毫秒这样就可以每分钟刷新一次...
然而事实是最低更新周期也得半小时(1800000ms)...如果你想更短只能再跑一个线程然后用广播通知什么的
为了这个折腾好长时间的我知道真相眼泪掉下来...
标签:
原文地址:http://www.cnblogs.com/hwding/p/5580081.html