简介
写了一个查询学校空闲教室的APP 拉取学校教务处网站的信息,分类显示,还加了一些杂七杂八的 毕竟第一次写android,什么都想尝试一下 点这下载:BuptRoom repository地址:一个简单的北邮自习室查询系统 完成第一个版本大概是3个周末 之后花了1个月陆陆续续更新了杂七杂八的 很多东西写的不规范,也是临时查到了就用上 总结一下这次写App的经过:

学习的内容
- Android基本架构,组件,生命周期
- Fragment的使用
- Java库与库之间的调用
- Github的使用
- 部署app
- 图像处理的一些方法
- 一个愚蠢的拉取网页内容的方式
- GitHub第三方库的利用
- 颜色方面的知识
- Android Material Design
- 简单的优化
- 多线程与Handler
解决的问题
主要解决了这么几个问题
- Android6.0以上的版本貌似权限需要动态验证,现在写的只支持5.0及以下版本,用到的permisson:
1 | <uses-permission android:name="android.permission.INTERNET"></uses-permission> |
- 网页是jsp动态网页,不能简单地parse,最后采用在webview中loadurl,执行javascript命令,需下载jsoup-1.9.2.jar这个包添加到库文件中
1 | final class MyWebViewClient extends WebViewClient { |
- 写一个handler响应javascript命令,这样在content中就拿到String形式的html文件中body内容
1 | final class JavascriptHandler{ |
- 之后是字符串处理,根据教务处给的格式精简分类
1 | 去逗号 |
界面上套了一个NavigationView,没有什么特别设计的,因为没有设置多界面,就靠刷新TextView来伪装多个界面
尝试了MaterialDesign组件,加入一点系统时间方面的东西
1 | final Calendar c = Calendar.getInstance(); |
在GitHub上学到的
此外还尝试引用了其他的一些GitHub库,学习了许多,包括调色盘,摇一摇模块,fir更新模块,滑动卡片界面等等 部分GitHub repository链接在这里 - 滑动卡片界面:Android-SwipeToDismiss - fir更新模块:UpdateDemo
还有一些直接写在代码里了,忘记原地址了.... - 摇一摇的传感器调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100public class ShakeService extends Service {
public static final String TAG = "ShakeService";
private SensorManager mSensorManager;
public boolean flag=false;
private ShakeBinder shakebinder= new ShakeBinder();
private String htmlbody="";
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Log.i(TAG,"Shake Service Create");
}
public void onDestroy() {
// TODO Auto-generated method stub
flag=false;
super.onDestroy();
mSensorManager.unregisterListener(mShakeListener);
}
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.i(TAG,"Shake Service Start");
}
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
mSensorManager.registerListener(mShakeListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
//SensorManager.SENSOR_DELAY_GAME,
50 * 1000); //batch every 50 milliseconds
htmlbody=intent.getStringExtra("htmlbody");
return super.onStartCommand(intent, flags, startId);
}
private final SensorEventListener mShakeListener = new SensorEventListener() {
private static final float SENSITIVITY = 10;
private static final int BUFFER = 5;
private float[] gravity = new float[3];
private float average = 0;
private int fill = 0;
public void onAccuracyChanged(Sensor sensor, int acc) {
}
public void onSensorChanged(SensorEvent event) {
final float alpha = 0.8F;
for (int i = 0; i < 3; i++) {
gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
}
float x = event.values[0] - gravity[0];
float y = event.values[1] - gravity[1];
float z = event.values[2] - gravity[2];
if (fill <= BUFFER) {
average += Math.abs(x) + Math.abs(y) + Math.abs(z);
fill++;
} else {
Log.i(TAG, "average:"+average);
Log.i(TAG, "average / BUFFER:"+(average / BUFFER));
if (average / BUFFER >= SENSITIVITY) {
handleShakeAction();//如果达到阈值则处理摇一摇响应
}
average = 0;
fill = 0;
}
}
};
protected void handleShakeAction() {
// TODO Auto-generated method stub
flag=true;
Toast.makeText(getApplicationContext(), "摇一摇成功", Toast.LENGTH_SHORT).show();
Intent intent= new Intent();
intent.putExtra("htmlbody",htmlbody);
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(this,"thinkwee.buptroom.ShakeTestActivity");
startActivity(intent);
}
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return shakebinder;
}
class ShakeBinder extends Binder{
}
}
独立网络拉取,并使用多线程
- 在之前的结构中网络拉取整合在欢迎界面的activity中,为了在主界面中添加刷新功能,随时调用网络拉取,我把网络拉取单独写成了一个类,需要的时候调用
- 然而在欢迎界面中显示欢迎动画和网络拉取在两个独立的线程中(为了使得动画不卡顿),这样就出现了可能欢迎动画做完了进入主界面时网络拉取还没有完成,传不了拉取的内容到主界面,最后的解决方案是设置网络拉取2s超时,若没拉取到则传一个错误的参数到启动主界面的activity中,提示刷新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40webget = new Webget();
webget.init(webView);
HaveNetFlag = webget.WebInit();
new Handler().postDelayed(new Runnable() {
public void run() {
//execute the task
ImageView img = (ImageView) findViewById(R.id.welcomeimg);
Animation animation = AnimationUtils.loadAnimation(WelcomeActivity.this, R.anim.enlarge);
animation.setFillAfter(true);
img.startAnimation(animation);
}
}, 50);
new Handler().postDelayed(new Runnable() {
public void run() {
//execute the task
WrongNet = webget.getWrongnet();
HaveNetFlag = webget.getHaveNetFlag();
htmlbody = webget.getHtmlbody();
Log.i("welcome", "2HaveNetFlag: " + HaveNetFlag);
Log.i("welcome", "2Wrongnet: " + WrongNet);
Log.i("welcome", "2html: " + htmlbody);
}
}, 2000);
new Handler().postDelayed(new Runnable() {
public void run() {
Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);
intent.putExtra("WrongNet", WrongNet);
intent.putExtra("HtmlBody", htmlbody);
startActivity(intent);
WelcomeActivity.this.finish();
}
}, 2500);
}