视讯游戏提供最新游戏下载和手游攻略!

深入解析Android与MySQL数据库实例的远程连接方法

发布时间:2024-09-03浏览:72

大家好,如果您还对深入解析Android与MySQL数据库实例的远程连接方法不太了解,没有关系,今天就由本站为大家分享深入解析Android与MySQL数据库实例的远程连接方法的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

第一次连接远程MySQL数据,在此留下笔记,针对遇到的总是也一并给出,在此说明,连接远程数据库在我没遇到的问题暂时无法给出,我尽量按写程的时间最全的给出代码。连接的方法是采用mysql-connector-java-5.1.30-bin.jar包进行连接。欢迎讨论。说明:

以下记录按时间先后顺利给出,采用同样的环境应该可以重现。

代码部分也由顺序给出,如:某一个方法或者类后面的代码可能比前面贴出的全,也可能是增加了内容,也可能是解决了前面的某个问题。

为了程序的可扩展性,本示例采用数据与UI分离写法,自定义了页面的基类BasePager,initView()和initData()

环境配置

服务器:阿里云服务器 ECS操作系统:centos 7MySQL:version: 5.7.27连接服务器软件:FinalShellMySQL管理软件:RoboDB MySQL Manager安卓开发软件:Androi Studio 3.5.2

查看MySQL:version方法

在登陆服务器后输入mysql -uroot -p再输入密码。

[root@njzhw ~]# mysql -uroot -pEnter password: Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 1234354Server version: 5.7.27 MySQL Community Server (GPL)Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>

新建Android工程

新建一个空白Activity的工程文,目前采用最新的各类文件版本,

build.gradle

app的build.gradle文件如下:所有支持均已最新版本。minSdkVersion 19因受我电脑外挂android模拟器的限制,采用了19。高了模拟器运行不起来。

apply plugin: 'com.android.application'android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { applicationId "cn.plczl.myapplication" minSdkVersion 19 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'}

activity_main.xml布局文件

MainActivity所对应的activity_main.xml的布局文只有一个FrameLayout,所有数据显示采用另外的代码实现。

<?xml version="1.0" encoding="utf-8"?>

MainActivity类修改为继承于Activity

新建好的MainActivity是继承于AppCompatActivity。区别是软件运行时不需要其默认的标题栏百度的区别:Activity 是其它 Activity 的基类,包括 AppCompatActivity。默认带标题栏,从字面理解,App兼容Activity,意思是允许我们轻易地将API 21+的特性应用到之前的那些老的,不兼容的Activity上面。例如很容易地将Toolbar添加到Activity上代码如下:

package cn.plczl.mysql;import android.app.Activity;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}

新建一个基类

用于子页面来继承,这样可以有多个页面采用自定义的一类进行界面、数据分离处理。在工程中新建一个base的包,包中建立一个BasePager的类。代码如下:本基类无需要继承,主要代码如下:

其中有一个构造函数public BasePager(Context context),用于获取上下文和初始化视图(rootView);

一个抽象的initView方法,强制由调用的页面来实现,以实现不同页面有不同的UI结构;

一个初始化数据的方法(initData),本方法为一个空方法,由继承它的子页面来实现数据填充。在子页面中还可以在本方法中进行耗时的联网,数据请求,数据显示的操作。注意:

因public abstract View initView();这个是一个抽象的方法,所对应的public abstract class BasePager 类也必须是抽象的,也就是由abstract关键字。

public Context conetxt;要修改为public,如果自生成时可能是这样的,private final Context conetxt;因为这个conetxt要被其它的类调用。

