效果图
- 数据的获取参见下面这两篇博客
Java登录方正教务系统
Java登录方正教务系统获取课表
登录界面设计
- 登录界面就是简单UI控件的应用,同时配合自定义其显示的样式,实现一些简单的视觉效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:background="@color/colorbackground_Lgoin"
android:layout_height="match_parent">
<ImageView
android:layout_marginTop="80dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/ic_pic"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="5dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/account_pic"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="学号"
android:text="201310503"
android:id="@+id/editText_id"
android:paddingLeft="20dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="5dp"
android:layout_gravity="center_vertical"
android:src="@mipmap/password_pic"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"
android:inputType="textPassword"
android:text="wz446774318"
android:paddingLeft="20dp"
android:id="@+id/editText_password" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:src="@mipmap/check_pic"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText_checkcode"
android:paddingLeft="20dp"
android:hint="验证码"
android:layout_weight="1"/>
<ImageView
android:layout_width="80dp"
android:layout_height="40dp"
android:id="@+id/imageView_checkcode" />
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:text="登录"
android:background="@drawable/selecter_login_button"
android:id="@+id/button_login"
android:layout_gravity="right" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注意事项"
android:layout_margin="10dp"
android:id="@+id/textView_care"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
</RelativeLayout>
</LinearLayout>
android的登陆操作
- 由于在安卓中不允许在主线程中访问网络和其他一些费时的操作,故在我们点击登录按钮的时候,我们需要开启新的线程去进行数据的提交,和返回数据的获取,对返回数据的处理,需要使用到消息传递机制Handler才能传递到主线程中。
private void loginThread() {
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
try {
// 拼接请求字符串
String str = "__VIEWSTATE=" + URLEncoder.encode(loginData.getViewState(), "gb2312") + "&txtUserName=" + loginData.getId() + "&TextBox2="
+ loginData.getPassword()+ "&txtSecretCode=" + loginData.getCheckCode() + "&RadioButtonList1=" + URLEncoder.encode("学生", "gb2312")
+ "&Button1=&lbLanguage=&hidPdrs=&hidsc=";
;
System.out.println("参数列表:" + str);
// 登录提交的网址
URL url = new URL("http://10.5.3.236/default2.aspx");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Post提交
conn.setRequestMethod("POST");
conn.setReadTimeout(5000);
conn.setUseCaches(false);
// 禁止程序自己跳转到目标网址,必须设置,不然程序会自己响应
// 302返回码,自己请求跳转后的网址,出现Object Had Moved!错误
conn.setInstanceFollowRedirects(false);
// 写入cookie
conn.setRequestProperty("Cookie", loginData.getCookie());
conn.setDoOutput(true);
OutputStream out = conn.getOutputStream();
// 写入参数
out.write(str.getBytes());
out.close();
// 打印返回码
System.out.println("返回码:" + conn.getResponseCode());
// 打印服务器返回的跳转网址
System.out.println("Location :" + conn.getHeaderField("Location"));
BufferedReader read = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String temp;
// 读取页面源码
StringBuffer ab = new StringBuffer();
while ((temp = read.readLine()) != null) {
ab.append(temp);
}
System.out.println(ab);
if (conn.getResponseCode() != 302) {
new Thread(new GetCheckCode(loginData, myHanler)).start();
Toast.makeText(LoginActivity.this, "用户名或密码错误!!!", Toast.LENGTH_SHORT).show();
Message msg=new Message();
msg.arg1=10086;
myHanler.sendMessage(msg);
} else {
GetNameByUrl.getNameByUrl(conn.getHeaderField("Location"),loginData);
Intent intent=new Intent(LoginActivity.this,MainActivity.class);
intent.putExtra("loginData",loginData);
startActivity(intent);
finish();
}
} catch (IOException e) {
e.printStackTrace();
}
Looper.loop();
}
}).start();
}
- 通过两个工具类实现验证码的获取,获取验证码的代码如下:
public class GetCheckCode implements Runnable{
private LoginData loginData;
private Handler myHandler;
public GetCheckCode(LoginData loginData, Handler myHandler) {
this.loginData = loginData;
this.myHandler = myHandler;
}
@Override
public void run() {
try {
/**
* img变量的值为http:http://10.5.3.236/CheckCode.aspx
* 也就是上面图片中,验证码的网址,在浏览器中,右键验证码 即可选择复制图片网址 请求 URL:
* http://10.5.3.236/CheckCode.aspx
*/
URL url = new URL("http://10.5.3.236/CheckCode.aspx");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
// cookie一同提交(ASP.NET_SessionId=4kusfii0urpbrazkhxvuas45,只需要等号后面的一串数据)
conn.setRequestProperty("Cookie", loginData.getCookie());
InputStream in = conn.getInputStream();
loginData.setBitmap_checkcode(BitmapFactory.decodeStream(conn.getInputStream()));
System.out.println("读取验证码完毕!");
Message msg=new Message();
msg.obj=loginData;
myHandler.sendMessage(msg);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 获取课表的代码如下
public class GetTimeTable implements Runnable {
private LoginData loginData;
private List<CourseBean> courseList;
private Handler myHanler;
public GetTimeTable(LoginData loginData,List<CourseBean> courseList,Handler myHanler) {
this.loginData = loginData;
this.courseList=courseList;
this.myHanler=myHanler;
}
@Override
public void run() {
System.out.println("读取课表");
String url = null;
try {
url = "http://10.5.3.236/xskbcx.aspx?xh="+loginData.getId()
+"&xm="+URLEncoder.encode(loginData.getName(), "gb2312")+"&gnmkdm="
+loginData.getNeedString();
System.out.println("获取课表的参数: " + url);
URL Url;
Url = new URL(url);
HttpURLConnection conn = (HttpURLConnection) Url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(2000);
conn.setRequestProperty("Cookie", loginData.getCookie());
conn.setRequestProperty("Referer",
"http://10.5.3.236/xs_main.aspx?xh="+loginData.getId());
conn.setInstanceFollowRedirects(false);
conn.setDoOutput(true);
BufferedReader read = new BufferedReader(new InputStreamReader(
conn.getInputStream(),"gb2312"));
StringBuffer sb = new StringBuffer();
String temp;
while ((temp = read.readLine()) != null) {
sb.append(temp);
}
dealTimeTableHtml(sb.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void dealTimeTableHtml(String courseHtml) {
Pattern pattern1 = Pattern.compile("width=\"7%\">.*?/td>");
Matcher matcher1 = pattern1.matcher(courseHtml);
StringBuffer sb = new StringBuffer();
int begin = 0;
int end = 0;
while (matcher1.find()) {
begin = matcher1.start();
end = matcher1.end();
String str = courseHtml.substring(begin + 11, end);
sb.append(str);
}
pattern1 = Pattern.compile("rowspan=\"2\">.*?/td>");
matcher1 = pattern1.matcher(courseHtml);
while (matcher1.find()) {
begin = matcher1.start();
end = matcher1.end();
String str = courseHtml.substring(begin + 12, end);
sb.append(str);
}
String str=sb.toString().replaceAll(" </td>","");
String[] courseString = str.split("</td>");
for (int i=0;i<courseString.length;i++){
String[] courseDital=courseString[i].split("<br>");
CourseBean courseBean=new CourseBean(courseDital[0],courseDital[1],courseDital[2],courseDital[3],courseDital[4]);
courseList.add(courseBean);
}
Message msg=new Message();
msg.obj=courseList;
myHanler.sendMessage(msg);
}
}
课表的解析和展示
- 课表的展示使用的是ViewPager,这是supportV4提供的一个控件,一个ViewPager里面包含了7个页面,在登录成功以后,登录界面会通过intent将解析出来并格式化好的课表信息发送给课表显示页面,然后根据课表信息是那一天的,在添加到不同页面的ListView中去,然后再为listView设置其适配器,自定义其显示的内容的样式即可。
/**
* Created by Wang on 2016/3/29.
*/
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private List<Fragment> pager_list;
private LoginData loginData;
private List<CourseBean> courseList, courseList1, courseList2, courseList3, courseList4, courseList5;
private ListView listView_pager1, listView_pager2, listView_pager3, listView_pager4, listView_pager5;
private MyFragment myFragment1, myFragment2, myFragment3, myFragment4, myFragment5;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
Intent intent = getIntent();
loginData = intent.getParcelableExtra("loginData");
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), pager_list);
viewPager.setAdapter(adapter);
Toast.makeText(MainActivity.this, "欢迎登陆," + loginData.getName() + "同学", Toast.LENGTH_SHORT).show();
new Thread(new GetTimeTable(loginData, courseList, myHanler)).start();
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
switch (position) {
case 0:
listView_pager1 = myFragment1.getListView();
MyAdapter adapter1 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList1);
listView_pager1.setAdapter(adapter1);
break;
case 1:
listView_pager2 = myFragment2.getListView();
MyAdapter adapter2 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList2);
listView_pager2.setAdapter(adapter2);
break;
case 2:
listView_pager3 = myFragment3.getListView();
MyAdapter adapter3 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList3);
listView_pager3.setAdapter(adapter3);
break;
case 3:
listView_pager4 = myFragment4.getListView();
MyAdapter adapter4 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList4);
listView_pager4.setAdapter(adapter4);
break;
case 4:
listView_pager5 = myFragment5.getListView();
MyAdapter adapter5 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList5);
listView_pager5.setAdapter(adapter5);
break;
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private Handler myHanler = new Handler() {
public void handleMessage(Message msg) {
courseList = (List) msg.obj;
for (int i = 0; i < courseList.size(); i++) {
CourseBean courseBean = courseList.get(i);
if (courseBean.getCourse_week().contains("周一")) {
courseList1.add(courseBean);
} else if (courseBean.getCourse_week().contains("周二")) {
courseList2.add(courseBean);
} else if (courseBean.getCourse_week().contains("周三")) {
courseList3.add(courseBean);
} else if (courseBean.getCourse_week().contains("周四")) {
courseList4.add(courseBean);
} else if (courseBean.getCourse_week().contains("周五")) {
courseList5.add(courseBean);
}
}
listView_pager1 = myFragment1.getListView();
MyAdapter adapter1 = new MyAdapter(MainActivity.this, R.layout.layout_item_listview, courseList1);
listView_pager1.setAdapter(adapter1);
}
};
private void init() {
viewPager = (ViewPager) findViewById(R.id.viewPager);
pager_list = new ArrayList<>();
myFragment1 = new MyFragment();
myFragment2 = new MyFragment();
myFragment3 = new MyFragment();
myFragment4 = new MyFragment();
myFragment5 = new MyFragment();
pager_list.add(myFragment1);
pager_list.add(myFragment2);
pager_list.add(myFragment3);
pager_list.add(myFragment4);
pager_list.add(myFragment5);
courseList = new ArrayList<>();
courseList1 = new ArrayList<>();
courseList2 = new ArrayList<>();
courseList3 = new ArrayList<>();
courseList4 = new ArrayList<>();
courseList5 = new ArrayList<>();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.login_out:
this.finish();
Toast.makeText(MainActivity.this, "用户已注销,请重新登录!!!", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(MainActivity.this,LoginActivity.class);
startActivity(intent);
break;
case R.id.exit:
finish();
break;
}
return true;
}
}
总结
- 由于本人水平有限,描述的也不尽然相近,代码中的诸多漏洞还请谅解,如果对代码存在疑问,可以查看源码并下载,地址:超级课程表(ViewPager实现)