栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android答题APP的设计与实现

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android答题APP的设计与实现

还没有整理完,待续……

学校开了Android课,最后让交一个大作业。正好拿来练练手,记录下思路。也希望能给有需要的朋友们一些帮助。恩,纯小白教程,大神们可以绕路了。

作业的题目是这样的:

考试APP系统:

1)要求有用户登陆功能:从远程服务器进行登陆验证。
2)要有考试测试界面,主要是选择、判断、简答题目测试。
3)要有统计成绩界面和错题显示界面。

评分标准:

1、界面设计占评分的30%
2、系统运行正确; 功能完善;工作量充分; 系统实现有一定的技术的难度。50%
3、要求有适当的系统主要模块的文档说明和代码注释。
4、直接将数据库文件(数据库一定要备份成SQL语句格式,指明数据库)和项目文件提交。

乍一看挺简单的,真要研究起来,写的实用一些,还真有点不知如何下手,那跟着我的思路,一起来吧!恩,不想看思路的,可以直接戳Android源码下载源码来看了。

功能需求设计:

登录注册
答题:选择题,判断题,简答题
答题得分计算
错题查看

最后效果

总体思路

总体思路是这样的,App通过http连接服务器,进行登录或者注册服务,登录成功之后,服务器查询数据库并以json的形式返回试题数据。App接收数据之后,解析并存到本地数据库,然后展示给用户答题。点击交卷按钮后,进行评分并可进行错题查看。内容比较杂乱,大家可以根据目录来快速查看自己需要或者感兴趣的地方。

数据库设计

首先,就登录注册的功能来说,得先有一个用户表,包含用户名,密码,id号这些基本的内容。我在这里又加了一个权限字段,用来返回状态。(设置权限字段,方便日后进行扩展,可设置用不同数字代表不同等级或身份)

tbl_user_info

其次,就是题库了。为了使项目具有实用性,减小安装包体积,便于更新修正,题库同样也需要放在服务器上才合适。

tbl_question

jsp程序

jsp依赖了两个jar包,分别是连接mysql的驱动:mysql-connector-java-5.1.34-bin还有生成json用的:json 。为了减少代码的耦合性,这里采用MVC模式进行设计。(自以为是MVC)。目录结构如下:

登录注册

1.连接数据库

数据库操作类,封装了连接,查询,关闭数据库的方法。大家如果使用这部分代码,别忘了把数据库连接常量改成自己的。

/
 public HashMap login(String username, String password) {

  HashMap hashMap = new HashMap();
  // 获取Sql查询语句
  String logSql = "select perssion from userinfo where username ='"
    + username + "' and password ='" + password + "'";
  System.out.println(logSql);
  // 获取DB对象
  DBManager sql = DBManager.createInstance();
  sql.connectDB();

  hashMap.put("permission", "-1");
  hashMap.put("username", username);

  // 操作DB对象
  try {
   ResultSet rs = sql.executeQuery(logSql);
   if (rs.next()) {
    hashMap.put("permission", rs.getInt(1) + "");
    System.out.print("权限===" + rs.getInt(1) + "t");
    sql.closeDB();
    return hashMap;
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
  sql.closeDB();
  return hashMap;
 }

 
 public HashMap register(String username, String password) {

  HashMap hashMap = new HashMap();
  hashMap.put("username", username);
  hashMap.put("msg", "notok");
  if (this.namerepeat(username)) {
   hashMap.put("msg", "rename");
  } else {
   // 获取Sql查询语句
   String regSql = "insert into userinfo(username,password) values('"
     + username + "','" + password + "')";
   System.out.println(regSql);

   // 获取DB对象
   DBManager sql = DBManager.createInstance();
   sql.connectDB();

   int ret = sql.executeUpdate(regSql);
   if (ret != 0) {
    hashMap.put("msg", "ok");
    sql.closeDB();
    return hashMap;
   }
   sql.closeDB();
  }

  return hashMap;
 }

 
 public Boolean namerepeat(String username) {
  String checkSql = "select username from userinfo where username ='"
    + username + "'";
  // 获取Sql查询语句
  System.out.println(checkSql);

  // 获取DB对象
  DBManager sql = DBManager.createInstance();
  sql.connectDB();

  // 操作DB对象
  try {
   ResultSet rs = sql.executeQuery(checkSql);
   if (rs.next()) {

    sql.closeDB();
    return true;
   }
  } catch (SQLException e) {
   e.printStackTrace();
  }
  sql.closeDB();
  return false;
 }
}

登录注册部分的代码基本一样,只把 serv.login变成serv.reglet就可以了。

/
 abstract int getLayoutId();

 
 void initView() {
 }

 
 void initData() {
 }

 
 void initListener() {
 }

 
 @Override
 public void onClick(View v) {
  switch (v.getId()) {
   default:
    processClick(v);
    break;
  }
 }

 
 void processClick(View v) {
 }
}

