0%

Android登录客户端

Android登录客户端

​ PS:现在只实现了注册功能,但是登录功能是一个道理,看完注册应该都会。

1、首先搭建登录界面

插一句:利用inputType属性实现EditText输入一行回车换行。

1
android:inputType="text"

注册

代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.15"></RelativeLayout>

<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.7"
android:orientation="vertical">

<com.example.activity.smartparking.CircleImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_marginTop="130dp"
android:src="@drawable/swpu"/>

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="18sp"
android:text="账号"/>
<EditText
android:id="@+id/account_r"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="请输入账号"
android:maxLength="10"
android:layout_gravity="center_vertical"/>
</LinearLayout>

<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="18sp"
android:text="密码"/>
<EditText
android:id="@+id/password_r"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="请输入密码"
android:maxLength="10"
android:layout_gravity="center_vertical"
android:inputType="textPassword"/>
</LinearLayout>

<Button
android:layout_gravity="center"
android:background="@color/buttonLogin"
android:id="@+id/register_r"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"/>

</LinearLayout>

<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.15"></RelativeLayout>

</LinearLayout>

2、信息传输

​ 搭建好了界面之后,就需要解决数据传输的问题。我们需要将输入的账号以及密码信息传输到服务器。

​ 不要忘了加权限!!!(用模拟器的选手本地不要用localhost,请使用10.0.0.2)

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

​ 信息传输我们使用OKhttp,要使用OKhttp,我们需要导入:

1
implementation 'com.squareup.okhttp3:okhttp:3.2.0'

​ 由于OKhttp还是比较底层的,我们还是将OKhttp进行简单的封装比较好用。这里我用了一个github别人封装好的库(忘了是哪个大哥的了,忏悔一下),源码在文末。

​ 然后我们就可以进行数据传输了,我们在Register.Activity中操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import android.content.Intent;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
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.google.gson.Gson;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Response;

public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {

private EditText account,password;
private Button register;
private String str1,str2;
private static String url = "http://10.24.22.247:80/SmartParking/reg1";
private Map<String,String> paramsMap = null;
private CallBackUtil callBackUtil = null;
private String jsonstr = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
init();
}

@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.register_r:
str1 = account.getText().toString();
str2 = password.getText().toString();
//下面这就是OKhttp的操作了,首先在rgister_f中定义好我们需要东西,最后用别人封装好的一句OkhttpUtil.okHttpPostJson(url,jsonstr,callBackUtil)就可以发送OKhttp请求了。
register_f();
OkhttpUtil.okHttpPostJson(url,jsonstr,callBackUtil);
}
}

private void init() {
account = (EditText)findViewById(R.id.account_r);
password = (EditText)findViewById(R.id.password_r);
register = (Button)findViewById(R.id.register_r);
register.setOnClickListener(this);
}

private Object register_f() {
//我们装备传输的数据是Json格式的,json数据写的方法有几种,我是通过先写Map数组,在直接将HashMap转换为json数据。
paramsMap = new HashMap<String, String>();
paramsMap.put("uname",str1);
paramsMap.put("pwd",str2);
Gson gson = new Gson();
jsonstr = gson.toJson(paramsMap);
//callBackUtil是别人封装好的OKhttp库
callBackUtil = new CallBackUtil() {
@Override
public Object onParseResponse(Call call, Response response) throws IOException {
String resp = response.body().string();
if(resp.equals("success")){
Looper.prepare();
Toast.makeText(RegisterActivity.this, "注册成功,请登录", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RegisterActivity.this,Login.class);
startActivity(intent);
Looper.loop();
return null;
}else if (resp.equals("failure")){
Looper.prepare();
Toast.makeText(RegisterActivity.this, "注册失败,请重新注册", Toast.LENGTH_SHORT).show();
Looper.loop();
return null;
}
return null;
}

@Override
public void onFailure(Call call, Exception e) {
Looper.prepare();
Toast.makeText(RegisterActivity.this, "注册失败", Toast.LENGTH_SHORT).show();
Looper.loop();
}

@Override
public void onResponse(Object response) {

}
};
return null;
}
}

