Android开发项目--跑腿APP-跑儿

跑儿是一款跑腿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;

    }

}
}