SplashActivity(启动页面)

绑定activity_splash布局文件,延时2秒钟跳转主页面。

public class SplashActivity extends baseActivity {

 @Override
 int getLayoutId() {
  return R.layout.activity_splash;
 }
 @Override
 void initData() {
  //延时2s,跳转。
  new Handler().postDelayed(new Runnable() {
   @Override
   public void run() {
    //跳转主页面
    Intent intent = new Intent(SplashActivity.this, MainActivity.class);
    startActivity(intent);
    finish();
   }
  }, 2000);
 }

}

LoginActivity(登录页面)

java代码LoginActivity.java

public class LoginActivity extends baseActivity {
 private static final int REQUEST_SIGNUP = 0;
 EditText et_username;
 EditText et_password;
 Button btn_login;
 TextView tv_signup;

 @Override
 int getLayoutId() {
  return R.layout.activity_login;
 }

 @Override
 void initView() {
  //通过id找控件
  et_username = (EditText) findViewById(R.id.input_username);
  et_password = (EditText) findViewById(R.id.input_password);
  btn_login = (Button) findViewById(R.id.btn_login);
  tv_signup = (TextView) findViewById(R.id.link_signup);
 }

 @Override
 void initListener() {
  //登录按钮,注册链接设置点击监听事件
  btn_login.setonClickListener(this);
  tv_signup.setonClickListener(this);
 }

 @Override
 void processClick(View v) {
  switch (v.getId()) {
   //点击登录按钮,执行登录操作
   case R.id.btn_login:
    login();
    break;
   //如果点击了注册链接,则跳转到注册页面
   case R.id.link_signup:
    Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
    startActivityForResult(intent, REQUEST_SIGNUP);
    finish();
    //动画效果
    overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
    break;
   default:
    break;
  }
 }

 
 public void login() {
  //如果内容不合法,则直接返回,显示错误。
  if (!validate()) {
   onLoginFailed();
   return;
  }
  //输入合法,将登录按钮置为不可用,显示圆形进度对话框
  btn_login.setEnabled(false);
  final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog);
  progressDialog.setIndeterminate(true);
  progressDialog.setMessage("登录中...");
  progressDialog.show();
  //获取输入内容
  String username = et_username.getText().toString().trim();
  String password = et_password.getText().toString().trim();
  //联网,获取数据
  OkGo.get(CONFIG.URL_LOGIN)
    .params("username", username)
    .params("password", password)
    .execute(new StringCallback() {
     @Override
     public void onSuccess(String s, Call call, Response response) {
      Gson gson = new Gson();
      JsonLoginBean jsonLoginBean = gson.fromJson(s, JsonLoginBean.class);
      //如果得到权限>0,则登录成功。
      if (jsonLoginBean.getPermission() > 0) {
Log.e("zwc", "onSuccess: ===");
onLoginSuccess();
progressDialog.dismiss();
      } else {
onLoginFailed();
progressDialog.dismiss();
      }
     }
    });
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == REQUEST_SIGNUP) {
   if (resultCode == RESULT_OK) {
    this.finish();
   }
  }
 }

 
 @Override
 public void onBackPressed() {
  // Disable going back to the MainActivity
  moveTaskToBack(true);
 }

 
 public void onLoginSuccess() {
  btn_login.setEnabled(true);
  Intent intent = new Intent(LoginActivity.this, MainActivity.class);
  startActivity(intent);
  finish();
 }

 
 public void onLoginFailed() {
  Toast.makeText(getbaseContext(), "登陆失败", Toast.LENGTH_LONG).show();
  btn_login.setEnabled(true);
 }

 
 public boolean validate() {
  //设置初值,默认为合法
  boolean valid = true;

  //获取输入内容
  String email = et_username.getText().toString().trim();
  String password = et_password.getText().toString().trim();

  //判断账号
  if (email.isEmpty()) {
   et_username.setError("请输入你的账号");
   valid = false;
  } else {
   et_username.setError(null);
  }
  //判断密码
  if (password.isEmpty()) {
   et_password.setError("请输入你的密码");
   valid = false;
  } else {
   et_password.setError(null);
  }

  return valid;
 }
}

