【安卓开发之图片分享应用1:登录功能的实现】

发布于:2023-01-10 ⋅ 阅读:(450) ⋅ 点赞:(0)


一、开发过程中踩中的坑以及解决方案


1. 连接云端MySQL出现java.lang.NoClassDefFoundError: Failed resolution of: Ljava/sql/SQLTy

问题分析: 我使用的mysql-connector-java-8.0版本号过高

解决方案: 将版本换成mysql-connector-java-5.1左右的即可

官网下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.49


2. 数据库连接池的连接connect只能使用一次com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.


问题分析: 原因很简单, 这里数据库的连接connection是一个static的,程序共享这一个connection。所以第一次对数据库操作没问题,当把connection关闭后,第二次还想操作数据库时connection肯定不存在了,如果一个程序中使用一个共同的staticconnection时,这种问题就很容易出现。


解决方案: 使用conn.isValid(int timeout)方法判断该连接是否失效, 失效则重新获取连接即可 , timeout 单位是秒, 失效则返回false , 有效则返回true

if(!conn.isValid(1)){
	conn = DriverManager.getConnection(url,user,pwd);
}


二、建立数据库以及用户信息表

在这里插入图片描述

1. 建立数据库




在这里插入图片描述


2. 建立用户信息表语句

建完数据库之后,在刚刚建立的数据库中建立用户信息表

