0

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.

Rydzombi
  • 1
  • 2

1 Answers1

0
  • NetworkOnMainThreadException error, it happens when an Android application's main thread does a network operation. You must connect to the database using an asynchronous task or in a different thread in order to fix this problem.

  • I have done a sample connection with Azure MySQL Database and server check below:

DatabaseConnection.java :

public class DatabaseConnection {
    private static final String DB_URL = "jdbc:mysql://your-database-server.mysql.database.azure.com:3306/your-database-name";
    private static final String DB_USER = "username@database-server";
    private static final String DB_PASSWORD = "database-password";

    public static Connection getConnection() throws SQLException {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
        } catch (ClassNotFoundException e) {
            throw new SQLException("MySQL JDBC driver not found!");
        }
    }

    public static void createTable() throws SQLException {
        Connection connection = null;
        try {
            connection = getConnection();
            String createTableQuery = "CREATE TABLE users (" +
                    "id INT PRIMARY KEY," +
                    "name VARCHAR(50) NOT NULL," +
                    "email VARCHAR(100) UNIQUE" +
                    ")";
            connection.createStatement().execute(createTableQuery);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void insertSampleData() throws SQLException {
        Connection connection = null;
        try {
            connection = getConnection();
            String insertDataQuery = "INSERT INTO users (id, name, email) VALUES " +
                    "(1, 'suresh', 'suresh@example.com')," +
                    "(2, 'surya', 'surya@example.com')," +
                    "(3, 'Rydzombi', 'Rydzombi@example.com')";
            connection.createStatement().execute(insertDataQuery);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }
}

DatabaseConnectionTask.java :

public class DatabaseConnectionTask extends AsyncTask<Void, Void, Connection> {

    @Override
    protected Connection doInBackground(Void... voids) {
        Connection connection = null;
        try {
            connection = DatabaseConnection.getConnection();
            DatabaseConnection.createTable(); // Create the table
            DatabaseConnection.insertSampleData(); // Insert sample data
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    @Override
    protected void onPostExecute(Connection connection) {
        // Use the connection in your app or pass it to another method
    }
}

MainActivity.java :

public class MainActivity extends AppCompatActivity {

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

    public void onClickButton(View view) {
        DatabaseConnectionTask task = new DatabaseConnectionTask();
        task.execute();
    }
}

If you use the Azure Active Directory authentication allows it to manage the identity and access to your Azure MySQL Database.

I have set as a public access and while using private access try to change the port and re-check the IP addresses updated.

enter image description here

I can see that the database connected and the data which I given is saved. Better once recheck your login timeout for your database.

enter image description here

Suresh Chikkam
  • 623
  • 2
  • 2
  • 6