布局文件activity_login.xml



 

  

  
  
   
  

  
  
   
  

  

  
 


SignupActivity(注册页面)

SignupActivity.java

public class SignupActivity extends baseActivity {

 EditText _nameText;
 EditText _emailText;
 EditText _passwordText;
 EditText _reEnterPasswordText;
 Button _signupButton;
 TextView _loginlink;

 @Override
 int getLayoutId() {
  return R.layout.activity_signup;
 }

 @Override
 void initView() {
  //根据id找控件
  _nameText = (EditText) findViewById(R.id.input_name);
  _emailText = (EditText) findViewById(R.id.input_username);
  _passwordText = (EditText) findViewById(R.id.input_password);
  _reEnterPasswordText = (EditText) findViewById(R.id.input_reEnterPassword);
  _signupButton = (Button) findViewById(R.id.btn_signup);
  _loginlink = (TextView) findViewById(R.id.link_login);
  _signupButton.setonClickListener(this);
  _loginlink.setonClickListener(this);
 }

 @Override
 void processClick(View v) {
  switch (v.getId()) {
   case R.id.btn_signup:
    signup();
    break;
   case R.id.link_login:
    //点击登录连接,跳转到登录页面
    Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
    startActivity(intent);
    finish();
    overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
    break;
   default:
    break;
  }
 }

 public void signup() {
  //判断是否合法
  if (!validate()) {
   onSignupFailed(0);
   return;
  }
  _signupButton.setEnabled(false);

  //显示圆形进度条对话框
  final ProgressDialog progressDialog = new ProgressDialog(SignupActivity.this,
    R.style.AppTheme_Dark_Dialog);
  progressDialog.setIndeterminate(true);
  progressDialog.setMessage("创建账号...");
  progressDialog.show();
  //获取数据
  String username = _nameText.getText().toString();
  String password = _passwordText.getText().toString();
//  联网获取数据
  OkGo.get(CONFIG.URL_SIGNUP)
    .params("username", username)
    .params("password", password)
    .execute(new StringCallback() {
     @Override
     public void onSuccess(String s, Call call, Response response) {
      Gson gson = new Gson();
      JsonSignupBean jsonSignupBean = gson.fromJson(s, JsonSignupBean.class);
      //如果得到返回消息为ok,则注册成功。
      if (jsonSignupBean.getMsg().equals("ok")) {
Log.e("zwc", "onSuccess: 注册成功");
onSignupSuccess();
//对话框消失
progressDialog.dismiss();
      } else {
onSignupFailed(1);
progressDialog.dismiss();
      }
     }
    });
 }

 
 public void onSignupSuccess() {
  _signupButton.setEnabled(true);

  Intent intent = new Intent(SignupActivity.this, MainActivity.class);
  startActivity(intent);
  finish();
 }

 
 public void onSignupFailed(int i) {
  if (i == 1) {
   Toast.makeText(getbaseContext(), "该用户名已经被注册", Toast.LENGTH_LONG).show();
  } else {
   Toast.makeText(getbaseContext(), "注册失败", Toast.LENGTH_LONG).show();
  }
  _signupButton.setEnabled(true);
 }

 
 public boolean validate() {
  boolean valid = true;
  //从控件中获取数据
  String name = _nameText.getText().toString();
  String password = _passwordText.getText().toString();
  String reEnterPassword = _reEnterPasswordText.getText().toString();
  //检测账号是否正确
  if (name.isEmpty()) {
   _nameText.setError("账号不能为空");
   valid = false;
  } else {
   _nameText.setError(null);
  }
  //检测密码是否正确
  if (password.isEmpty()) {
   _passwordText.setError("请输入密码");
   valid = false;
  } else {
   _passwordText.setError(null);
  }
  //检测重复密码是否正确
  if (reEnterPassword.isEmpty() || !(reEnterPassword.equals(password))) {
   _reEnterPasswordText.setError("两次密码不一致");
   valid = false;
  } else {
   _reEnterPasswordText.setError(null);
  }
  return valid;
 }
}