create table users (
	id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
	username VARCHAR(100) Not NULL,
	password VARCHAR(100) Not NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

3. 往用户信息表插入信息

我们往该用户信息表中插入一条用户信息,该用户用来测试登录功能。

insert into users(username,password)
VALUES ('admin','666666');


三、登录功能的实现

我们使用Android StudiologinActivity模板连接云端MySQL来进行登录功能的开发, 当然使用本地MySQL也是可以的, 也就是改一下ip地址而已。
在这里插入图片描述


1. 创建LoginActivity

新建一个空项目(想必各位都会), 然后鼠标右键点击app->New->Activity->Login Activity进行创建, 如下图所示
创建Login Activity




创建好之后就会发现多了这些东西,一个是data文件夹,另一个是ui.login文件夹,以及layout布局里面的activity_login.xml登录布局, 虽然文件很多, 但是对我们要改的却是很少, 我们只需要修改ui.login里面的LoginActivity , LoginViewModel, 以及data里面的LoginDataSource即可。
login activity内容


下面是Android Studio生成的Login Activity界面

登录界面



2. 设置权限

如果是使用云端MySQL需要添加网络权限,在AndroidManifest里面添加下面代码即可

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

权限



3. 创建MySQL数据库连接池进行登录信息验证

最好还是使用接口,直接连接数据库进行操作是不符合开发模式的

注意: 按理说MySQL连接和SQL语句查询是分开的,为了方便我将他们放在一个文件里了

3.1 添加MySQL连接依赖

下载MySQL依赖包: https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.49


选择Project查看模式
选择Project查看模式


然后找到app下面的libs文件夹,将下载好的MySQL依赖包添加进去
在这里插入图片描述


鼠标右键点击添加的MySQL依赖,选择Add As Library

在这里插入图片描述


可以打开这个依赖说明添加成功了
发现可以打开

3.2 Mysql连接工具类

鼠标右键New一个DButils数据库连接工具类
在这里插入图片描述


然后输入数据库的ip地址、用户名以及密码。
如果是本地的数据库可以使用localhost或者127.0.0.1

import android.util.Log;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DBUtils {
    private static final String driver = "com.mysql.jdbc.Driver";
    private static final String url = "jdbc:mysql://(你云端MySQL的IP地址或者是本地IP地址):3306/picture_app?useUnicode=true&characterEncoding=UTF-8";
    private static final String user = "(输入你数据库的用户名)";
    private static final String pwd = "(输入你数据库的密码)";

    private static Connection conn=null;
    private static int jumper=111;
    private static String userid;
    private static String nickname;

    static{
        try {
            Class.forName(driver);
            Log.e("驱动加载: ","成功!");//测试用的
        }
        catch (Exception e){
            Log.e("驱动加载: ","失败!");
            e.printStackTrace();
        }
        try {
            conn=DriverManager.getConnection(url, user, pwd);
            Log.e("连接数据库: ","成功!");
        }
        catch (Exception e){
            Log.e("连接数据库: ","失败!");
            e.printStackTrace();
        }
    }


    public static void linkLoginsql(String username, String password) {
        try {
        	//验证是否用户名以及密码是否正确
            String logSql = "Select * from users where username='"+ username+ "'and password='"+ password+ "'";
            //判断连接是否失效,失效则重新获取连接
            if(!conn.isValid(1)){
                conn = DriverManager.getConnection(url,user,pwd);
            }
            PreparedStatement stmt = conn.prepareStatement(logSql);

            ResultSet rs = stmt.executeQuery(logSql);

            // 获取跳转判断
            if(rs.next()){
                jumper=233;
                userid=rs.getString("username");
                nickname=rs.getString("nickname");
            }else{
                jumper=777;
            }
            System.out.println(jumper);
            rs.close();
            stmt.close();

        }
        catch (Exception e){
            e.printStackTrace();
        }

        //关闭数据库
        if(conn!=null){
            try {

                conn.close();

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    //获取跳转判断
    public static int getjumper(){
        return jumper;
    }
    //获取用户ID
    public static String getuserid(){
        return userid;
    }
    //获取用户昵称
    public static String getnickname(){
        return nickname;
    }
}


4. 将Login Activity与MySQL工具类连接起来

我们只需要修改ui.login里面的LoginActivity , LoginViewModel, 以及data里面的LoginDataSource即可

4.1 改写LoginActivity

1. 改写登录按钮监听器:
    点击登录按钮时,会对输入的username和password进行验证,那么就需要调用MySQL连接工具类的DBUtils.linkLoginsql方法,如果查询成功则DBUtils里面的jumper就会被赋值233,否则赋值777,这个是判断是否登录成功的标志。我们看到在代码的结尾调用了loginViewModel.login方法,所以我们还需要到LoginViewModel该类里面进行登录判断的编写。
在这里插入图片描述

代码如下:
LoginActivity:

//设置点击事件
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //在线程中调用数据库
                Thread t1 = new Thread(new Runnable() {
                    public void run() {

                        DBUtils.linkLoginsql(usernameEditText.getText().toString(),passwordEditText.getText().toString());
                    }
                });

                t1.start();
                //在数据库连接完成之前暂停其他活动
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                loadingProgressBar.setVisibility(View.VISIBLE);
                loginViewModel.login(usernameEditText.getText().toString(),passwordEditText.getText().toString());
            }
        });

2. 改写登录验证成功后的事件:

当验证用户名和密码正确时,也就是登录成功,我们需要从登录界面跳转到首页

在这里插入图片描述

代码如下:
LoginActivity:

        loginViewModel.getLoginResult().observe(this, new Observer<LoginResult>() {
            @Override
            public void onChanged(@Nullable LoginResult loginResult) {
                if (loginResult == null) {
                    return;
                }
                loadingProgressBar.setVisibility(View.GONE);
                if (loginResult.getError() != null) {
                	//显示登录失败
                    showLoginFailed(loginResult.getError());
                }
                if (loginResult.getSuccess() != null) {
                    updateUiWithUser(loginResult.getSuccess());
                    //添加登录跳转,登录成功就跳转到首页
                    Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                    LoginActivity.this.startActivity(intent);
                    updateUiWithUser(loginResult.getSuccess());
                }
                setResult(Activity.RESULT_OK);

                //Complete and destroy login activity once successful
                //finish();这个注释掉,不然会结束掉这个activity,也就是登录界面消失

            }
        });


4.2 改写LoginViewModel

loginViewModel

代码如下:
LoginViewModel:

        public void login(String username, String password) {
        // can be launched in a separate asynchronous job
        Result<LoggedInUser> result = loginRepository.login(username, password);

        //判断是否登录成功
        if (DBUtils.getjumper() == 233) {
            //登录成功
            LoggedInUser data = ((Result.Success<LoggedInUser>) result).getData();
            loginResult.setValue(new LoginResult(new LoggedInUserView(data.getDisplayName())));
        } else {
            //登录失败
            loginResult.setValue(new LoginResult(R.string.login_failed));
        }
    }


4.3 改写LoginDataSource

用于显示登录成功后的用户名
在这里插入图片描述

代码如下:
LoginDataSource:

public class LoginDataSource {

    public Result<LoggedInUser> login(String username, String password) {

        try {
            // TODO: handle loggedInUser authentication
            LoggedInUser fakeUser =
                    new LoggedInUser(
                            //修改显示的用户昵称
                            java.util.UUID.randomUUID().toString(),
                            DBUtils.getnickname());
            return new Result.Success<>(fakeUser);
        } catch (Exception e) {
            return new Result.Error(new IOException("Error logging in", e));
        }
    }

    public void logout() {
        // TODO: revoke authentication
    }
}



5. 登录成功后跳转的主页面MainActivity

效果演示
也就是为了查看登录成功后能不能跳转到首页而随便写的,所以很丑

在这里插入图片描述

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="14dp"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/editText"
        android:text="首页"
        android:textSize="64dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button_Send"
        android:text="登录"
        app:layout_constraintStart_toStartOf="@id/editText"
        app:layout_constraintTop_toBottomOf="@id/editText"
        android:layout_marginLeft="15dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity:

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.pictureapp.ui.login.LoginActivity;

public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		//登录按钮,在首页点击后重新回到登录页面
        Button btn_Send = findViewById(R.id.button_Send);
        btn_Send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"正在进入...",Toast.LENGTH_LONG).show();
                Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                startActivity(intent);
            }
        });
    }
}



6. 实现启动APP后直接跳转到登录界面

其实很简单,只需要在AndroidManifest里面讲LoginActivity与MainActivity的位置交换,也就是将启动第一次呈现的页面变成登录页面

交换后
在这里插入图片描述

最后大功告成,启动App即可。
想对Android Studio的LoginActivity进一步了解的可以查看相关的资料。


网站公告

今日签到

点亮在社区的每一天
去签到