Android app 登陆注册
所有app第一步都是登陆注册
如果你想做一个app,那么登陆注册功能是最基本的功能之一,简单介绍一下Android app登陆注册功能,客户端使用mvvm模式,jetpack全家桶,数据库用sqlite。后端用的springboot框架,数据库为mysql。
布局
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.07" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.27" />
<EditText
android:id="@+id/editTextNumberPassword"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="72dp"
android:ems="10"
android:hint="密码"
android:inputType="numberPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.343"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
<EditText
android:id="@+id/editTextTextPersonName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:ems="10"
android:hint="账号"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.35"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.54" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.6538988" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="登陆"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline3" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.7619699" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="注册"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
</androidx.constraintlayout.widget.ConstraintLayout>
还有注册界面的布局
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=".LoginActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline6"
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:orientation=“horizontal”
app:layout_constraintGuide_percent=“0.07” />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.27" />
<EditText
android:id="@+id/editTextTextPersonName2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:ems="10"
android:hint="account"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline6" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.54" />
<EditText
android:id="@+id/editTextNumberPassword2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:ems="10"
android:hint="password"
android:inputType="numberPassword"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline7" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:text="Register"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline8" />
</androidx.constraintlayout.widget.ConstraintLayout>
登陆
运用jetback首先要对账号登陆做一个数据类Account
package com.example.chiditan.shuchu;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity
public class Account {
@PrimaryKey(autoGenerate = true)
int id;
@ColumnInfo
private int account;
@ColumnInfo
private String password;
public Account(int account, String password) {
this.account = account;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAccount() {
return account;
}
public void setAccount(int account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
随后创建一个dao接口,用于处理sqlite
package com.example.chiditan.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import com.example.chiditan.shuchu.Account;
import java.util.List;
import javax.sql.DataSource;
@Dao
public interface Accountdao {
@Update
void updataAccount(Account...accounts);
@Insert
void insertAccount(Account...accounts);
@Query("select * from Account where account = :account1")
List<Account> queryAccount(int account1);
@Query("select * from Account where account = :password & account =:account")
List<Account> queryPassword(int account,String password);
@Query("select * from Account where id =1")
LiveData<Account> getAccountlive();
}
创建viewmodel类
package com.example.chiditan.ViewModel;
import android.app.Application;
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.room.Update;
import com.example.chiditan.dao.Accountdao;
import com.example.chiditan.database.Accountdatabase;
import com.example.chiditan.shuchu.Account;
public class AccountViewModel extends AndroidViewModel{
private Accountdao accountdao;
private LiveData<Account> accountlive;
public LiveData<Account> getAccountlive() {
return accountlive;
}
public AccountViewModel(@NonNull Application application)
{
super(application);
Accountdatabase accountdatabase=Accountdatabase.getAccountdatabase(application);
accountdao=accountdatabase.getAccountdao();
accountlive=accountdao.getAccountlive();
}
static class InsterAsyncTask extends AsyncTask<Account,Void,Void>
{
private Accountdao accountdao;
public InsterAsyncTask(Accountdao accountdao) {
this.accountdao = accountdao;
}
@Override
protected Void doInBackground(Account... accounts) {
accountdao.insertAccount(accounts);
return null;
}
}
static class UpdataAsyncTask extends AsyncTask<Account,Void,Void>
{
private Accountdao accountdao;
public UpdataAsyncTask(Accountdao accountdao) {
this.accountdao = accountdao;
}
@Override
protected Void doInBackground(Account... accounts) {
accountdao.updataAccount(accounts);
return null;
}
}
public void InsertAccount(Account...accounts)
{
new InsterAsyncTask(accountdao).execute(accounts);
}
public void UpdataAccount(Account...accounts)
{
new UpdataAsyncTask(accountdao).execute(accounts);
}
}
创建database
package com.example.chiditan.database;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import com.example.chiditan.dao.Accountdao;
import com.example.chiditan.shuchu.Account;
@Database(entities = {Account.class},version = 1,exportSchema = false)
public abstract class Accountdatabase extends RoomDatabase {
private static Accountdatabase INSTANCE;
public static synchronized Accountdatabase getAccountdatabase(Context context)
{
if(INSTANCE==null)
{
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),Accountdatabase.class,"account_database")
.allowMainThreadQueries()
.build();
}
return INSTANCE;
}
public abstract Accountdao getAccountdao();
}
最后登录activit
package com.example.chiditan;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.chiditan.ViewModel.AccountViewModel;
import com.example.chiditan.dao.Accountdao;
import com.example.chiditan.shuchu.Account;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.List;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity
{
private Button login_but, register_but;
private TextView user_text, password_text;
LiveData<Account> accountlive;
AccountViewModel accountViewModel;
public Response response;
public String account1 = null;
Accountdao accountdao;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
password_text = findViewById(R.id.editTextNumberPassword);
user_text = findViewById(R.id.editTextTextPersonName);
login_but = findViewById(R.id.button);
register_but = findViewById(R.id.button2);
accountViewModel = ViewModelProviders.of(this).get(AccountViewModel.class);
accountViewModel.getAccountlive().observe(this, new Observer<Account>()
{
//时刻更新数据,自动显示上次注册成功的账号密码
@Override
public void onChanged(Account account)
{
if (account != null)
{
int account_text = 0;
String password1_text = "";
account_text = account.getAccount();
password1_text = account.getPassword();
password_text.setText(password1_text);
user_text.setText(String.valueOf(account_text));
}
}
});
//点击跳转到登陆界面
register_but.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
});
//点击登陆按钮
login_but.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
RequestBody formBody = new FormBody.Builder()
.add("account", user_text.getText().toString())
.add("password", password_text.getText().toString())
.build();
OkHttpClient client = new OkHttpClient();
//发送账号信息
Request request = new Request.Builder()
.url("http://10.0.2.2:8080/Login")
.post(formBody)
.build();
Response response = null;
response = client.newCall(request).execute();
String s = response.body().string();
int res = Integer.valueOf(s);
Log.d(s, "获取返回值");
//根据后端反应确定是否登陆成功
if (res == 1)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Toast.makeText(getApplicationContext(), "未注册账号",
Toast.LENGTH_SHORT).show();
}
});
} else
{
if (res == 2)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Toast.makeText(getApplicationContext(), "密码错误",
Toast.LENGTH_SHORT).show();
}
});
}
//登陆成功跳转到主页面
if (res == 3)
{
Intent intent = new Intent();
intent.setClass(MainActivity.this, MainActivity2.class);
Bundle bundle = new Bundle();
startActivity(intent);
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Toast.makeText(getApplicationContext(), "登陆成功",
Toast.LENGTH_LONG).show();
;
}
});
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
}).start();
}
});
注册页面
package com.example.chiditan;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProviders;
import com.example.chiditan.ViewModel.AccountViewModel;
import com.example.chiditan.dao.Accountdao;
import com.example.chiditan.database.Accountdatabase;
import com.example.chiditan.shuchu.Account;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.json.JSONObject;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class LoginActivity extends AppCompatActivity {
Accountdatabase accountdatabase;
Accountdao accountdao;
private Button register_but2;
private TextView user_text,password_text;
AccountViewModel accountViewModel;
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
password_text =findViewById(R.id.editTextNumberPassword2);
user_text =findViewById(R.id.editTextTextPersonName2);
register_but2 = findViewById(R.id.button3);
accountViewModel = ViewModelProviders.of(this).get(AccountViewModel.class);
//点击注册按钮
register_but2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
try {
RequestBody formBody = new FormBody.Builder()
.add("account", user_text.getText().toString())
.add("password", password_text.getText().toString())
.build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://10.0.2.2:8080/Register")
.post(formBody)
.build();
Response response = client.newCall(request).execute();
String s = response.body().string();
int res= Integer.valueOf(s);
Log.d(s, "获取返回值");
//根据后端的回应发送确定下一步动作
if(res==1)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"该账号已注册,请使用此账号直接登录或使用其他账号注册",Toast.LENGTH_SHORT).show();
}
});
}
else
{
if(res==3)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"密码错误",Toast.LENGTH_SHORT).show();
}
});
}
else
//注册成功将本地的数据库进行更新
{
Account account=new Account(Integer.valueOf(user_text.getText().toString()).intValue(),password_text.getText().toString());
if(accountViewModel.getAccountlive().getValue()==null)
{
accountViewModel.InsertAccount(account);
}
else
{
account.setId(1);
accountViewModel.UpdataAccount(account);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"注册成功",Toast.LENGTH_LONG).show();;
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
}
后端
登陆
package com.example.ditanbao.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@RestController
@org.springframework.stereotype.Controller
public class LoginController
{
private static final long serialVersionUID = 1L;
@Autowired
private JdbcTemplate jdbcTemplate;
public LoginController()
{
super();
}
@ResponseBody
@PostMapping("Login")
public int doPost(@RequestParam("account") String account, @RequestParam("password") String password)
{
System.out.println("account:" + account + "\npassword:" + password); // 打印出来看一看
String result = "";
int res=0;
Map result1=null;
Map result2=null;
String sqlQuery = "select * from table_user_password where userName=" + account;
try
{
result1 = (Map) jdbcTemplate.queryForMap(sqlQuery); // 先查询同样的账号(比如手机号)是否存在
}catch (Exception e)
{ };
if (result1==null)
{ // 模拟登陆账号、密码验证
result="账号不存在";
System.out.println(result);
res=1;
} else
{
String sqlQuery1 = "select * from table_user_password where username= '"+account+"' and userpassword= '" + password+"'";
try
{
result2=(Map) jdbcTemplate.queryForMap(sqlQuery1);
}catch (Exception e)
{ };
if (result2==null)
{
result="密码不对";
res=2;
System.out.println(result);
}else
{
res=3;
result="登录成功";
System.out.println(result);
}
}
return res;
}
}
注册
package com.example.ditanbao.Controller;
import com.example.ditanbao.domain.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import java.util.Map;
@RestController
@org.springframework.stereotype.Controller
public class RegisterController
{
@Autowired
private JdbcTemplate jdbcTemplate;
private static final long serialVersionUID = 1L;
public RegisterController()
{
super();
}
@ResponseBody
@PostMapping("Register")
public int doPost(@RequestParam("account") String account,@RequestParam("password") String password)
{
//String account=account1.getAccount();
//String password=account1.getPassword();
System.out.println("account:" + account + "\npassword:" + password); // 打印出来看一看
String resMsg = "";
/* 这里我们做一个最简单的注册逻辑,当然,你的实际业务可以相当复杂 */
int res=0;
Map result = null;
Map result2 =null;
int[] result1;
String sqlQuery = "select * from table_user_password where userName=" + account;
// 查询类操作返回一个ResultSet集合,没有查到结果时ResultSet的长度为0
try
{
result = (Map) jdbcTemplate.queryForMap(sqlQuery); // 先查询同样的账号(比如手机号)是否存在
}catch (Exception e)
{ };
if (result!=null)
{ // 已存在
res=1;
resMsg = "该账号已注册,请使用此账号直接登录或使用其他账号注册";
System.out.println(resMsg);
}
else
{ // 不存在
String sqlInsertPass = "insert into " + "table_user_password" + "(userName,userPassword) values('" + account + "','" + password + "')";
result1 = jdbcTemplate.batchUpdate(sqlInsertPass); // 插入帐号密码
if (result1.length > 0)
{
String sqlQueryId = "select userId from " + "table_user_password" + " where userName='" + account + "'";
try
{
result2 = (Map) jdbcTemplate.queryForMap(sqlQueryId); // 查询新增记录的userId
}catch (Exception e)
{ };
if (result2!=null)
{
res=2;
resMsg = "注册成功";
System.out.println(resMsg);
}else {
res=3;
resMsg="注册失败";
}
}
}
return res;
}
}