布局文件 activity_signup.xml




 

  

  
  

   
  

  
  

   
  

  
  

   
  

  

  

 


AnswerActivity ,AnswerFragment(答题页面)

回答问题的页面。当到达AnswerActivity页面的时候,会联网获取题目数据,并将题目存入本地数据库。然后通过viewpager绑定n个AnswerFragment,对题目进行展示。作答后,进行存库操作。(n由题目数量决定)

public class AnswerActivity extends baseActivity implements Chronometer.onChronometerTickListener {

 private Chronometer chronometer;
 private ViewPager vp_answer;
 private ArrayList fragmentlists;
 private int minute = 0;
 private int second = 0;
 private alertDialog.Builder builder;
 private ArrayList a;
 private Button btn_previous;
 private Button btn_submit;
 private Button btn_next;
 private int nowpager = 0;
 private List messages;
 private String type;

 @Override
 int getLayoutId() {
  return R.layout.activity_answer;
 }

 
 @Override
 void initView() {
  chronometer = (Chronometer) findViewById(R.id._chro_exam);
  vp_answer = (ViewPager) findViewById(R.id.vp_answer);
  btn_previous = (Button) findViewById(R.id._btn_previous);
  btn_submit = (Button) findViewById(R.id._btn_submit);
  btn_next = (Button) findViewById(R.id._btn_next);
//  获取传递来的变量
  type = getIntent().getExtras().get("type").toString().trim();

//  联网获取数据
  initNet(type);

  btn_previous.setonClickListener(this);
  btn_submit.setonClickListener(this);
  btn_next.setonClickListener(this);
  vp_answer.setonPageChangeListener(new MyonPageChangeListener());
  setChronometer();
 }

 
 private void setChronometer() {
  chronometer.setText(nowtime());
  chronometer.start();
  chronometer.setonChronometerTickListener(this);
  chronometer.setonClickListener(this);
 }

 
 @Override
 public void onChronometerTick(Chronometer chronometer) {
  second++;
  if (second == 59) {
   minute++;
   second = 00;
  }
 }

 
 private String nowtime() {
  if (second < 10) {
   return (minute + ":0" + second);
  } else {
   return (minute + ":" + second);
  }
 }

 
 private void initNet(String type) {
  a = new ArrayList<>();
  fragmentlists = new ArrayList<>();
  Log.e("zwc", "initNet: 开始联网…………");
  //进度条对话框
  final ProgressDialog progressDialog = new ProgressDialog(AnswerActivity.this, R.style.AppTheme_Dark_Dialog);
  progressDialog.setIndeterminate(true);
  progressDialog.setMessage("获取题目中...");
  progressDialog.show();
//  联网
  OkGo.get(CONFIG.URL_GETQUEST1)
    .params("type", type)
    .execute(new StringCallback() {
     @Override
     public void onSuccess(String s, Call call, Response response) {
      Log.i("zwc", "onSuccess: ========---------======" + s);
      //gson解析
      Gson gson = new Gson();
      JsonQuestBean jsonQuestBean = gson.fromJson(s, JsonQuestBean.class);
      messages = jsonQuestBean.getMessages();
      for (int i = 0; i < messages.size(); i++) {
QuestBean questBeanQ = messages.get(i);
questBeanQ.setId(i);
fragmentlists.add(new AnswerFragment(questBeanQ));
LoveDao.insertLove(questBeanQ);
a.add(questBeanQ.getId() + "");
Log.e("zwc", i + "ooooooonSuccessssssssssss: " + questBeanQ.getId() + questBeanQ.getTitle());
      }
//      设置适配器
      vp_answer.setAdapter(new MainAdapter(getSupportFragmentManager()));
      progressDialog.dismiss();
     }

     @Override
     public void onError(Call call, Response response, Exception e) {
      Log.i("zwc", "onError///////////////////");
     }
    });
  Log.e("zwc", "initNet: 联网结束…………");
 }

 
 class MainAdapter extends FragmentPagerAdapter {