package com.atguigu.mysql_dome.Base;import android.content.Context;import android.view.View;public abstract class BasePager { public Context conetxt; public View rootview; //本类的构造函数 public BasePager(Context context){ this.conetxt=context; rootview=initView(); } //初始化视图的抽象类。强制由继承本类的其它类来实现 public abstract View initView(); //初始化视图的空方法,执行联网、数据请求、数据显示操作,本空方法不能缺少。 public void initData(){ }}

新建一个子页面

在工程中新建一个包(pager)来存放各子页面,在其包下新建一个EthMainPager的子页面,代码如下:初步的实现了构造方法,initView()方法和initData方法。其在程序中显示“初始化了EthMainPager”的文字。

package cn.plczl.mysql.pager;import android.content.Context;import android.view.Gravity;import android.view.View;import android.widget.TextView;import cn.plczl.mysql.base.BasePager;import cn.plczl.mysql.utils.LogUtil;public class EthMainPager extends BasePager { private TextView textView; public EthMainPager(Context context) { super(context); } @Override public View initView() { textView=new TextView(conetxt); textView.setGravity(Gravity.CENTER); textView.setTextSize(20); return textView; } @Override public void initData() { super.initData(); LogUtil.e("初始化了EthMainPager"); textView.setText("初始化了EthMainPager"); }}

将EthMainPager页面放入MainActivity中并显示。

修改MainActivity,为程序扩展,将EthMainPager放入一个basePagers的集合中,自定义了setFragment、getEthMainPager方法,新建了一个ReplacePager类

public class MainActivity extends FragmentActivity { private ArrayListbasePagers; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); basePagers = new ArrayList<>(); basePagers.add(new EthMainPager(this)); setFragment(); } private void setFragment() { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); //这里采用了replace方法,如果只是一个页面,也可以采用add方法。 fragmentTransaction.replace(R.id.fl_main,new ReplacePager(getEthMainPager())); fragmentTransaction.commit(); } private BasePager getEthMainPager() { BasePager basePager=basePagers.get(0); if(basePager!=null){ basePager.initData(); } return basePager; } public static class ReplacePager extends Fragment { public BasePager currPager; public ReplacePager(BasePager basePager) { this.currPager=basePager; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return currPager.rootView; } }}

为使程序看起来简捷,将public static class ReplacePager extends Fragment抽取出来形成一个单独的类。将其抽取至base目录中。文件名为ReplacePager在MainActivity加入包含import cn.plczl.mysql.base.ReplacePager;

package cn.plczl.mysql.base;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.fragment.app.Fragment;public class ReplacePager extends Fragment { public BasePager currPager; public ReplacePager(BasePager basePager) { this.currPager=basePager; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return currPager.rootView; }}

初步运行界面

以上代码完成初步的界面搭建,初步运行起来的画面如下:

子页面的完善编写

接下来的基本操作都将在EthMainPager子页面中去实现界面,联网和数据请示以及数据显示的操作。

子页面的布局

在EthMainPager的public View initView() 加入一条View view=View.inflate(conetxt, R.layout.ethmainpager,null);,用于加载ethmainpager.xml布局文,不再采用上面程序中的如下代码来初始化子页面了,initView体现了页面的初始化,

textView=new TextView(conetxt);textView.setGravity(Gravity.CENTER);textView.setTextSize(20);return textView; @Override public View initView() { View view=View.inflate(conetxt, R.layout.ethmainpager,null); return view; }

ethmainpager.xml文件

这里采用简单的一个线性布局,里面有四个TextView,这个程序是Dome性质,只要参调出MySQL数据一张表中库中的两个数据和另一张表中的一个数据,这里设定能调出数据库最近更新的日期和时间就完成任务。

<?xml version="1.0" encoding="utf-8"?>

实例化控件

将用于要显进日期和时间的两个TextView实例化。

private TextView tv_data; private TextView tv_time; private TextView tv_version; public EthMainPager(Context context) { super(context); } @Override public View initView() { View view = View.inflate(conetxt, R.layout.ethmainpager,null); tv_data = view.findViewById(R.id.tv_data); tv_time = view.findViewById(R.id.tv_time); tv_version = view.findViewById(R.id.tv_version); return view; }

导入jar包

apply plugin: 'com.android.application'android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { applicationId "cn.plczl.myapplication" minSdkVersion 19 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation files('libs/mysql-connector-java-5.1.30-bin.jar')}

数据库连接工具类

编写了连接数据库的工具类DBUtils.jave。用于要对数据操作的调用,代码如下:其中有三个方法:

getConn用于连接数据,其中String dbName参数为要连接的数据名字,

getEthData方法是获得eth数据库中的apidate表的最新一行的数据方法。

getVersion方法是eth数据库中的version表中的version字段的的最新一行的数据方法。调用的方法分别以一个数组和字符串返回。

获得数据更新

在EthMainPagerr的initData()方法中写了两个方法,分别连接两个数据库获得数据并显示。getData()方法是调用DBUtils数据库连接工具中的getEthData()getVersion();方法是调用DBUtils数据库连接工具中的getVersion()采用在子线程中连接数据库和Handler切换到主线程进行数据更新。

@Override public void initData() { super.initData(); LogUtil.e("初始化了EthMainPager"); getData(); getVersion(); }

