Spanish Perdida al conectar Mysql

TheFalcon

Active Member
Licensed User
Longtime User
Buenas, he hecho una aplicación que la base de datos la tiene en Mysql, ya pregunte un par de dudas con anterioridad, y me dijeron que no debería de perder datos, pero probando con 3 dispositivos a la vez para comprobar los tamaños
Muchísimas veces, mas de las que quisiera, no me refresca datos, es decir el MAIN principal recoge una noticia de la mysql y la muestra en un label, pues no refresca, si por un casual un dispositivo me refresca el siguiente suele no refrescar y a los 15 seg, darme el error de colectividad, y no tengo ni idea de por que.

No se si es de los móviles , de la base de datos mysql, o de que carajo, pero la aplicación sera para mas de 200 usuarios y si con 3 móviles me pasa, no quiero ni pensar mas adelante.

Agradecería de vuestra maravillosa sabiduría.

Un saludo
 

Alejandro Moyano

Member
Licensed User
Hola, ¿Cómo estas trabajando con la base de datos?. Yo actualmente estoy haciendo un proyecto con MySQL pero el backend lo hago en Flask-SQLAlchemy (Python) y no he tenido ningún problema, estas usando un backend B4J con jRDC2?
 

josejad

Expert
Licensed User
Longtime User
Hola TheFalcon. Déjanos ver como haces la conexión, como la refrescas, etc... sube un proyecto de ejemplo o algo...

Saludos y tranquilo, entre todos daremos con el problema
 

TheFalcon

Active Member
Licensed User
Longtime User
La conexión la hago con Jobdone, un archivo PHP en mi hosting, esta noche pego la conexión que ahora no estoy en mi PC , gracias por las prontas respuestas
 

TheFalcon

Active Member
Licensed User
Longtime User
En el Activity Create pongo , tambien lo pongo en Activity_Resume
B4X:
If IsConnected = True Then ' si hay conexion a internet
       
   
       
ExecuteRemoteQuery("SELECT id,fecha,titulo,noticia FROM noticias ORDER by id desc",consulta_noticias )
   
           
        If FirstTime Then
            hc.Initialize("hc")
        End If
   





   
    Else ' si no hay internet, arranca normal
       
        Msgbox("No se a podido comprobar la conexión a Internet, verifica que estas conectado/a","Atención")
    End If


Aqui el execute non query

B4X:
Sub ExecuteRemoteQuery(Query As String, JobName As String)
    Dim job As HttpJob
    job.Initialize(JobName, Me)
    job.PostString("http://www.midominio.com/query_consulta.php", Query)
End Sub

Sub JobDone(Job As HttpJob)
   
   
   
   
    ProgressDialogHide
    If Job.Success Then
   
        Dim res As String
        res = Job.GetString
        Log("Response from server: " & res)




        Dim parser As JSONParser
        'res=res.SubString2(res.IndexOf("["),res.IndexOf("]"))
        parser.Initialize(res)
        Select Job.JobName
       
   
       
       
        '    'ESTA CONSULTA SE EJECUTA AL ARRANCAR Y COGE LA ULTIMA NOTICIA POR FECHA
            Case consulta_noticias
                Dim CONSULTA As List
                CONSULTA = parser.NextArray 'returns a list with maps
                For i = 0 To CONSULTA.Size - 1
                    Dim m As Map
                    m = CONSULTA.Get(i)
           
                                       
fecha_mysql=m.Get("fecha") 'coge la fecha de mysql
titulo_mysql=m.Get("titulo")'coge titulo de mysq
noticia_mysql=m.Get("noticia")'coge noticia de mysq

Exit ' PONEMOS EXIT PARA QUE SOLO COJA 1 NOTICIA , EN LA CONSULTA YA ESTA ORDENADO POR FECHA
                       

                Next      
               
               
               
               
                'AQUI RELLENA LOS CAMPOS DE LA NOTICIA
                lblfecha.Text = fecha_mysql
                lbltitulo.Text = titulo_mysql
                lblnoticia.text = noticia_mysql
               

       
    End Select
       
        Else
       
Log(Job.ErrorMessage)
ToastMessageShow("Ha habido algún problema a la hora de conectar a la base de datos, intentalo mas tarde",True)
        End If




   
    Job.Release
   
