【Android学习之路】之从零开始做一个小项目(一)

   日期:2020-05-14     浏览:236    评论:0    
核心提示:最近在学Android(初学者吖),写下这个【Android学习之路】系列记录一下自己学习的过程,欢迎阅读~????本文目录目前进度准备阶段开发工具以及方向构思要实现的功能计划第一阶段UI展示功能展示目前进度① 总体页面框架基本成型,初始界面和登录界面经过一定的美化② 注册和登录功能已经实现,密码采用MD5算法进行加密存储③ 能成功连接SQLite数据库并进行数据的CRUD操作④ 手机验证码登录功能进行至一半(采用的是MobTech平台)准备阶段开发工具以及方向构思我用的开发工具是And数据库

最近在学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"?>
<LinearLayout 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">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@mipmap/welcome"
        android:adjustViewBounds="true">
    </ImageView>
    <TextView
        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" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <RelativeLayout
            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">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/teacher_ico"
                android:layout_margin="10dp"
                android:src="@mipmap/teacher_ico"/>
            <TextView
                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"/>
        </RelativeLayout>
        <TextView
            android:id="@+id/canzhao"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true" />
        <RelativeLayout
            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">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/student_ico"
                android:layout_margin="10dp"
                android:src="@mipmap/student_ico"/>
            <TextView
                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"/>
        </RelativeLayout>
        <TextView
            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" />
        <ImageView
            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">
        </ImageView>
    </RelativeLayout>

</LinearLayout>

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;


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) {
        
        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;


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 15):
相关教程可参考:快速激活Navicat Premium 12

打开后连接我从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两个表,每个页面的设计也会在第二阶段弄出来,不过刚学不久,在很多地方遇到了障碍,在努力克服中,继续加油叭!

下一阶段会在这周更新出来,然后在本文附上链接~
对了,安卓连接SQLite数据库的一些具体介绍我会在近期发表一篇博客~

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

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服