最近在学Android(初学者吖),写下这个【Android学习之路】系列记录一下自己学习的过程,欢迎阅读~

本文目录

    • 目前进度
  • 准备阶段
    • 开发工具以及方向构思
    • 要实现的功能计划
  • 第一阶段
    • UI展示
    • 功能展示


目前进度

① 总体页面框架基本成型,初始界面和登录界面经过一定的美化
② 注册和登录功能已经实现,密码采用MD5算法进行加密存储
③ 能成功连接SQLite数据库并进行数据的CRUD操作
④ 手机验证码登录功能进行至一半(采用的是MobTech平台)

准备阶段

开发工具以及方向构思

我用的开发工具是Android Studio,是谷歌基于IntelliJ IDEA开发的IDE,因为习惯于用IDEA写Java,所以我选择使用用Android Studio来进行安卓开发,而不是Eclipse(而且谷歌已经停止对Eclipse Android开发工具的一切支持)。

附上我用的版本的百度网盘链接:
Android Studio:链接:https://pan.baidu.com/s/1y2uXHEUl0ungSwA2eaAO7A 提取码:twmm
SDK: 链接:https://pan.baidu.com/s/1OdKp84vJnbMcm8ky-L28AQ 提取码:h5zi

模拟器我用的是夜神,使用效果还可以,同样附上链接:

链接:https://pan.baidu.com/s/1JOI0bWH1aOvP1gpc4-79pQ
提取码:odn9

— — — — — — — — — — — — — — — — — —
构思自己要做的项目时,方向是和学校相关的,因为这样也比较贴近我的生活,更加熟悉一些,哈哈。然后本取名鬼才给该项目和APP均取名为:SchoolSystem,哈哈,不过现在我发现这个名字在手机里显示不全,后半截直接省略号了

要实现的功能计划

功能方面我的计划是:
① 分为教师和学生两种登录方式(密码采用MD5加密),登录后所能使用的功能是不同的(拿【学习】页面来说老师能出题和修改学生的分数等,学生只能查看成绩结果和分析以及做题等)
② 老师注册和登录时有一定的限制(我提前准备好可以注册的手机号,老师注册的时候比学生多出手机短信验证这一限制),然后在登录后学生需进行身份认证,认证成功后可享受全部功能,否则只有【计划】这一页面可供使用
③ 【学习】页面有学生的成绩绘制成的图表分析,以及自己的所有成绩查询(和全班的成绩),然后在该页面会实现一个可以做题的功能(教师在该页面可出题,然后学生在该页面做题)
④ 【计划】这一页面可供大家写下自己的计划(可设置为自己可见和全部人可见)
⑤ 如果能力达到的条件下,完善【论坛】页面,连接云数据库,大家可在其中发表一些内容


第一阶段

UI展示

APP启动后会进入初始的选择登录身份的界面,如下图(是我手机上的截屏):

APP的图标我采用了AS里提供的炒鸡好用的Image Asset功能进行制作,好处是基本能适应各种机型,包括图标是圆形,设计界面如下图:

选择登录身份的初始界面InitActivity的布局采用了LinearLayout垂直方向线性布局,页面中有ImageView组件显示我设计的欢迎那一张图片和底部的图片,然后是“请选择您的身份”和“Copyright”的TextView组件,下面部分我采用了RelativeLayout相对布局,并在其中嵌套了一个相对布局用于教师选择和学生选择的位置控制,使其具有更好地适应能力,该activity_init.xml文件源代码如下:

<?xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:background="@mipmap/bg1"    android:padding="3dp"    tools:context=".InitActivity">    android:layout_width="match_parent"        android:layout_height="wrap_content"        android:src="@mipmap/welcome"        android:adjustViewBounds="true">        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginStart="8dp"        android:layout_marginTop="10dp"        android:layout_marginEnd="8dp"        android:padding="8dp"        android:background="@drawable/translucent2"        android:lineSpacingExtra="4sp"        android:text="请选择您的身份"        android:textAlignment="center"        android:textSize="20sp"        android:textStyle="bold" />    android:layout_width="match_parent"        android:layout_height="match_parent">        android:id="@+id/ChooseTeacher"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@drawable/translucent2"            android:layout_toLeftOf="@+id/canzhao"            android:layout_marginRight="45dp"            android:layout_marginTop="50dp">            android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:id="@+id/teacher_ico"                android:layout_margin="10dp"                android:src="@mipmap/teacher_ico"/>            android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="18sp"                android:text="我是教师"                android:layout_centerHorizontal="true"                android:textColor="#576B95"                android:layout_marginTop="5dp"                android:layout_below="@id/teacher_ico"                android:textStyle="bold"/>                android:id="@+id/canzhao"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerHorizontal="true" />        android:id="@+id/ChooseStudent"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@drawable/translucent2"            android:layout_toRightOf="@+id/canzhao"            android:layout_marginLeft="45dp"            android:layout_marginTop="50dp">            android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:id="@+id/student_ico"                android:layout_margin="10dp"                android:src="@mipmap/student_ico"/>            android:id="@+id/nameLogined"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="18sp"                android:text="我是学生"                android:layout_centerHorizontal="true"                android:textColor="#576B95"                android:layout_marginTop="5dp"                android:layout_below="@id/student_ico"                android:textStyle="bold"/>                android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="@drawable/translucent2"            android:lineSpacingExtra="4sp"            android:text="Copyright © 2020 Henry.  All Rights Reserved"            android:layout_marginTop="300dp"            android:textAlignment="center"            android:textSize="12sp"            android:textStyle="bold" />        android:id="@+id/welcomebottom"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:src="@mipmap/welcomebottom"            android:adjustViewBounds="true">            