End Sub




Aqui aunque no es relevante supongo, la función isconected para comprobar si hay internet

B4X:
Sub IsConnected As Boolean
    Dim P As Phone,server As ServerSocket'Add a reference to the network library  'Check status: DISCONNECTED 0
    Try
        server.Initialize(0, "")
        Log("mobile data state: " & P.GetDataState & " wifi_on: " & P.GetSettings("wifi_on") & " server ip: " & server.GetMyIP & CRLF &  "wifi ip: " & server.GetMyWifiIP)
        If server.GetMyIP = "127.0.0.1" Then Return False  'this is the local host address
        If Not(P.GetDataState.EqualsIgnoreCase("CONNECTED")) And server.GetMyWifiIP = "127.0.0.1" Then Return False
       
   
        Return True
    Catch
        Return False
   
    End Try
   
   
End Sub



el mensaje de error que me da es el que está en el NONQUERY
 

Alejandro Moyano

Member
Licensed User
La verdad no se muy bien porque separas el código en relación si genera el hilo, por lo que tengo entendido si te genera el hilo de ejecución porque te da success, podrías debaggear como le llega la consulta en PHP, me ha pasado seguido errores SQL porque la codificación de cliente y servidor no era la misma.

Así los manejo yo casi siempre, habría que ver si haciendo un PostMultipart en vez de un PostString funciona.

B4X:
Public Sub resumLogin(Email As String, Password As String) As ResumableSub
    Dim post As HttpJob
    Dim PostValues, root As Map
    Dim parser As JSONParser
    PostValues.Initialize
    PostValues.Put("email",Email)
    PostValues.Put("psw",Password)
    post.Initialize("Login", Me)
    post.PostMultipart( $"http://${ServerIpDomain}:${ServerPort}/api/login"$,PostValues, Null)
    Wait For (post) JobDone (post As HttpJob)
    If post.Success Then
        Log(post.GetString)
        parser.Initialize(post.GetString)
        root  = parser.NextObject
        accesToken  = root.Get("access_token")
        grantsString  = root.Get("grants")
        refreshToken  = root.Get("refresh_token")
        Message = root.Get("message")
        APPCODE  = root.Get("app_code")
        Loged = True
        If APPCODE <> 0 Then Loged = False
    End If
    post.Release
    Return APPCODE
End Sub
 

josejad

Expert
Licensed User
Longtime User
' 'ESTA CONSULTA SE EJECUTA AL ARRANCAR Y COGE LA ULTIMA NOTICIA POR FECHA
Case consulta_noticias
Dim CONSULTA As List
CONSULTA = parser.NextArray 'returns a list with maps
For i = 0 To CONSULTA.Size - 1
Dim m As Map
m = CONSULTA.Get(i)


fecha_mysql=m.Get(
"fecha") 'coge la fecha de mysql
titulo_mysql=m.Get("titulo")'coge titulo de mysq
noticia_mysql=m.Get("noticia")'coge noticia de mysq

Exit ' PONEMOS EXIT PARA QUE SOLO COJA 1 NOTICIA , EN LA CONSULTA YA ESTA ORDENADO POR FECHA


Next

Hola:

Hay algo que no entiendo en ese bucle.
Si tienes las consultas ordenadas por fechas y haces el exit, para qué es necesario el bucle?
Siempre coges la 0, no? En este caso sería lo mismo poner:
B4X:
 m =CONSULTA.Get(0)

¿No sería mejor para eso además hacer una consulta SQL que sólo coja la última noticia y no todas ordenadas por fecha?
 

TheFalcon

Active Member
Licensed User
Longtime User
Lo de exit se lo pongo por que con la consulta que hago me recorría todas las noticias y para que cogiera la 1 y saliera puse esa solución, probare como dices a ver , aunque indistintamente de eso, creo qeu no es el que me genera el problema , por que si no creo que deberia darme problema con todos y a veces los dispositivos conectan sin problema con la BD y otras veces no y me da el error.

Con respecto a lo que comentas alejandro, nunca probe con postmultipart, lo tengo así por qu es como vi en el foro los tutoriales y fui adaptándome a esos y probando
 

Alejandro Moyano

Member
Licensed User
Hola @TheFalcon se me ocurre que podrías hacer la siguiente consulta asumiendo que definiste la la tabla así:

B4X:
CREATE TABLE noticias(
 id INT AUTO_INCREMENT PRIMARY KEY,
 fecha DATE,
 titulo VARCHAR(xxx),
 noticia LONGTEXT
);


Como el numero es siempre creciente y lo ordenas descendiente así tomas solo el ultimo dato, eso te va alivianar la capa de transporte porque la respuesta del server es mas pequeña.

B4X:
SELECT id,fecha,titulo,noticia FROM noticias ORDER by id desc LIMIT 1;

Para cargar los datos yo usaria algo asi:

B4X:
'Load the last new
public Sub LoadLastNew()
    Dim sql As String = "SELECT id,fecha,titulo,noticia FROM noticias ORDER by id desc LIMIT 1;"
    Wait For (LoadServerData(sql)) Complete (Result As Map)
    lblfecha.Text = Result.Get("fecha")
    lbltitulo.Text = Result.Get("titulo")
    lblnoticia.text = Result.Get("noticia")
End Sub

'Load data from server using post
Public Sub LoadServerData(query As String) As ResumableSub
    Dim post As HttpJob
    Dim PostValues, root As Map
    Dim parser As JSONParser
    PostValues.Initialize
    PostValues.Put("query",query)
    post.Initialize("LoadServerData", Me)
    post.PostMultipart( $"http://www.midominio.com/query_consulta.php"$,PostValues, Null)
    Wait For (post) JobDone (post As HttpJob)
    If post.Success Then
        Log(post.GetString)
        parser.Initialize(post.GetString)
        root  = parser.NextObject
    End If
    post.Release
    Return root
End Sub

Fijate si te funciona así, en php solo tenes que hacer POST['query'] y ejecutar eso, yo sinceramente no programo en PHP desde la version 5, lo que si cualquiera que descubra la url tiene acceso a toda tu base de datos, al usuario dale grants sobre ciertas tablas publicas, sino fíjate dejar la consulta en el servidor y que el cliente (APP) envíe el código de la consulta http://www.midominio.com/api.php?consulta=5 algo mas seguro que la otra forma.
 

TheFalcon

Active Member
Licensed User
Longtime User
Muchas gracias, lo pruebo este fin de semana que entre semana no me da tiempo a nada jaja, y te comento a ver que tal, a ver si el problema de que no responda es por el modo en que pido la consulta . Gracias y un saludo
 

TheFalcon

Active Member
Licensed User
Longtime User
cualquiera que descubra la url tiene acceso a toda tu base de datos, al usuario dale grants sobre ciertas tablas publicas, sino fíjate dejar la consulta en el servidor y que el cliente (APP) envíe el código de la consulta http://www.midominio.com/api.php?consulta=5 algo mas seguro que la otra forma.

con eso me has dejado preocupado, pense que las consultas no puedes acceder a ellas, en la base de datos no abra gran información importante, pero si alguien pudiera acceder a los datos del query.php si me joderia bastante, que me aconsejas que haga entonces, ya que en el query, lo unico que tengo es los datos de conexión , es decir solo tengo lo siguiente

B4X:
<?
error_reporting ( E_ALL  ^  E_NOTICE  ^  E_DEPRECATED );

$databasehost = "IP DEL HOSTIN";
$databasename = "nombre_BD";
$databaseusername ="nombre_user";
$databasepassword = "clave";

$con = mysql_connect($databasehost,$databaseusername,$databasepassword) or die(mysql_error());
mysql_select_db($databasename) or die(mysql_error());
mysql_query("SET CHARACTER SET utf8");
$query = file_get_contents("php://input");
$sth = mysql_query($query);

if (mysql_errno()) {
    header("HTTP/1.1 500 Internal Server Error");
    echo $query.'\n';
    echo mysql_error();
}
else
{
    $rows = array();
    while($r = mysql_fetch_assoc($sth)) {
        $rows[] = $r;
    }
    print json_encode($rows);
}
?>
 

josejad

Expert
Licensed User
Longtime User
¿Qué tipo de servidor tienes? Un host php/mysql? Un VPS?
 

TheFalcon

Active Member
Licensed User
Longtime User
Si es un host linux en el que tengo una web, y aparte tengo bases de datos mysql, un host de pago, no montado en casa
 