  public MainAdapter(FragmentManager fm) {
   super(fm);
  }

  //获取条目
  @Override
  public Fragment getItem(int position) {
   return fragmentlists.get(position);
  }

  //数目
  @Override
  public int getCount() {
   return fragmentlists.size();
  }
 }

 @Override
 void processClick(View v) {
  switch (v.getId()) {
//   点击上一题按钮
   case R.id._btn_previous:
//    如果是第一题,则谈吐司提醒,否则上移一道题
    if (nowpager == 0) {
     Toast.makeText(AnswerActivity.this, "已经到头啦!", Toast.LENGTH_SHORT).show();
    } else {
     vp_answer.setCurrentItem(--nowpager);
    }
    break;
//   点击提交按钮
   case R.id._btn_submit:
//    简答题不进行提交评分
    if (type.equals("3")) {
     Toast.makeText(this, "简答题目前暂不支持评分", Toast.LENGTH_SHORT).show();
     return;
    }
//    否则初始化并展示提交对话框
    initalertDialog();
    builder.show();
    break;
//   点击下一题按钮
   case R.id._btn_next:
//    如果是最后一题,则谈吐司提醒,否则下移一道题
    if (nowpager == fragmentlists.size()) {
     Toast.makeText(AnswerActivity.this, "已经是最后一题了!", Toast.LENGTH_SHORT).show();
    } else {
     vp_answer.setCurrentItem(++nowpager);
    }
    break;
   default:
    break;
  }
 }

 // 弹出是否确认交卷的对话框
 private void initalertDialog() {
  //新建对话框
  builder = new alertDialog.Builder(AnswerActivity.this);
  builder.setTitle("提示");
  builder.setMessage("是否确定交卷?");
  builder.setPositiveButton("确定", new DialogInterface.onClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int which) {
    // TODO: 2017/6/14 交卷操作
//    计算分数
    int grade = 0;
//    判断题
    if (type.equals("2")) {
     for (int i = 0; i < messages.size(); i++) {
//      查询
      QuestBean questBeenA = LoveDao.queryLove(Integer.parseInt(a.get(i)));
//      判断
      if (questBeenA.getAnswer().equals("对") && questBeenA.getMyanswer().equals("A") || questBeenA.getAnswer().equals("错") && questBeenA.getMyanswer().equals("B")) {
grade += 20;
      }
      ;
     }
    }
//    选择题
    else {
     for (int i = 0; i < messages.size(); i++) {
      QuestBean questBeenA = LoveDao.queryLove(Integer.parseInt(a.get(i)));
      if (questBeenA.getAnswer().equals(questBeenA.getMyanswer())) {
grade += 20;
      }
      ;
     }
    }

//    传递分数
    Intent intent = new Intent(AnswerActivity.this, GradeActivity.class);
    intent.putExtra("grade", "" + grade);
//    传递题目列表
    intent.putStringArrayListExtra("timu", a);
    startActivity(intent);
    finish();
   }

  });
  builder.setNegativeButton("取消", null);
 }

 
 private class MyonPageChangeListener implements ViewPager.onPageChangeListener {
  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  }

  @Override
  public void onPageSelected(int position) {
   nowpager = position;
  }

  @Override
  public void onPageScrollStateChanged(int state) {

  }
 }

恩,现在就写了这么多,对于作业来说应该是绰绰有余了。不过还是有很多需要改善的地方。以后有时间的话,会继续完善一下。最后,本文挺长的。真诚的感谢一下你能看到这里。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/156672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号