emm,这个代码的颜色有些刺眼哈哈,接下来分别是教师和学生登录页面(因为手机短信验证功能还没调试成功,所以教师页面暂时也是用户名+密码的注册和登录形式):


成功登录后跳转一个新的Activity,其中能通过点击底部的导航栏在4个Fragment中切换
(暂时还未设计出其他三个页面的布局框架,目前初步定下【我的】页面):

在【我的】页面中,点击【关于】可跳转至【关于我】页面,里面简单写了一点我的联系方式,然后可以通过点击图标直接拨打电话或发送短信(需要同意相应的权限):

该【关于我】页面的调用拨号和发短信功能实现具体代码如下(我在这里把我的号码改成123456了嘻嘻):

package com.henry.schoolsystem.ui.me;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.widget.ImageButton;import com.henry.schoolsystem.R;public class AboutActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_about);        ImageButton imageButton = (ImageButton) findViewById(R.id.imageButton_phone); //获取电话图片按钮        ImageButton imageButton1 = (ImageButton) findViewById(R.id.imageButton_sms); //获取短信图片按钮        imageButton.setOnClickListener(l); //为电话图片按钮设置单击事件        imageButton1.setOnClickListener(l);//为短信图片按钮设置单击事件    }    //创建监听事件对象    View.OnClickListener l = new View.OnClickListener() {        @Override        public void onClick(View v) {            Intent intent = new Intent(); //创建Intent对象            switch (v.getId()) {       //根据ImageButton组件的id进行判断                case R.id.imageButton_phone:              //如果是电话图片按钮                    intent.setAction(intent.ACTION_DIAL); //调用拨号面板                    intent.setData(Uri.parse("tel:123456")); //设置要拨打的号码                    startActivity(intent); //启动Activity                    break;                case R.id.imageButton_sms:             //如果是短信图片按钮                    intent.setAction(intent.ACTION_SENDTO); //调用发送短信息                    intent.setData(Uri.parse("smsto:123456")); //设置要发送的号码                    intent.putExtra("sms_body", "您好!"); //设置要发送的信息内容                    startActivity(intent); //启动Activity            }        }    };}

功能展示

首先是注册/登录界面功能
写入数据库需要使用SQLiteOpenHelper类,该类是一个抽象类,需要创建该类的派生类,我这里是DBOpenHelper,源代码如下:

