整体设计思路:
客户端主要完成学生注册,登陆,查看自己的信息,以及自己的签到信息。
服务端主要完成课程创建,课程列表,然后查看列表,每一个有个展示,完成二维码扫码,扫出来此课程的所有学生信息。
详细的界面完整流程:
我们的BaseApplication 是全局的Application,里面实现启动时候的全局初始化数据,主要完成数据库创建 二维码信息目录创建
设置和获取用户信息。
@Override
public void onCreate() {
super.onCreate();
//创建数据库 info
LiteOrmDBUtil.createDb(this, “info”);
// 创建一个目录
initFile();
}
private void initFile() {
File storageDirectory = Environment.getExternalStorageDirectory();
String path = storageDirectory.getPath() + "/QrWiFiSign";
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
}
// 存下来学生信息
public void setUser(user info) {
this.info = info;
}
// 返回学生信息
public user getUser() {
return info;
}
AndroidManifest.xml 里面有这些activity.
AnimationActivity 第一个动画界面,启动入口,完成一个动画效果,然后进入选择是客户端和服务端主界面。
AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);
aa.setDuration(ANIMATION_TIME);
aa.setFillAfter(true);
//动画,结束后进行启动选择是否进入客户端还是服务端
//客户端就是登录用户,然后里面显示我的二维码,我的课程列表
//服务端主要完成课程建立,然后用户扫码,进行签到课程即可
this.findViewById(R.id.iv_animation_logo).startAnimation(aa);
aa.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
startMainActivity();
}
});
}
//进入选择界面
private void startMainActivity() {
finish();
Intent intent = new Intent(this, selActivity.class);
startActivity(intent);
}
selActivity 选择的界面,主要点击客户端和服务端,进入自己的主界面
// 客户端,进入用户注册登录界面
kehuduan = (TextView) findViewById(R.id.kehuduan);
//注册回调,于是selActivity会实现回调方法
kehuduan.setOnClickListener(this);
fuwuduan = (TextView) findViewById(R.id.fuwuduan);
fuwuduan.setOnClickListener(this);
//这里实现OnClickListener方法
selActivity extends Activity implements OnClickListener {
//然后实现的点击流程
// 点击客户端,进入登录注册界面 完成登录界面 注册界面的启动
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch (arg0.getId()) {
case R.id.kehuduan:
//客户端点击,进入注册界面
Intent intent = new Intent(this, registerActivity.class);
startActivity(intent);
break;
case R.id.fuwuduan:
//服务端点击,进入服务端主界面 显示创建课程 和 所有课程
Intent intent1 = new Intent(this, fuwuduanActivity.class);
startActivity(intent1);
break;
}
finish();
}
registerActivity 注册界面,显示信息如下,填写完成后点击注册或者去直接登陆
// 姓名
EditText xingming;
// 班级
EditText banji;
// 学号
EditText xuehao;
// 注册
TextView zhuce;
// 登录
TextView denglu;
点击注册的内容信息为:
// 注册逻辑代码,需要判断是否为空,为空提示,如果ok,存储下来,同时需要注意学号不能重复
zhuce.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String tmp1 = xingming.getText().toString();
String tmp2 = banji.getText().toString();
String tmp3 = xuehao.getText().toString();
// 如果发现哪个为空,就提示让输入
if (tmp1.isEmpty() || tmp2.isEmpty() || tmp3.isEmpty()) {
Toast.makeText(registerActivity.this,
"姓名 班级 学号 都不能为空,请输入完成注册!", Toast.LENGTH_SHORT)
.show();
return;
}
// 查询是否都存储过了 如果此学号的已经有,则提示已经有此用户了,可以去登陆
// 查询此学号是否存在了
QueryBuilder qb = new QueryBuilder(user.class).whereEquals(
"xuehao", tmp3);
List aa = LiteOrmDBUtil.getLiteOrm(). query(qb);
if (aa.size() > 0) {
Toast.makeText(registerActivity.this,
"此学号已经存在了,如果注册了,请登录!", Toast.LENGTH_SHORT).show();
return;
}
// 如果此学号没有,就可以存储了
LiteOrmDBUtil.saveData(new user(tmp1, tmp2, tmp3));
Toast.makeText(registerActivity.this, "注册成功,可以登录了!",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(registerActivity.this,
loginActivity.class);
startActivity(intent);
}
});
点击去登录的逻辑:
denglu.setOnClickListener(new OnClickListener() {
//进入登录界面
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(registerActivity.this,
loginActivity.class);
startActivity(intent);
}
});
loginActivity 登录界面,实现填写 学生 名字和 学号 ,然后登录进来
点击登录的逻辑为:
// 登录逻辑代码,需要判断是否为空,为空提示,如果ok 判断 输入的名字 和学号是否存在,存在说明正确的。
denglu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String tmp1 = xingming.getText().toString();
String tmp2 = xuehao.getText().toString();
// 如果发现哪个为空,就提示让输入
if (tmp1.isEmpty() || tmp2.isEmpty()) {
Toast.makeText(loginActivity.this, "姓名 学号 不能为空,请输入完成后登陆!",
Toast.LENGTH_SHORT).show();
return;
}
// 查询是否都存储过了 如果此学号的已经有,则提示已经有此用户了,可以去登陆
// 查询此学号是否存在了
QueryBuilder qb = new QueryBuilder(user.class)
.whereEquals("xuehao", tmp2).whereAppendAnd()
.whereEquals("name", tmp1);
List aa = LiteOrmDBUtil.getLiteOrm(). query(qb);
// 如果 没有查到信息,说民输入错误了,请重输入
if (aa.size() == 0) {
Toast.makeText(loginActivity.this, "姓名 学号输入有误,请重新输入后登陆!",
Toast.LENGTH_SHORT).show();
return;
}
//存储下来这个登录的用户,后面需要用
((BaseApplication) getApplication()).setUser(aa.get(0));
// 进入主界面
Toast.makeText(loginActivity.this, "登陆成功!", Toast.LENGTH_SHORT)
.show();
// 启动进入学生主界面 ,主要显示两个信息 ,我的信息,以及我的签到课程
Intent intent = new Intent(loginActivity.this,
MainActivity.class);
startActivity(intent);
}
});
MainActivity 进入学生的主界面
主要显示的为:我的信息 以及 我的签到
点击为:
case R.id.wodeqiandao:
//我的签到界面
Intent intent = new Intent(this, qiandaoActivity.class);
startActivity(intent);
break;
case R.id.wodexinxi:
//我的信息
Intent intent1 = new Intent(this, xinxiActivity.class);
startActivity(intent1);
break;
}
xinxiActivity 我的信息,显示我的名字 我的班级 我的学号 ,我的二维码
// 获取这个登录的用户
user info = ((BaseApplication) getApplication()).getUser();
if (info != null) {
xingming.setText(“姓名 : ” + info.getName());
banji.setText(“班级 : ” + info.getBanji());
xuehao.setText(“学号 : ” + info.getXuehao());
}
//生成的二维码显示出来
CreateQrCode(info);
public void CreateQrCode(user info) {
//将学生的信息存储下来,用的json存下来。
//生成位图
Bitmap bitmap = EncodingUtils.createQRCode(info.toString(), 300, 300,
null);
//存储下来
saveBitmap2Image(bitmap, info.getXuehao() + ".jpg");
}
public void saveBitmap2Image(Bitmap bmp, String filename) {
OutputStream stream = null;
String path = "/sdcard/QrWiFiSign/" + filename;
File file = new File(path);
Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
int quality = 100;
if (file.exists()) {
//如果已经生成过了,就直接拿到本地的图显示出来即可
erweima.setImageBitmap(getLoacalBitmap(path));
return;
}
try {
//拿到存储的流
stream = new FileOutputStream(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 存储下来
bmp.compress(format, quality, stream);
// 设置这个位图
erweima.setImageBitmap(bmp);
}
/**
* 加载本地图片
*
* @param url
* @return
*/
public Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis); // /把流转化为Bitmap图片
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
qiandaoActivity 显示我的所有签到信息,主要列出来所有此学号的签到课程,通过签到课程id,拿到所有的详细信息
QueryBuilder qb = new QueryBuilder(qiandao.class).whereEquals(“xuehao”,
info.getXuehao());
qiandaoinfo = LiteOrmDBUtil.getLiteOrm(). query(qb);
这里通过学号查询,查出所有的签到信息
然后通过签到id,然后找出签到的课程信息,显示出来。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
viewHolder.name = (TextView) convertView
.findViewById(R.id.mingzi);
viewHolder.index = (TextView) convertView
.findViewById(R.id.index);
viewHolder.time = (TextView) convertView
.findViewById(R.id.shijian);
viewHolder.laoshi = (TextView) convertView
.findViewById(R.id.laoshi);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
qiandao item = qiandaoinfo.get(position);
//从课程里面,通过课程id 找到对应的课程信息,此处需要显示它
QueryBuilder qb = new QueryBuilder(kecheng.class).whereEquals(
"index", item.getIndex());
List kecheng = LiteOrmDBUtil.getLiteOrm(). query(
qb);
//如果查到了,拿到第一个就好了,因为我们原则上,不允许同一个课程id出现在 多个课程里面,所以可以保证一个课程id对应一门课程
if (kecheng.size() != 0) {
kecheng tmp = kecheng.get(0);
viewHolder.name.setText(tmp.getName());
viewHolder.index.setText(tmp.getIndex() + "");
viewHolder.time.setText(tmp.getTime());
viewHolder.laoshi.setText(tmp.getLaoshi());
}
return convertView;
}
private final class ViewHolder {
public TextView name;
// 课程index
public TextView index;
// 时间
public TextView time;
// 老师
public TextView laoshi;
}
}
服务端主界面,主要就是创建课程 和 课程列表
chuangjianActivity 创建课程
// 课程index
EditText index;
// 名字
EditText name;
// 时间
TextView time;
// 老师
EditText laoshi;
// 创建课程
TextView chuangjian;
时间响应为:
time.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
initTimeFromPickerListener();
showTimePickerDiaLog();
}
});
//显示时间选择
private void showTimePickerDiaLog() {
calendar = Calendar.getInstance();
new TimePickerDialog(this, timeSetListener,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE), true).show();
}
//时间选择回调,设置我们的时间信息
private void initTimeFromPickerListener() {
timeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
time.setText("时间:" + hourOfDay + ":" + minute);
}
};
}
点击创建,逻辑代码为:
chuangjian.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String tmp1 = index.getText().toString();
String tmp2 = name.getText().toString();
String tmp3 = time.getText().toString();
String tmp4 = laoshi.getText().toString();
// 如果发现哪个为空,就提示让输入
if (tmp1.isEmpty() || tmp2.isEmpty() || tmp3.isEmpty()) {
Toast.makeText(chuangjianActivity.this,
"课程id 名字 时间 老师 都不能为空,请输入完成注册!", Toast.LENGTH_SHORT)
.show();
return;
}
int index = 0;
// id 转换为整数,不行则确定课程id不正确,需要重输入
try {
index = Integer.valueOf(tmp1);
} catch (java.lang.NumberFormatException ex) {
Toast.makeText(chuangjianActivity.this, "课程ID只能是数字!",
Toast.LENGTH_SHORT).show();
return;
}
//存储下来课程信息
LiteOrmDBUtil.saveData(new kecheng(index, tmp2, tmp3, tmp4));
//显示创建成功
Toast.makeText(chuangjianActivity.this, "创建课程成功!",
Toast.LENGTH_SHORT).show();
//关闭此界面
finish();
}
});
二维码存储的位置在
“/sdcard/QrWiFiSign/”下面
com\yecc\scancode 这个里面就是核心的二维码扫码了,直接用的三方的库,不用关心具体实现。
CaptureActivity.java 主要的扫码界面
ImagecheckActivity.java 图片选择的界面
Myalbumlist.java 图片选择的列表item
服务器端代码是:
fuwuduanActivity 主要显示菜单,完成两个功能:创建课程和所有课程
具体实现为:
switch (arg0.getId()) {
case R.id.chuangjian:
//启动创建课程界面
Intent intent = new Intent(this, chuangjianActivity.class);
startActivity(intent);
break;
case R.id.suoyoukecheng:
// 所有课程界面
Intent intent1 = new Intent(this, suoyouActivity.class);
startActivity(intent1);
break;
}
chuangjianActivity 创建课程界面
主要元素:
// 课程index
EditText index;
// 名字
EditText name;
// 时间
TextView time;
// 老师
EditText laoshi;
时间点击处理逻辑:
time.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//设置时间点击处理
initTimeFromPickerListener();
//显示时间选择对话框
showTimePickerDiaLog();
}
});
initTimeFromPickerListener 接收到时间选择的时候,设置下时间
private void initTimeFromPickerListener() {
timeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
time.setText("时间:" + hourOfDay + ":" + minute);
}
};
}
弹出时间选择界面 timeSetListener 是回调方法。
private void showTimePickerDiaLog() {
calendar = Calendar.getInstance();
new TimePickerDialog(this, timeSetListener,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE), true).show();
}
点击创建课程的代码:
chuangjian = (TextView) findViewById(R.id.chuangjian);
chuangjian.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String tmp1 = index.getText().toString();
String tmp2 = name.getText().toString();
String tmp3 = time.getText().toString();
String tmp4 = laoshi.getText().toString();
// 如果发现哪个为空,就提示让输入
if (tmp1.isEmpty() || tmp2.isEmpty() || tmp3.isEmpty()) {
Toast.makeText(chuangjianActivity.this,
"课程id 名字 时间 老师 都不能为空,请输入完成注册!", Toast.LENGTH_SHORT)
.show();
return;
}
int index = 0;
// id 转换为整数,不行则确定课程id不正确,需要重输入
try {
index = Integer.valueOf(tmp1);
} catch (java.lang.NumberFormatException ex) {
Toast.makeText(chuangjianActivity.this, "课程ID只能是数字!",
Toast.LENGTH_SHORT).show();
return;
}
//存储下此课程
LiteOrmDBUtil.saveData(new kecheng(index, tmp2, tmp3, tmp4));
//弹出创建成功
Toast.makeText(chuangjianActivity.this, "创建课程成功!",
Toast.LENGTH_SHORT).show();
//关掉此界面
finish();
}
});
suoyouActivity 所有课程界面
此界面是个list,然后设置适配器,查询到所有课程显示出来
detlist = (ListView) findViewById(R.id.detlist);
detlist.setAdapter(new tbViewAdapter(this));
//查询所有课程
kechenginfo = LiteOrmDBUtil.getLiteOrm(). query(kecheng.class);
界面每个元素的界面更新逻辑:
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
//加载布局
convertView = mInflater.inflate(R.layout.list_fuwu_item, null);
// 初始化view
viewHolder.name = (TextView) convertView
.findViewById(R.id.mingzi);
viewHolder.index = (TextView) convertView
.findViewById(R.id.index);
viewHolder.time = (TextView) convertView
.findViewById(R.id.shijian);
viewHolder.laoshi = (TextView) convertView
.findViewById(R.id.laoshi);
viewHolder.qiandao = (TextView) convertView
.findViewById(R.id.qiandao);
viewHolder.yiqiandao = (TextView) convertView
.findViewById(R.id.yiqiandao);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
//获取到课程
final kecheng item = kechenginfo.get(position);
if (item != null) {
viewHolder.name.setText("名字:" + item.getName());
viewHolder.index.setText("Id:" + item.getId_index() + "");
viewHolder.time.setText(item.getTime());
viewHolder.laoshi.setText("老师:" + item.getLaoshi());
} else {
return convertView;
}
// 点击签到。我们启动二维码扫码界面,进行处理。
//index 是此课程的id,我们做关联学生信息的,学生这里我们会存下来学号,作为标识
viewHolder.qiandao.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent1 = new Intent(suoyouActivity.this,
CaptureActivity.class);
index = item.getId_index();
//启动返回时候接受参数,具体在onActivityResult里面处理返回
startActivityForResult(intent1, SCANNIN_GREQUEST_CODE);
}
});
//已签到,点击进入已签到学生,启动传入参数课程id
viewHolder.yiqiandao.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent1 = new Intent(suoyouActivity.this,
yiqiandaoActivity.class);
intent1.putExtra("index", item.getId_index());
startActivity(intent1);
}
});
return convertView;
}
private final class ViewHolder {
public TextView name;
// 课程index
public TextView index;
// 时间
public TextView time;
// 老师
public TextView laoshi;
// 签到
public TextView qiandao;
// 已签到
public TextView yiqiandao;
}
}
我们看下扫码后的处理:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case SCANNIN_GREQUEST_CODE:
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
//拿到结果
String result = bundle.getString(“result”);
// Log.i(“logxxxxx”, bundle.getString(“result”));
//结果转换成user
user userInfo = gson.fromJson(result, user.class);
// 通过学号值和课程id,来确定下是否此学生已经签到了此课,如果签了就提示签过了
否则签到
QueryBuilder qb = new QueryBuilder(qiandao.class)
.whereEquals(“xuehao”, userInfo.getXuehao())
.whereAppendAnd().whereEquals(“id_index”, index);
List tmp = LiteOrmDBUtil.getLiteOrm(). query(
qb);
if (tmp.size() == 0) {
// 如果此学号没有,就可以存储了
LiteOrmDBUtil.saveData(new qiandao(index, userInfo
.getXuehao()));
Toast.makeText(this, “课程签到成功”, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, “此学生已经签到了”, Toast.LENGTH_LONG).show();
}
}
break;
}
}
yiqiandaoActivity 已签到的学生界面:
//拿到课程id
index = getIntent().getIntExtra(“index”,0);
detlist.setAdapter(new tbViewAdapter(this));
// 查询此学号在签到列表进行检索
QueryBuilder qb = new QueryBuilder(qiandao.class).whereEquals(
“id_index”, index);
//查到签到信息
qiandaoinfo = LiteOrmDBUtil.getLiteOrm(). query(qb);
在列表里面更新的代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.xinxi, null);
viewHolder.xingming = (TextView) convertView.findViewById(R.id.xingming);
viewHolder.banji = (TextView) convertView.findViewById(R.id.banji);
viewHolder.xuehao = (TextView) convertView.findViewById(R.id.xuehao);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
qiandao item = qiandaoinfo.get(position);
// 从课程里面,通过课程id 找到对应的课程信息,此处需要显示它
QueryBuilder qb = new QueryBuilder(user.class).whereEquals(
"xuehao", item.getXuehao());
List tmp = LiteOrmDBUtil.getLiteOrm(). query(qb);
// 如果查到了,拿到第一个就好了
if (tmp.size() != 0) {
user u = tmp.get(0);
viewHolder.xingming.setText("姓名 : " + u.getName());
viewHolder.banji.setText("班级 : " + u.getBanji());
viewHolder.xuehao.setText("学号 : " + u.getXuehao());
}
return convertView;
}
private final class ViewHolder {
// 姓名
TextView xingming;
// 班级
TextView banji;
// 学号
TextView xuehao;
}
}
qiandaoActivity 我的签到,通过我的学号,去签到里面查找,然后查到的课程id,从课程id里面找课程,然后显示出来。
// 存储下来这个登录的用户,后面需要用
user info = ((BaseApplication) getApplication()).getUser();
// 查询此学号在签到列表进行检索
QueryBuilder qb = new QueryBuilder(qiandao.class).whereEquals(“xuehao”,
info.getXuehao());
qiandaoinfo = LiteOrmDBUtil.getLiteOrm(). query(qb);
更新view的界面:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
viewHolder.name = (TextView) convertView
.findViewById(R.id.mingzi);
viewHolder.index = (TextView) convertView
.findViewById(R.id.index);
viewHolder.time = (TextView) convertView
.findViewById(R.id.shijian);
viewHolder.laoshi = (TextView) convertView
.findViewById(R.id.laoshi);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
qiandao item = qiandaoinfo.get(position);
//从课程里面,通过课程id 找到对应的课程信息,此处需要显示它
QueryBuilder qb = new QueryBuilder(kecheng.class).whereEquals(
"id_index", item.getId_index());
List kecheng = LiteOrmDBUtil.getLiteOrm(). query(
qb);
//如果查到了,拿到第一个就好了,因为我们原则上,不允许同一个课程id出现在 多个课程里面,所以可以保证一个课程id对应一门课程
if (kecheng.size() != 0) {
kecheng tmp = kecheng.get(0);
viewHolder.name.setText("课程名字:"+tmp.getName());
viewHolder.index.setText("课程id:"+tmp.getId_index() + "");
viewHolder.time.setText(tmp.getTime());
viewHolder.laoshi.setText("老师:"+tmp.getLaoshi());
}
return convertView;
}
private final class ViewHolder {
public TextView name;
// 课程index
public TextView index;
// 时间
public TextView time;
// 老师
public TextView laoshi;
}
}