Im doing a project for school and Im trying to use a MySQL database on azure in android app.
The problem is when Im trying to connect to the database using jdbc it say me an error
Error:
FATAL EXCEPTION: main Process: com.example.trasteros, PID: 29432 java.lang.IllegalStateException: Could not execute method for android:onClick at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:446) at android.view.View.performClick(View.java:6256) at android.view.View$PerformClick.run(View.java:24701) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:441) at android.view.View.performClick(View.java:6256) at android.view.View$PerformClick.run(View.java:24701) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) Caused by: java.lang.RuntimeException: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. at com.example.trasteros.Conexion.conectarse(Conexion.java:17) at com.example.trasteros.CrearUsuario.ocCrearUsuario(CrearUsuario.java:75) at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:441) at android.view.View.performClick(View.java:6256) at android.view.View$PerformClick.run(View.java:24701) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) Caused by: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:111) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:98) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:90) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:64) at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:1001) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:446) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:239) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:188) at java.sql.DriverManager.getConnection(DriverManager.java:569) at java.sql.DriverManager.getConnection(DriverManager.java:219) at com.example.trasteros.Conexion.conectarse(Conexion.java:15) at com.example.trasteros.CrearUsuario.ocCrearUsuario(CrearUsuario.java:75) at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:441) at android.view.View.performClick(View.java:6256) at android.view.View$PerformClick.run(View.java:24701) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) Caused by: android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448) at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:102) at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90) at java.net.InetAddress.getAllByName(InetAddress.java:787) at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:130) at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:63) at com.mysql.cj.NativeSession.connect(NativeSession.java:121) at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:945) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:446) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:239) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:188) at java.sql.DriverManager.getConnection(DriverManager.java:569) at java.sql.DriverManager.getConnection(DriverManager.java:219) at com.example.trasteros.Conexion.conectarse(Conexion.java:15) at com.example.trasteros.CrearUsuario.ocCrearUsuario(CrearUsuario.java:75) at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:441) at android.view.View.performClick(View.java:6256) at android.view.View$PerformClick.run(View.java:24701) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
My code is this:
Connection Class: User and password are the same that in Azure database.
package com.example.trasteros;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Conexion{
Connection conexion;
String url="jdbc:mysql://raseulalmacenes.mysql.database.azure.com:3306/raseul?useSSL=true";
public Connection conectarse(){
try {
Class.forName("com.mysql.jdbc.Driver");
conexion = DriverManager.getConnection(url, "raseuladmin", "******");
} catch (SQLException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
return conexion;
}
}
I use Connection Class here:
package com.example.trasteros;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CrearUsuario extends AppCompatActivity {
private EditText eTNombre, eTApellidos, eTDNI, eTID, eTContrasenia, eTNombreEmpresa;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_crear_usuario);
if(getSupportActionBar()!=null){
getSupportActionBar().hide();
}
eTNombre = findViewById(R.id.eTNombre);
eTApellidos = findViewById(R.id.eTApellidos);
eTDNI = findViewById(R.id.etDNI);
eTID = findViewById(R.id.eTCrearUsuarioID);
eTContrasenia = findViewById(R.id.eTCrearUsuarioContrasenia);
eTNombreEmpresa = findViewById(R.id.eTNombreEmpresa);
}
public void ocVolverAInicioDeSesion(View view) {
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
}
public void ocCrearUsuario(View view) {
String nombre = eTNombre.getText().toString();
String apellidos = eTApellidos.getText().toString();
String dni = eTDNI.getText().toString();
String nombreUsuario = eTID.getText().toString();
String contrasenia = eTContrasenia.getText().toString();
String nombreEmpresa = eTNombreEmpresa.getText().toString();
if(nombre.equals("")){
Toast.makeText(this, R.string.introduzcaNombreError, Toast.LENGTH_SHORT).show();
}else if(!comprobarNombre(nombre)){
Toast.makeText(this, R.string.maximoNombre, Toast.LENGTH_SHORT).show();
}else if(apellidos.equals("")) {
Toast.makeText(this, R.string.introduzcaApellidosError, Toast.LENGTH_SHORT).show();
}else if(apellidos.length()>45){
Toast.makeText(this, R.string.maximoApellidos, Toast.LENGTH_SHORT).show();
}else if(dni.equals("")){
Toast.makeText(this, R.string.introduzcaDNIError, Toast.LENGTH_SHORT).show();
}else if(!comprobarDNI(dni)){
Toast.makeText(this, R.string.maximoDNI, Toast.LENGTH_SHORT).show();
}else if(nombreUsuario.equals("")){
Toast.makeText(this, R.string.introduzcaIDError, Toast.LENGTH_SHORT).show();
}else if(nombreUsuario.length()>15 || nombreUsuario.length()<3){
Toast.makeText(this, R.string.maximoNombreUsuario, Toast.LENGTH_SHORT).show();
}else if(contrasenia.equals("")){
Toast.makeText(this, R.string.introduzcaContraseniaError, Toast.LENGTH_SHORT).show();
}else if(!comprobarContrasenia(contrasenia)){
Toast.makeText(this, R.string.maximoContrasenia, Toast.LENGTH_SHORT).show();
}else{
ResultSet resultado;
PreparedStatement pS = null;
Conexion conexion = new Conexion();
String consulta = "Select username from cliente where username = (?)";
try {
pS = conexion.conectarse().prepareStatement(consulta);
pS.setString(1, nombreUsuario);
resultado = pS.executeQuery();
if(resultado.next()){
Toast.makeText(this, R.string.usuarioExistente, Toast.LENGTH_SHORT).show();
}else{
consulta = "Select NIF from clientes where NIF = (?)";
pS.setString(1, dni);
resultado = pS.executeQuery();
if(resultado.next()){
Toast.makeText(this,R.string.nifExistente, Toast.LENGTH_SHORT).show();
}else{
pS = conexion.conectarse().prepareStatement(consulta);
consulta = "insert into cliente(NIF, nombre, apellidos, FECHA_ALTA, username, PASSWORD) values ((?), (?), (?), (?), (?), (?))";
pS = conexion.conectarse().prepareStatement(consulta);
pS.setString(1, dni);
pS.setString(2, nombre);
pS.setString(3, apellidos);
pS.setDate(4, obtenerFechaActual());
pS.setString(5, nombreUsuario);
pS.setString(6, contrasenia);
pS.executeUpdate();
eTNombre.setText("");
eTApellidos.setText("");
eTDNI.setText("");
eTID.setText("");
eTContrasenia.setText("");
eTNombreEmpresa.setText("");
Toast.makeText(this, R.string.usuarioCreado, Toast.LENGTH_SHORT).show();
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
/*public boolean comprobarDNICOMPLETO(String dni){
if (dni == null || dni.length() != 9) {
return false;
}
char letra = dni.charAt(8);
if (!Character.isLetter(letra)) {
return false;
}
String numeros = dni.substring(0, 8);
try {
Integer.parseInt(numeros);
} catch (NumberFormatException e) {
return false;
}
String tablaLetras = "TRWAGMYFPDXBNJZSQVHLCKE";
int numero = Integer.parseInt(numeros);
int indice = numero % 23;
char letraCalculada = tablaLetras.charAt(indice);
return letra == letraCalculada;
}*/
public boolean comprobarDNI(String dni) {
// Comprobar que el DNI tenga 9 caracteres
if (dni.length() != 9) {
return false;
}
// Comprobar que los 8 primeros caracteres sean números
for (int i = 0; i < 8; i++) {
if (!Character.isDigit(dni.charAt(i))) {
return false;
}
}
// Comprobar que el último carácter sea una letra mayúscula
char letra = Character.toUpperCase(dni.charAt(8));
return letra >= 'A' && letra <= 'Z';
}
public boolean comprobarContrasenia(String contrasenia) {
if (contrasenia == null || contrasenia.length() < 3 || contrasenia.length() > 15) {
return false;
}
boolean contieneLetra = false;
boolean contieneNumero = false;
for (char c : contrasenia.toCharArray()) {
if (Character.isLetter(c)) {
contieneLetra = true;
} else if (Character.isDigit(c)) {
contieneNumero = true;
}
}
return contieneLetra && contieneNumero;
}
public boolean comprobarNombre(String nombre) {
if (nombre == null || nombre.length() > 15 || nombre.length() == 0) {
return false;
}
char primerCaracter = nombre.charAt(0);
if (!Character.isUpperCase(primerCaracter)) {
return false;
}
return true;
}
public Date obtenerFechaActual() {
java.util.Date fechaActualUtil = new java.util.Date();
return new Date(fechaActualUtil.getTime());
}
@Override
protected void onResume() {
super.onResume();
eTNombre.setText("");
eTApellidos.setText("");
eTDNI.setText("");
eTID.setText("");
eTContrasenia.setText("");
eTNombreEmpresa.setText("");
}
}
Build Gradle:
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.trasteros'
compileSdk 33
defaultConfig {
applicationId "com.example.trasteros"
minSdk 26
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation files('libs\\mysql-connector-j-8.0.33.jar')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Trasteros"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SesionIniciada"
android:exported="true">
</activity>
<activity
android:name=".CrearUsuario"
android:exported="true">
</activity>
<activity
android:name=".Ajustes"
android:exported="true">
</activity>
</application>
</manifest>
I tried change jdbc version, checking the IP multiple times and the IP is the same that azure say me to connect to jdbc.
On MySQL Workbench it works and don't have any problem.