因为Android 自带SQLite,加上连接mysql会造成一些安全隐患,比如自己ip地址,账号密码的泄露,所以Android直接连接mysql用的地方可能不多,但是多了解一种方案,对自己也是一种提升。
mysql相关配置
我用的jdbc版本是5.1.30
mysql版本是5.7.28,是wampserver直接包装好的,wampserver装好了之后就可以使用
因为之前装的mysql是8.x的,连接mysql的时候出现了错误,不知道是mysql版本的问题还是什么原因。还是推荐5.7吧,mysql这些东西并不是越新版越好,还是要追求稳定的性能。
jdbc驱动包下载好之后,在main文件夹下新建libs文件夹。将jdbc驱动复制到libs中,右键点击驱动包,选择add as libray
在app/bulid gradle 文件中,可以看到下面的
implementation files('src\\main\\libs\\mysql-connector-java-5.1.30-bin.jar')
说明已经加载到依赖中了。
先在数据库中新建myuser数据库(自己定义数据库名),
再在myuser中新建user表
建表语法:
create table user()
name varchar(20) primary key,
password varchar(20),
;
插入数据,先放入一条数据:
insert into user values('yx','123');
现在进行下一步
连接mysql
既然是移动端访问电脑,肯定需要网络,首先在清单文件AndroidManifest 中添加访问网络权限。
<uses-permission android:name="android.permission.INTERNET"/>
然后关闭电脑防火墙,方法有很多,百度上都有。
要注意电脑和手机在同一网络下
已经配置好了之后,先尝试有没有连接,代码很简单,新建一个project,布局什么的都不用动,直接在MainActivity的onCreate方法中新建一个线程:
因为我安装的是wampserver,注意指定mysql端口号的时候最好先在my.ini文件中查看一下是3306还是3308:
MainActivity.java:
import android.os.Bundle;
import android.util.Log;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("MainActivity.this","你好");
new Thread(new Runnable() {
@Override
public void run() {
try {
//加载jdbc驱动
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection cn= DriverManager.getConnection("jdbc:mysql://电脑ip:数据库的端口号/数据库名","用户","数据库密码");
//待查询语句,此时表中只有一条数据: 'yx':'123'
String sql="select * from user";
//创建Statement对象
// Statement 对象用于将 SQL 语句发送到数据库中
Statement st=(Statement)cn.createStatement();
//为了执行 Statement 对象,被发送到数据库的 SQL 语句将被作为参数提供给 Statement 的方法:
//Statement 接口提供了三种执行 SQL 语句的方法:
//executeQuery、executeUpdate 和execute。使用哪一个方法由 SQL 语句所产生的内容决定。
//原理可以参考https://zhidao.baidu.com/question/122589837.html
ResultSet rs=st.executeQuery(sql);
//读取的数据放在rs中,rs应该是一个数据集,此时的rs可以理解为 'name':'yx','password':'123'
while(rs.next()){//读取数据
String name=rs.getString("name");//可以通过列名获取对应的内容
String pass=rs.getString("password")
Log.d("MainActivity.this","用户名:" + name);//打印
Log.d("MainActivity.this","密码:" + pass);
Log.d("MainActivity.this","终于连接好了");
}
//关闭相关连接
cn.close();
st.close();
rs.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}).start();
}
}
然后检查logcat 输出的有没有对应的内容
但是这样只能简单的logcat输出日志,因为Android 中的主线程无法访问网络,如果看过郭神的《第一行代码》,会发现他书中访问网络都是开启子线程,不过子线程又无法进行UI操作,所以解决方法就是在点击按钮时开启一个子线程,子线程连接mysql,进行数据读取,再将数据通过Message方法发送到主线程
话不多说,看一遍代码就知道什么意思了。
首先先建立User类,用来操作接收到的数据
public class User {
private String name;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
MainActivity.java:
package com.example.testmysql2;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
TextView showData;
EditText inputName;
EditText inputPass;
Button submit;
private static final int CONN_OK = 1;
private static final int CONN_FALSE = 0;
private String queryName;
private String queryPass;
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
//((TextView) findViewById(R.id.show_data)).setText((String) message.obj);
String name;
String password;
switch (message.what) {
case CONN_OK:
//接受到子线程发送过来的消息
User user = (User) message.obj;
name = user.getName();
password = user.getPassword();
showData.setText("用户名" + name + "\n密码" + password);
Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
Log.d("MainActivity.this", "用户名:" + name);
Log.d("MainActivity.this", "密码:" + password);
Log.d("MainActivity.this", "数据库中有这个用户");
break;
}
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
public void initView() {
showData = (TextView) findViewById(R.id.show_data);
inputName = (EditText) findViewById(R.id.input_name);
inputPass = (EditText) findViewById(R.id.input_pass);
submit = (Button) findViewById(R.id.login);
submit.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.login:
queryName = inputName.getText().toString();
queryPass = inputPass.getText().toString();
new Thread(new Runnable() {
@Override
public void run() {
try {
//获得Message对象
Message msg = new Message();
//加载jdbc驱动
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection cn= DriverManager.getConnection("jdbc:mysql://电脑ip:数据库的端口号/数据库名","用户","数据库密码");
//待查询语句
String sql = "select * from user where name='" + queryName + "'";
//String sql = "select * from user where name= '\"+queryName+\"'";
//创建Statement对象
// Statement 对象用于将 SQL 语句发送到数据库中
//Statement st = (Statement) conn.createStatement();
PreparedStatement ps = conn.prepareStatement(sql);
//为了执行 Statement 对象,被发送到数据库的 SQL 语句将被作为参数提供给 Statement 的方法:
//Statement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和execute。使用哪一个方法由 SQL 语句所产生的内容决定。
ResultSet rs = ps.executeQuery(sql);
//原理可以参考https://zhidao.baidu.com/question/122589837.html
while (rs.next()) {
if (rs.getString("name").equals(queryName)) {
Log.d("MainActivity.this", "数据库中有这个用户");
if (rs.getString("password").equals(queryPass)) {
User user = new User();
//将user对象中的name属性设置为从数据库读取的name字段
user.setName(rs.getString("name")); //user.setName(rs.getString(1));
//将user对象中的password属性设置为从数据库读取的password字段
user.setPassword(rs.getString("password"));
msg.what = CONN_OK;//msg.what判断是什么类型的消息,可以在Handle里面接受
msg.obj = user;//消息的对象是user,就是消息承载的主体就是user,
//子线程中无法对界面进行处理,要将消息发送到主线程
handler.sendMessage(msg);
Log.d("MainActivity.this", "终于连接好了啊");
}
}
//关闭连接
conn.close();
ps.close();
rs.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}).start();//开启线程
break;
default:
break;
}
}
}
显示数据:
<?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"
tools:context=".MainActivity">
<EditText
android:id="@+id/input_name"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="请输入用户名" />
<EditText
android:id="@+id/input_pass"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="请输入密码"/>
<TextView
android:id="@+id/show_data"
android:layout_height="100dp"
android:layout_width="match_parent"
android:textSize="30dp"
android:gravity="center"
android:text="点击按钮显示数据" />
<Button
android:id="@+id/login"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击获取数据"/>
</LinearLayout>
输入用户姓名与密码,会在界面显示姓名与密码,这里的showData.setText(…)只是一个小例子,可以自己换成其它的代码,
比如Intent intent = new Intent(....);
跳转到其它活动。
插入数据:
在onClick()中的switch case中加入
case R.id.add_user:
//自己在布局界面添加输入框的
final String iName = "想插入的用户名";//insertName.getText().toString();
final String iPass = "用户的密码";//insertPass.getText().toString();
//先判断输入信息是否为空
if (iName.equals("") || iPass.equals("")) {
Toast.makeText(this,"输入内容不能为空",Toast.LENGTH_SHORT).show();
} else {
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection cn= DriverManager.getConnection("jdbc:mysql://电脑ip:数据库的端口号/数据库名","用户","数据库密码");
String sql = "insert into user values(?,?)";
PreparedStatement pst;
pst = (PreparedStatement) conn.prepareStatement(sql);
pst.setString(1,iName);
pst.setString(2,iPass);
int row = pst.executeUpdate();
pst.close();
conn.close();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
}).start();//开启线程
}
break;
如果有错误欢迎指正,如果有需要代码或者软件相关资料的可以留言