josejad

Expert
Licensed User
Longtime User
Ok, lo comentaba porque jRDC2 es más seguro y da mejor rendimiento.
 

TheFalcon

Active Member
Licensed User
Longtime User
creo que estuve mirando JRDC2 y no conseguí a echarlo andar, sabes de un hilo en el que lo expliquen bien, todo lo que sea mejorar
 

josejad

Expert
Licensed User
Longtime User
Podría echarte una mano con jRDC2, pero me temo que no podrás ponerlo en tu host a menos que sea un VPS, pero por lo que comentas imagino que es un host php+mysql. Para usar jRDC2 tendrías que tener un servidor en el que correr el .jar (jRDC2 es un servidor B4J intermedio que es el que conecta a tu bbdd mysql, y tu app conectaría al servidor jRDC2, es más seguro porque el sql no estaría en tu app, sino en el servidor).

Para tener un poco más de seguridad lo suyo es que en tu script php trabajes con sentencias preparadas. Puedes leer un poco sobre ello aquí:
https://diego.com.es/sentencias-preparadas-en-php

Creo que el tutorial más actualizado en este sentido es este:
https://www.b4x.com/android/forum/threads/updated-mysql-php-example.96790/#content
 

TheFalcon

Active Member
Licensed User
Longtime User
Estuve mirando mi hosting y no tengo servicio VPS. Aunque puedo contratarlo, he registrado uno gratuito para probar, asi que hare 2 versiones de la apk la actual por q ya la tengo que poner en marcha y ptra en jrdc2 para probar y aprender a usarlo.

A ver si testeo la apk y veo el por que a veces no me da conexión, en el debug y lo pego para ver si sacamos el por què.
 

josejad

Expert
Licensed User
Longtime User
Ahora que ha acabado tu feria lo mismo lo ves todo más claro :p

En el VPS que tengo puedes configurarlo todo, y me sale unos 3 € al mes. En chit chat lo puse.
 

killiak

Member
Licensed User
Longtime User
con eso me has dejado preocupado, pense que las consultas no puedes acceder a ellas, en la base de datos no abra gran información importante, pero si alguien pudiera acceder a los datos del query.php si me joderia bastante, que me aconsejas que haga entonces, ya que en el query, lo unico que tengo es los datos de conexión , es decir solo tengo lo siguiente

B4X:
<?
error_reporting ( E_ALL  ^  E_NOTICE  ^  E_DEPRECATED );

$databasehost = "IP DEL HOSTIN";
$databasename = "nombre_BD";
$databaseusername ="nombre_user";
$databasepassword = "clave";

$con = mysql_connect($databasehost,$databaseusername,$databasepassword) or die(mysql_error());
mysql_select_db($databasename) or die(mysql_error());
mysql_query("SET CHARACTER SET utf8");
$query = file_get_contents("php://input");
$sth = mysql_query($query);

if (mysql_errno()) {
    header("HTTP/1.1 500 Internal Server Error");
    echo $query.'\n';
    echo mysql_error();
}
else
{
    $rows = array();
    while($r = mysql_fetch_assoc($sth)) {
        $rows[] = $r;
    }
    print json_encode($rows);
}
?>

Una forma que utilizo yo para mysql por PHP primero es controlar las inyecciones de SQL (si no conoces el tema, simplemente coloca php inyecciones sql y listo) y segundo comparto siempre una clave hasheada entre mi aplicacion y el php. De esta manera inicio en un bucle de verificación si una de las variables enviadas por post con clave (hash) es una palabra secreta que comparto entre la aplicación y el php. No es 100% pero seguramente evita quienes intenten hacer algo. Obviamente si se quieren dedicar lo pueden descifrar... pero bueno, nada es invulnerable y la información que manejo no es tan delicada. Lo mejor igual es siempre mantener el SQL en PHP. midominio/query.php?id=buscar&var1=bla&var2=bla&hash=AAS8D97ASD897FA8DA78F9A9SD78A9SDJOFJLV

El ID hace en un Select case en el PHP y ademas evitas la inyeccion. Ahi no paso la sentencia en ningun momento, solo variables.

Igual es como te recomiendan, lo mejor es montar un VPS y ahi el jrdc.
 
Top