getData()

简单的new了一个Thread子线程,用于调用 ethdata=DBUtils.getEthData();方法,将数据存入ethdata数组中。通过handler.sendEmptyMessage(0);返回主线程。

private void getData() { new Thread(){ @Override public void run() { super.run(); ethdata=DBUtils.getEthData(); handler.sendEmptyMessage(0); } }.start(); }

handler

在handler中更换tv_data.setText(ethdata[0]);tv_time.setText(ethdata[1]);获得的数据。

private Handler handler = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); LogUtil.e(String.valueOf(ethdata.length)); tv_data.setText(ethdata[0]); tv_time.setText(ethdata[1]); } };

getVersion()

与 getData()类似。version=DBUtils.getVersion();方法,将数据存入version数组中。通过versionhandle.sendEmptyMessage(1);返回主线程。

private void getVersion() { new Thread(){ @Override public void run() { super.run(); version=DBUtils.getVersion(); versionhandle.sendEmptyMessage(1); } }.start(); }

versionhandle

在versionhandle中更新tv_version.setText(version);获得的数据。

private Handler versionhandle = new Handler(){ @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); LogUtil.e(String.valueOf(ethdata.length)); tv_version.setText(version); } };

最终运行的结果

软件运行结果

数据库中的数据

用户评论

凉凉凉”凉但是人心

这篇博客终于解决了我一直困扰的问题!用安卓连接远程MYSQL数据库确实有点麻烦, 特别是安全性方面更容易出问题. 这篇文章讲解很清楚,代码也很易懂,感谢作者!

    有16位网友表示赞同!

不要冷战i

我一直使用SQLite本地数据库,想尝试一下远程MySQL的优势,这篇博客正好给了我思路!不过对于新手来说,连接配置部分还是需要多看看教程理解一下。

    有7位网友表示赞同!

有恃无恐

感觉这篇文章有点太详细了,讲到一些高层概念我没那么了解。主要是想快速看下安卓访问remote MySQL 的基本步骤,希望作者能增加一篇更简明的入门指南.

    有16位网友表示赞同!

失心疯i

我之前遇到过类似问题,当时自己摸索很久都没找到合适的解决方案!这篇博客的代码十分有效,真是太棒了!

    有6位网友表示赞同!

怪咖

写的不错啊,很详细地介绍了连接过程,还有安全性考虑,这方面做的很棒。对于想要深入了解远程mysql操作的用户来说非常有价值。

    有15位网友表示赞同!

裸睡の鱼

我尝试着照着文章步骤去做,但是运行到某个步骤就总是报错,不知道是不是我代码写错了。能否提供一些常见问题解决的建议?

    有18位网友表示赞同!

太易動情也是罪名

远程数据库通常需要防火墙配置之类的,这篇文章并没有提到这些信息,希望作者可以补充一下相关的安全知识点,避免安全风险

    有8位网友表示赞同!

七级床震

连接成功了,但是查询数据的时候总是返回 null,感觉代码没问题啊…有没有什么隐藏的条件需要注意?

    有15位网友表示赞同!

千城暮雪

这篇博文真是太棒了!以前一直想学习远程数据库操作的技巧,这下终于找到了合适的教程!希望能多分享一些不同的应用案例。

    有7位网友表示赞同!

抚涟i

安卓开发确实有很多东西需要学,连接远程mysql也是其中的一部分。这个博客帮到我了,以后我会继续关注作者的文章!

    有14位网友表示赞同!

迷路的男人

文章讲解得很到位,代码清晰易懂,是我学习Android远程MySQL数据库操作的最佳良师!

    有12位网友表示赞同!

泪湿青衫

这种远程操作感觉有点复杂啊,如果能用一些更简单的方式连接数据库就好了。不过也理解使用远程数据库的好处要付出一定的努力.

    有11位网友表示赞同!

米兰

这篇文章终于解决了我的痛点!以前总是遇到连接MySQL数据库的问题,现在终于有了一个方法可以参考了!感谢作者!

    有7位网友表示赞同!

何年何念

代码写的太简练了,对于初学者来说可能读起来不太容易理解。能不能加上一些详细的注释解释一下每个步骤为什么要这样做?

    有18位网友表示赞同!

あ浅浅の嘚僾

我觉得这种远程数据库连接方案相对复杂一些,在实际项目中也可能会遇到很多问题。有没有其他更简单的方法可以供参考?

    有15位网友表示赞同!

热点资讯