3、服务器搭建

​ 我是在本机用Tomcat服务器测试的,关于Tomcat服务器的测试,我就不在这里说了,网上教程很多。

​ 在搭建好了Tomcat服务器之后,我们先提一个小东西,Eclipse的TCP/IP Monitor,这个东西是监听端口数据的,我们可以用它来监听Servlet的请求数据(request)和响应数据(response)。

​ TCP/IP Monitor打开方式:进入菜单 Window->Show View->Other,在弹出框中选择 TCP/IP Monitor 项。

​ 空白处右键选择properties,点击 Add 添加一个新的监控。

监控

监控设置

⭐⭐设置各项属性,其中各属性含义如下:

  • Local monitoring port:本地的监控端口,此监控端口必须未被使用;且设置之后,客户端程序须修改为向此端口发送请求,而不是之前的服务器接收的端口;

  • Host name:服务器地址(这里是本机);

  • Port:服务器端口;

  • Type:HTTP/HTTPS,根据实际使用协议选择;

  • Timeout:monitor在尝试重连之前的等待时间。

    简单来讲,假设你开始访问的地址是:http://10.24.22.247:8080/SmartParking/reg1,现在你就需要将你之前设置的端口改为上面的Local monitoring port端口,即改为http://10.24.22.247:80/SmartParking/reg1,TCP/IP Monitor会将发往端口80的数据转发给你实际用到的端口8080。

    4、服务器处理请求(request)及返回(response)

    ​ 写这个之前我想先说说服务起的相关知识,前文所提到的访问地址,如http://10.24.22.247:8080/SmartParking/reg1之类的信息具体指什么呢?

    ​ 10.24.22.247 是你服务器的ip地址(这里提一句,如果你是在模拟器上运行的话,这里不能填localhost,需要你电脑在公网下面的私网ip(cmd输入ipconfig找到ipv4就是你的ip了,校园网的话可能一段时间会换,自己注意下)。

    ​ 8080就是端口号了,我们电脑的端口很多,只要用不被占用的就行了。

    ​ SmartParking/reg1就是你的SmartParking工程下的某一个servlet,我们通过reg1将真实地址隐藏了(我这里学的不是很明白,懂得应该都能懂,没有学过servlet的建议去B站找找servlet的资源听一下,很简单的,听两节servlet基础就行了)。

    ​ 反正经过上面的东东,我们就可以访问到我们自己的服务器资源了。

    ​ 先把代码列出来(需要自己导入JDBK数据库操作的jar包),简单说一下:就是客户端通过OKhttp发送数据给服务器(这一步就是请求request),服务器如果成功接受了数据,就会首先分析该请求是get还是post,然后在根据他的类型执行不同的方法,get请求执行doGet方法,post请求执行doPost方法(我上传的是post请求,所以只对doPost方法进行了编写)。最后执行完相应的方法之后就会返回响应给客户端,响应数据的写入也在doGet和doPost方法中写,核心内容方法是getWriter().write()。

    ​ 代码中的DBHandle是封装的连接数据库以及curd方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;

    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import com.google.gson.Gson;

    public class RegisterServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // TODO Auto-generated method stub
    super.service(req, resp);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    this.doPost(request, response);
    }

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf-8");
    resp.addIntHeader("ycy", 101);
    System.out.println(req.getRequestURI());
    BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)req.getInputStream(), "utf-8"));
    StringBuffer sb = new StringBuffer("");
    String temp,json;
    while ((temp = br.readLine()) != null) {
    sb.append(temp);
    }
    br.close();
    json = sb.toString();
    Gson gson = new Gson();
    User user = gson.fromJson(json, User.class);
    String uname = user.getUname();
    String pwd = user.getPwd();
    boolean u_exit = false;
    u_exit = exit(uname,u_exit);
    if(u_exit) {
    insert(uname, pwd);
    resp.getWriter().write("success");
    }else {
    resp.getWriter().write("failure");
    }
    }

    private boolean exit(String uname,boolean b_exit) {
    DBHandler db_exit = new DBHandler();
    String sql_select = "select *from user where username=?";
    String a_exit = db_exit.query(sql_select, new String[] {uname});

    /* //判断获得的数据库数据中的username所在的索引区间,username是第一行数据,所有只用判断第一个分节符*所在位置即可
    int a = a_exit.indexOf("*");
    //如果a是-1,表明数据库中没有该username注册,如果不是-1;返回该索引值前的字符串
    if(a != -1) {
    b_exit = a_exit.substring(0,a);
    return b_exit;
    }else {
    return null;
    }*/

    /* //上面这个方法感觉很不方便,是否可以这样,通过索引值是否为-1就可以判断啊,如果是-1则不存在,不然就是存在的,没必要进行其他操作。
    int a = a_exit.indexOf("*");
    //如果a是-1,表明数据库中没有该username账号注册,b_exit为真;如果不是-1,则证明数据库中已经注册过该账号
    if(a != -1) {
    b_exit = false;
    return b_exit;
    }else {
    b_exit = true;
    return b_exit;
    }*/

    //上面这个方法也不行,我们直接判断a_exit是否为空不就好了吗
    //如果a是-1,表明数据库中没有该username账号注册,b_exit为真;如果不是-1,则证明数据库中已经注册过该账号
    if(a_exit.isEmpty()) {
    b_exit = true;
    return b_exit;
    }else {
    b_exit = false;
    return b_exit;
    }
    }

    private void insert(String uname, String pwd) {
    DBHandler db_insert = new DBHandler();
    String sql = "insert into user(username,pwd) values (?,?)";
    db_insert.insert(sql, new String[] {uname, pwd});
    }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.servlet.http.HttpServlet;