package com.henry.schoolsystem.ui.login;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;/** * Created by Henry */public class DBOpenHelper extends SQLiteOpenHelper {    public static final String USER_INFO = "userInfo";    public static final String USER_LOGIN = "userLogin";    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {        super(context, name, null, version);     //重写构造方法并设置factory为null    }    @Override    public void onCreate(SQLiteDatabase db) {        /**         * 当该子类被实例化时会创建指定名的数据库,在onCreate中创建用户信息表和登录信息表         * **/        db.execSQL("CREATE TABLE IF NOT EXISTS " + USER_INFO + "( "                + "_id  INTEGER PRIMARY KEY AUTOINCREMENT, "                + "userName VARCHAR, "                + "nickName VARCHAR, "                + "sex VARCHAR, "                + "qq VARCHAR, "                + "wechat VARCHAR, "                + "motto VARCHAR "                + ")");        db.execSQL("CREATE TABLE IF NOT EXISTS " + USER_LOGIN + "( "                + "_id  INTEGER PRIMARY KEY AUTOINCREMENT, "                + "userName VARCHAR, "                + "password VARCHAR"                + ")");    }    @Override    // 重写基类的onUpgrade()方法,以便数据库版本更新    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        //提示版本更新并输出旧版本信息与新版本信息        System.out.println("---版本更新-----" + oldVersion + "--->" + newVersion);    }}

注册/登录页面的Activity中的代码如下(以学生页面SLoginActivity为例):

package com.henry.schoolsystem.ui.login;import androidx.appcompat.app.AppCompatActivity;import android.content.ContentValues;import android.content.Intent;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;import com.henry.schoolsystem.R;import com.henry.schoolsystem.SMainActivity;import com.henry.schoolsystem.TMainActivity;import com.henry.schoolsystem.utils.MD5Utils;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;public class SLoginActivity extends AppCompatActivity {    private DBOpenHelper dbOpenHelper;  //定义DBOpenHelper,用于与数据库连接    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_slogin);        //创建DBOpenHelper对象,指定名称、版本号并保存在databases目录下        dbOpenHelper = new DBOpenHelper(SLoginActivity.this, "student.db", null, 1);        final EditText usernameEditText = (EditText) findViewById(R.id.add_username);           //获取添加用户名的编辑框        final EditText passwordEditText = (EditText) findViewById(R.id.add_password);  //获取添加密码的编辑框        final Button btn_Save = (Button) findViewById(R.id.register2);      //获取注册按钮        final Button btn_Login = (Button) findViewById(R.id.login2);     //获取登录按钮        //登录        btn_Login.setOnClickListener(new View.OnClickListener() {  //单击登录按钮查看是否有该用户以及密码是否正确            @Override            public void onClick(View v) {                SQLiteDatabase db = dbOpenHelper.getWritableDatabase();                String key = usernameEditText.getText().toString();  //获取输入的登录名                //用Cursor游标进行查询                Cursor cursor = db.query("userLogin", null                        , "userName = ?", new String[]{key}, null, null, null);                ArrayList<Map<String, String>> resultList = new ArrayList<Map<String, String>>();   //创建ArrayList对象,用于保存查询出的结果                while (cursor.moveToNext()) {  // 遍历Cursor结果集                    Map<String, String> map = new HashMap<>();  // 将结果集中的数据存入HashMap中                    // 取出查询记录中第2、3列的值                    if (resultList.size() != 0) break;                    map.put("userName", cursor.getString(1));                    map.put("password", cursor.getString(2));//将查询出的数据存入ArrayList中                    resultList.add(map);                }                if (resultList.size() == 0) {  //如果数据库中没有数据                    Toast.makeText(SLoginActivity.this, "用户名不存在,请重新输入或注册!", Toast.LENGTH_SHORT).show();                    cursor.close();                } else {                    // 否则比较password是否一致                    String passwordIn = passwordEditText.getText().toString(); //获取输入的密码                    String passwordNeed = cursor.getString(cursor.getColumnIndex("password"));  //获取需要填写的密码                    if (passwordNeed.equals(MD5Utils.md5(passwordIn))) {   //只是比较内容,不能用==                        Toast.makeText(SLoginActivity.this, "登录成功!"+key+",欢迎您~", Toast.LENGTH_LONG).show();                        cursor.close();                        Intent intent = new Intent(SLoginActivity.this, SMainActivity.class);  //登录成功跳转至学生端                        startActivity(intent);                    } else {                        Toast.makeText(SLoginActivity.this, "密码错误,请重新输入!", Toast.LENGTH_SHORT).show();                    }                }            }        });        //注册        btn_Save.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String username = usernameEditText.getText().toString();  //获取填写的用户名                String password = passwordEditText.getText().toString(); //获取填写的密码                if (username.equals("")||password.equals("")){  //如果填写的用户名或密码为空时                    Toast.makeText(SLoginActivity.this, "用户名或密码为空,请重新填写", Toast.LENGTH_SHORT).show();                }else {                    // 调用insertData()方法,实现插入用户数据                    insertData(dbOpenHelper.getReadableDatabase(), username, password);                    // 显示提示信息                    dbOpenHelper.close();                    Toast.makeText(SLoginActivity.this, "注册成功!可以登录啦", Toast.LENGTH_SHORT).show();                }            }        });    }    //创建insertData()方法实现插入数据    private void insertData(SQLiteDatabase readableDatabase, String username, String password) {        ContentValues values = new ContentValues();        values.put("userName", username);       //保存用户名        values.put("password", MD5Utils.md5(password));  //保存密码        try {            readableDatabase.insert("userLogin", null, values);//执行插入操作        }        catch (SQLException e) {            Log.e("SQLiteDatabase", "Error inserting " + values, e);        }    }}

当填入的用户名或密码中有一个为空时,注册失败同时通过Toast弹出消息提示框,注册成功并登录后会弹出一个欢迎的消息提示框,如下图:

对了,上一步中,如果密码输入错误或是用户名不存在会有如下的登录失败提示:

然后该注册的密码在数据库中是经过MD5算法加密后存储的,MD5加密算法的java类如下:

package com.henry.schoolsystem.utils;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;/** *  创建一个md5()方法 *  通过 MessageDigest 的 getInstance()方法 *  获取数据加密对象 digest,然后通过该对象的 digest()方法对密码进行加密 *  由于注册登录涉及密码,需要对用户的密码进行 MD5 算法加密 */public class MD5Utils {    // md5 加密的算法    public static String md5(String text){        MessageDigest digest = null;        try {            //获取数据指纹对象            digest = MessageDigest.getInstance("md5");            //字节数组            byte[] result = digest.digest(text.getBytes());            //16进制转换            StringBuffer sb = new StringBuffer();            //获取所有字节进行转换            for (byte b: result){                //使用『与算法』,java使用unicode字符,所以每个字符占位两个                // 需要与两位16进制最大值进行与运算,获取number值                int number = b & 0xff;                //number值转换字符串                String hex = Integer.toHexString(number);                if (hex.length() == 1){                    //若转换后的字符长度等于1则进行字符串拼接                    sb.append("0"+hex);                }else {                    sb.append(hex);                }            }            return sb.toString();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();            //发送异常return空字符串            return "";        }    }}

查看SQLite数据库中的相关记录(我使用的是Navicat Premium 12):

相关教程可参考:快速激活Navicat Premium 12

附上Navicat Premium 12网盘链接(PJ教程看上面的链接):
链接:https://pan.baidu.com/s/1Dj1m5g6eFVrLMEmQbyWnkA
提取码:yzxa

打开后连接我从AS中导出的数据库student.db,查看userLogin表:


— — — — — — — — — — — — — — — — — — — — — — — — — — — —
短信验证功能可以有很多平台使用,我选择的是MobTech(免费的),可由此查看相关文档:SMSSDK for Android
需要在AndroidManifest.xml中添加以下权限:

以及在项目根目录的build.gradle中添加依赖,不过你可能还需要像我一样添加上两个库:

以及在使用SMSSDK模块的build.gradle中,添加MobSDK插件和扩展:

// 添加插件apply plugin: 'com.mob.sdk'// 在MobSDK的扩展中注册SMSSDK的相关信息MobSDK {    appKey "申请Mob的appkey"    appSecret "申请Mob的AppSecret"    SMSSDK {}}

这些设置在文档中都有:SMSSDK for Android,写的挺详细的,该短信验证功能的具体代码实现和调用在下一阶段会完成~


第一阶段主要是构造好了基本的大的框架和初级的登录功能,数据库的详细的各个关系模式将在最近几天设计出来,目前只有userLoginuserInfo两个表,在数据库数据的操作上还存在一些bug,第二阶段将会解决一些本阶段中的问题,不过刚学不久,在很多地方遇到了障碍,在努力克服中,继续加油叭!

第二阶段传送:【Android学习之路】之从零开始做一个小项目(二)
对了,关于SQLite数据库的一些基本操作这里有位老哥写的挺不错的:10分钟理解Android数据库的创建与使用(附详解和示例代码)
该安卓项目中使用到的SQLite数据库的相关操作我会在后续总结出来~

(ps:因为目前代码中一些地方写的还不够好,在最终项目完成后会将项目源码上传至GitHub,目前发表出的代码中如有问题和需改进的地方希望大家积极指出~)

更多相关文章

  1. mono for android 第三课--页面布局
  2. 混合开发H5页面嵌入ios/Android及echarts图表问题总结
  3. Android(安卓)ViewPager 如何判断当前页面是从前一页还是后一页
  4. android页面布局时定义控件ID时@id/XX和@+id/xx 有什么区别?
  5. 利用Cordova对H5页面进行APP开发打包
  6. Android底部菜单(Fragment控制切换多个页面)
  7. [Android]如何做一个崩溃率少于千分之三噶应用app(8)-多渠道模块
  8. Android小项目一:微信精选
  9. 【Android】利用表格布局,Android中xml文件与java的交互制作登录

随机推荐

  1. Android启动画面实现
  2. Android概述
  3. 【Android】精通Android(安卓)UI设计
  4. android第二行代码总结:二、UI
  5. ListView之setEmptyView的问题
  6. Android异步处理二:使用AsyncTask异步更新
  7. android TextView实现跑马灯效果
  8. 【Android】性能优化的一些方法
  9. Android(安卓)ListView 去除边缘阴影、选
  10. Android(安卓)textview 显示不全的问题