跑儿是一款跑腿APP,用户可以发布自己的跑腿需求然后跑手可以进行接单来完成相应的“任务”。
开发工具:Android Studio,SQLite Expert Professional,Photoshop
开发语言:Android,Java
1.初始界面
初始界面会有两个按钮,一个登录,一个注册,两个按钮分别加了监听,点击时会出现不同的响应。
2.注册
当点击注册界面时,会弹出一个AlertDialog的注册界面,头像选择采用的是一个网格布局来显示的,用户名跟密码采用了正则表达式来进行判断,当用户名或密码出现特殊字符时系统会弹出一个Toast提示用户名或密码格式错误,并清空你刚才输入的用户名跟密码让你重新输入,当你填写用户名时,会拿你这个用户名在数据库里进行查找比对,如果这个用户名在数据库中存在,则系统会提示用户名已被注册,你可以选择返回主页面直接进行登陆;当所有信息填写无误时点击注册,系统会弹出一个对话框提示你注册成功,点击返回主页登录,Dialog将关闭回到初始界面登录。
3.登陆
点击登录按钮,会弹出一个Dialog,输入注册时的账号跟密码,点击登录按钮,将你输入的账号跟密码去数据库进行进行查找,如果账号密码跟数据库的某条相同,则返回一个true并显示登录成功,否则显示登陆失败,登陆成功后系统会提示你打开地图定位权限,为了后面地图功能的正常运行。
4.管理员模式
管理员账号:liuaichao 密码:123456 进入管理员模式后,会将注册的数据库信息通过ListView呈现出来包括用户名,性别,手机号,头像,点击窗口右上角的按钮,会出现管理,点击管理后,每个用户的后面会出现删除按钮,点击删除可将此用户从数据库中删除,也可以点击对应的CheckBox来进行批量删除,给每个条目上面的CheckBox加监听,点击储存当前CheckBox的选中状态到对应条目的User对象里面去,避免适配器刷新后导致CheckBox恢复初始未选中状态。ListView的Adapter是继承了自己写的一个MyAdapter,为了方便数据的传入。
5.主页
主页是跑儿的订单编辑跟提交界面,左上角为你当前位置的定位,右上角为地图,这里使用了百度地图的API,给你在写起点终点时提供了一个位置参考和您当前位置的官方描述
物品类型采用了ArrayList跟下拉框的配合,使物品类型更加形象的展示出来,具体内容可以输入一些自己对跑手的要求;
点击提交按钮会弹出一个对话框提示订单提交成功,并清空刚才订单输入的信息,点击返回主页将返回到登陆成功界面(注:初始APP未加入金钱建议功能,因为接入第三方支付比如支付宝,微信等,需要企业的营业执照等相关信息的提交,所以未涉及金钱交易)
6.订单
订单界面是单独的一个数据库,为了实现单个用户拥有自己单独的订单,自己想了一个方法:单独建立一个数据库,根据getWritableDatabase()的用法打开或创建数据库,即当存在这个数据库是是打开,不存在时是创建,我想的是通过改变数据库的名字来实现订单的独立,当你登录成功时,获取你的用户名,因为用户名是不可重复的即唯一的,用这个用户名来创建或打开数据库,这样每个账户便有了一个自己唯一的订单管理库,可以查看历史订单跟新订单。每条订单信息包括起点,终点,备注,下单时间,订单状态,取消订单,地图,确认完成按钮,通过date中的toLocaleString()方法获取系统的下单时间来作为之后跑手版的订单唯一标识,状态会显示订单目前的状态,当跑手未接单时状态显示未接单,跑手接单后,会显示已接单,点击确认订单完成按钮后,会显示已完成,取消订单会将订单取消并且将订单从数据库中删除,地图按钮会显示你跟跑手之间的位置,跑手方会给你传一个经纬度坐标,然后跟你的经纬度进行骑行规划,来实时跟踪订单位置。
7.我的
“我的”界面,也就是简单个人信息界面,包括头像跟用户名,点击个人信息会跳转到详细的个人信息界面,点击切换到跑手版将会进入跑手界面,可进行接单操作。
8.个人信息
个人信息界面会从数据库中找到该条记录,然后详细的展示出来,默认用户名是不可修改的,点击密码栏的“点击修改”将进入修改密码的界面,输入旧密码,根据用户名去数据库中找出旧密码进行比对,成功返回true,新密码跟确认新密码进行一次比对,相同返回true,同样的,新密码也有正则表达式的验证,成功后,新密码将填入数据库,系统提示重新登录,确定后进入登陆界面;手机号可以直接修改,点击“保存”后会将修改的信息保存并返回“我的”界面;点击退出账号即退出当前账号,返回登陆界面。
9.跑手版
为了跟好的测试,我们加入了跑手版,也就是接单的模块,这个模块相当于一个大厅效果,所有的用户提交订单号一份数据传入自己私有的数据库,另一份传入“大厅”数据库,跑手版的数据也是有ListViev呈现出来的,点击电话按钮时,会根据你所点条目第position来确定某个用户的订单,然后根据用户注册时输入的手机号通过Uri.parse(“tel:”+tel)来调用系统拨号来给下单者拨号;点击“确认接单”按钮,该订单将从“大厅”数据库中删除,并修改私有数据库的状态为已接单,给下单者一个准确的提示。
下面部分代码(代码太长,有需要的可以在底下评论):
package com.example.thinkpad.apps.ui;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.example.thinkpad.apps.R;
import com.example.thinkpad.apps.dao.IUserDao;
import com.example.thinkpad.apps.dao.impl.UserDaoDBImpl;
import com.example.thinkpad.apps.dao.utils.CheckString;
import com.example.thinkpad.apps.dao.utils.MyOpenHelper;
public class ChangeActivity extends Activity implements View.OnClickListener {
private ImageButton fanhui;
private EditText oldpwd;
private EditText newpwd;
private EditText renewpwd;
private Button enter;
private IUserDao userDao;
private MyOpenHelper mOpenHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change);
fanhui=findViewById(R.id.xg_fanhui);
oldpwd=findViewById(R.id.xg_oldpwd);
newpwd=findViewById(R.id.xg_newpwd);
renewpwd=findViewById(R.id.xg_renewpwad);
enter=findViewById(R.id.xg_enter);
//监听
fanhui.setOnClickListener(this);
enter.setOnClickListener(this);
userDao= UserDaoDBImpl.getDao(this);
mOpenHelper=new MyOpenHelper(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.xg_fanhui:
Intent intent=new Intent(this,PersonActivity.class);
startActivity(intent);
finish();
break;
case R.id.xg_enter:
String old=oldpwd.getText().toString().trim();
String news=newpwd.getText().toString().trim();
String renew=renewpwd.getText().toString().trim();
String name=WelcomeActivity.Noname;
if(CheckString.check(news)){
if(userDao.findUserPwd(old)&&news.equals(renew)){
Toast.makeText(this, "密码修改成功,请重新登录", Toast.LENGTH_SHORT).show();
//数据库进行修改
SQLiteDatabase db=mOpenHelper.getWritableDatabase();
ContentValues contentValues=new ContentValues();
contentValues.put("pwd",news);
db.update("user",contentValues,"name=?",new String[]{name});
db.close();
Intent intent1=new Intent(this,WelcomeActivity.class);
startActivity(intent1);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
finish();
}else if(userDao.findUserPwd(old)==false){
Toast.makeText(this, "旧密码输入不正确,请重新输入", Toast.LENGTH_SHORT).show();
}else if((userDao.findUserPwd(old)==true)&&(news.equals(renew)==false)){
Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this, "密码中含有非法字符或密码长度短", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
package com.example.thinkpad.apps.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.Date;
import com.example.thinkpad.apps.IUserDao2;
import com.example.thinkpad.apps.R;
import com.example.thinkpad.apps.dao.IUserDao3;
import com.example.thinkpad.apps.dao.entity.User;
import com.example.thinkpad.apps.dao.entity.User2;
import com.example.thinkpad.apps.dao.entity.User3;
import com.example.thinkpad.apps.dao.impl.UserDaoDBImpl2;
import com.example.thinkpad.apps.dao.impl.UserDaoDBImpl3;
import com.example.thinkpad.apps.dao.utils.MyOpenHelper;
import com.example.thinkpad.apps.dao.utils.MyOpenHelperPao;
import com.example.thinkpad.apps.map.Ditu;
import java.util.ArrayList;
import java.util.List;
public class jinru extends Activity implements View.OnClickListener {
private TextView dn_didian;
private ImageButton dn_ditu;
private EditText dn_qidian;
private EditText dn_zhongdian;
private EditText dn_jiner;
private EditText dn_neirong;
private Spinner dn_spinner;
private Button dn_tijiao;
private Button dn_zhuye;
private Button dn_dingdan;
private Button dn_wode;
private List<String> list;
private Date loca_time;
private IUserDao2 userDao;
private IUserDao3 userDao3;
private AlertDialog.Builder mBuilder2;
private AlertDialog.Builder mBuilder3;
private AlertDialog alertDialog2;
private AlertDialog alertDialog3;
private static MyOpenHelper mOpenHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zhuye);
//实例化对象
dn_didian=findViewById(R.id.didian);
dn_ditu=findViewById(R.id.ditu);
dn_qidian=findViewById(R.id.zy_qidian);
dn_zhongdian=findViewById(R.id.zy_zhongdian);
dn_jiner=findViewById(R.id.zy_jiner);
dn_neirong=findViewById(R.id.zy_neirong);
dn_spinner=findViewById(R.id.spinner);
dn_tijiao=findViewById(R.id.zy_tijiao);
dn_zhuye=findViewById(R.id.zy_zhuye);
dn_dingdan=findViewById(R.id.zy_dingdan);
dn_wode=findViewById(R.id.zy_wode);
mOpenHelper=new MyOpenHelper(this);
//设置按钮的监听
dn_ditu.setOnClickListener(this);//地图
dn_tijiao.setOnClickListener(this);//提交
dn_zhuye.setOnClickListener(this);//主页
dn_zhuye.setEnabled(false);//主页
dn_dingdan.setOnClickListener(this);//订单
dn_wode.setOnClickListener(this);//我的
dn_didian.setText(Ditu.weizhi);
list = new ArrayList<String>();
list.add("---请选择物品类型---");
list.add("快递");
list.add("食品");
list.add("电子产品");
list.add("大型物品>50kg");
list.add("代购");
list.add("其他");
final ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
dn_spinner.setAdapter(adapter);
//时间
loca_time=new Date();
userDao= UserDaoDBImpl2.getDao(this,WelcomeActivity.Noname,null,1);
userDao3= UserDaoDBImpl3.getDao(this);
//提交成功弹出对话框
mBuilder2=new AlertDialog.Builder(this);
mBuilder2.setTitle("");
mBuilder2.setMessage("订 单 提 交 成 功");
mBuilder2.setPositiveButton("返回主页", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dn_qidian.setText("");
dn_zhongdian.setText("");
dn_jiner.setText("");
dn_neirong.setText("");
alertDialog2.dismiss();
adapter.notifyDataSetChanged();
}
});
alertDialog2=mBuilder2.create();
//返回键监听提示框
mBuilder3=new AlertDialog.Builder(this);
mBuilder3.setTitle("");
mBuilder3.setMessage("您 确 定 要 退 出 吗");
mBuilder3.setPositiveButton("退出", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
alertDialog3.dismiss();
adapter.notifyDataSetChanged();
}
});
mBuilder3.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialog3.dismiss();
adapter.notifyDataSetChanged();
}
});
alertDialog3=mBuilder3.create();
}
public void askGoOn2(){
alertDialog2.show();
}
public void onBackPressed() {
alertDialog3.show();
}
//按钮监听
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.ditu:
Intent intent=new Intent(this, Ditu.class);
startActivity(intent);
this.overridePendingTransition(R.anim.main_in4,R.anim.main_out4);
finish();
break;
case R.id.zy_tijiao://提交订单按钮实现
String name=WelcomeActivity.Noname;
String qidian=dn_qidian.getText().toString();
String zhongdian=dn_zhongdian.getText().toString();
String jiner=dn_jiner.getText().toString();
String neirong=dn_neirong.getText().toString();
String time= loca_time.toLocaleString();
//查找电话
String tel;
tel="";
SQLiteDatabase db=mOpenHelper.getWritableDatabase();
String sql="select * from user where name=?";
Cursor cursor=db.rawQuery(sql,new String[]{name});
while (cursor.moveToNext()){
tel=cursor.getString(cursor.getColumnIndex("tel"));
}
String state="未接单";
User2 u=new User2();
u.setStart(qidian);
u.setFina(zhongdian);
u.setRemark(neirong);
u.setTime(time);
u.setState(state);
u.setNamer(name);
userDao.addUser(u);
//写入add数据库
User3 u1=new User3();
u1.setStart(qidian);
u1.setFina(zhongdian);
u1.setRemark(neirong);
u1.setTime(time);
u1.setState(state);
u1.setNamer(name);
u1.setTel(tel);
userDao3.addUser(u1);
askGoOn2();
break;
case R.id.zy_zhuye:
break;
case R.id.zy_dingdan:
Intent intent1=new Intent(this,ResultActivity2.class);
startActivity(intent1);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
finish();
break;
case R.id.zy_wode:
Intent intent2=new Intent(this,WodeActivity.class);
startActivity(intent2);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
finish();
break;
}
}
}
package com.example.thinkpad.apps.ui;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.thinkpad.apps.R;
import com.example.thinkpad.apps.dao.utils.MyOpenHelper;
public class PersonActivity extends Activity implements View.OnClickListener {
private Button fanhui;
private Button baocun;
private Button tuichu;
private Button xiugai;
private ImageView head;
private TextView zhanghao;
private EditText tel;
private MyOpenHelper mOpenHelper;
private String namer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_person);
//实例化
fanhui=findViewById(R.id.ps_fanhui);
baocun=findViewById(R.id.ps_baocun);
tuichu=findViewById(R.id.ps_tuichu);
xiugai=findViewById(R.id.ps_xiugai);
head=findViewById(R.id.ps_head);
zhanghao=findViewById(R.id.ps_zhanghao);
tel=findViewById(R.id.ps_tel);
mOpenHelper=new MyOpenHelper(this);
//按钮监听
fanhui.setOnClickListener(this);
baocun.setOnClickListener(this);
tuichu.setOnClickListener(this);
xiugai.setOnClickListener(this);
//信息展示
xinxishow();
}
private void xinxishow() {
SQLiteDatabase db=mOpenHelper.getWritableDatabase();
String sql="select * from user where name=?";
Cursor cursor=db.rawQuery(sql,new String[]{WelcomeActivity.Noname});
while(cursor.moveToNext()){
namer=cursor.getString(cursor.getColumnIndex("name"));
head.setImageResource(cursor.getInt(cursor.getColumnIndex("headImg")));//设置头像
zhanghao.setText(namer);
tel.setText(cursor.getString(cursor.getColumnIndex("tel")));
}
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.ps_fanhui://取消
Intent intent3=new Intent(this,WodeActivity.class);
startActivity(intent3);
this.overridePendingTransition(R.anim.main_in2,R.anim.main_out2);
finish();
break;
case R.id.ps_baocun://保存电话
String ntel=tel.getText().toString().trim();
String nname=zhanghao.getText().toString().trim();
SQLiteDatabase db=mOpenHelper.getWritableDatabase();
ContentValues contentValues=new ContentValues();
contentValues.put("tel",ntel);
db.update("user",contentValues,"name=?",new String[]{nname});
db.close();
Toast.makeText(this, "信息保存成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(this,WodeActivity.class);
startActivity(intent);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
finish();
break;
case R.id.ps_xiugai://修改密码
Intent intent1=new Intent(this,ChangeActivity.class);
startActivity(intent1);
break;
case R.id.ps_tuichu://退出
Intent intent2=new Intent(this,WelcomeActivity.class);
startActivity(intent2);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
finish();
break;
}
}
}
package com.example.thinkpad.apps.ui;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.thinkpad.apps.R;
import com.example.thinkpad.apps.dao.IUserDao;
import com.example.thinkpad.apps.dao.impl.UserDaoDBImpl;
import com.example.thinkpad.apps.dao.utils.CheckString;
import com.example.thinkpad.apps.dao.utils.MyOpenHelper;
public class WelcomeActivity extends Activity implements View.OnClickListener{
private Button item_login;
private Button item_reg;
private EditText mEdtLoginname;//用户名输入框
private EditText mEdtLoginpwd;//密码输入框
private Button mBtLogingo;
private Button mBtLogincancel;
private IUserDao userDao;
private Button denglu;
private Button zhuce;
private Dialog dig_login;
private UserDaoDBImpl userDaoDB;
public static String Noname;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_welcome);
userDao=UserDaoDBImpl.getDao(this);
dig_login=new Dialog(this);
dig_login.setContentView(R.layout.login_dig);
dig_login.setTitle("登录");
denglu=(Button) findViewById(R.id.denglu);//登录按钮
zhuce=(Button) findViewById(R.id.zhuce);//注册按钮
//登录界面监控
mEdtLoginname=(EditText)dig_login.findViewById(R.id.edt_loginname);
mEdtLoginpwd=(EditText)dig_login.findViewById(R.id.edt_loginpwd);
mBtLogingo=(Button)dig_login.findViewById(R.id.bt_logingo);
mBtLogincancel=(Button)dig_login.findViewById(R.id.bt_logincancel);
denglu.setOnClickListener(this);
zhuce.setOnClickListener(this);
mBtLogingo.setOnClickListener(this);
mBtLogincancel.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.denglu://登录进入监听
dig_login.show();
break;
case R.id.bt_logingo://登录监听
String name=mEdtLoginname.getText().toString();
String pwd=mEdtLoginpwd.getText().toString();
if(CheckString.check(name)&&CheckString.check(pwd)){
//判断数据库中是否有数据,能否登录
if(userDao.findUserByNameAndPwd(name,pwd)){
Toast.makeText(this, "登陆成功", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "请开启地图定位权限", Toast.LENGTH_SHORT).show();
Noname=name;
Intent intent=new Intent(this,jinru.class);
startActivity(intent);
this.overridePendingTransition(R.anim.main_in1,R.anim.main_out1);
dig_login.cancel();
finish();
}else if(name.equals("liuaichao")&&pwd.equals("123456")){
Toast.makeText(this, "进入管理员模式", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(this,ResultActivity.class);
startActivity(intent);
} else {
Toast.makeText(this, "账号或密码错误,请重新输入", Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(this, "用户名或密码格式错误,请重新输入", Toast.LENGTH_SHORT).show();
}
break;
case R.id.bt_logincancel://取消监听
dig_login.cancel();
break;
case R.id.zhuce:
Toast.makeText(this, "注册", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(this,RegActivity.class);
startActivity(intent);
break;
}
}
}