public class DBHandler {
String url = "jdbc:mysql://localhost/parking";
String user="root";
String pwd="Qwert592665";
private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
public Connection getConn(){
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, pwd);
}catch(Exception ex){
ex.printStackTrace();
}
return conn;
}
public String query(String sql,String[] args){
String result="";
try{
conn=getConn();
System.out.println(sql);
ps=conn.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ps.setString(i+1, args[i]);
}
rs=ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int count=rsmd.getColumnCount();
System.out.println(count);
while (rs.next()) {
for(int i=1;i<=count;i++){
result+=rs.getString(i)+"*";
}
}
}catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
public boolean insert(String sql,String[] args){
boolean flag=false;
try{
conn=getConn();
System.out.println(sql);
ps=conn.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ps.setString(i+1, args[i]);
}
int i=ps.executeUpdate();
System.out.println(i);
if(i==1){
flag=true;
}
}catch (Exception ex) {
ex.printStackTrace();
}
return flag;
}
public boolean checkUser(String sql,String[] args){
boolean flag=false;
try{
conn=getConn();
ps=conn.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ps.setString(i+1, args[i]);
}
rs=ps.executeQuery();
if(rs.next()){
flag=true;
}
}catch (Exception ex) {
ex.printStackTrace();
}
return flag;
}

public static void main(String[] args){
DBHandler dbh=new DBHandler();
String result=dbh.query(
"select * from book where book_name like ? or book_author like ?",
new String[] { "wandou", "123456" });
System.out.println(result);
}
}

5、最终调试

​ 调试过程遇到很多问题就要自己解决了,但是首先应该明白一点就是要用TCP/IP Monitor来看自己的数据对不对。

调试

​ 左下角和右下角分别是你的request和response,里面有你的响应头和数据,首先分析自己发送的东西有没有问题,最后写东西。

6、源码

​ 项目地址:https://github.com/HuaHuaHuaHe/LoginTest