Android Tutorial Connect Android to MySQL Database Tutorial

Status
Not open for further replies.
A new more powerful framework is now available: jRDC2.

This tutorial explains the basic concepts required for creating a connection between Android device and a remote server. In this case it is a MySQL database.
A tutorial for connecting to SQL Server is available here.

Android cannot connect directly to the database server (search for JdbcSQL). Therefore we need to create a simple web service that will pass the requests to the database and will return the response.

For this example I've created a new database that lists the countries population. The data was derived from a UN database.

The database includes a single table named "countries" with three columns:
mysql_1.png

PHP Script

The web service is made of a single PHP script running on the same server.
You have several options for the web service implementation. You can create several prepared statements which will be filled with parameters passed in the request.
Or you can take the complete query from the request and pass it to the database server.
There are high security risks with issuing queries received from an unknown user. If your service is public then you will probably want to choose the first option.
You should also make sure to correctly escape the parameters. See this php method: PHP: mysql_real_escape_string - Manual

In our example I've chosen the second option which takes the query and passes it to the database directly.
I've restricted the database user to SELECT queries (in MySQL configuration).

The PHP code:
PHP:
<?php

$databasehost = "localhost";
$databasename = "xxxx";
$databaseusername ="xxxx";
$databasepassword = "xxxx";

$con = mysqli_connect($databasehost,$databaseusername,$databasepassword, $databasename) or die(mysqli_error($con));
mysqli_set_charset ($con , "utf8");
$query = file_get_contents("php://input");
$sth = mysqli_query($con, $query);

if (mysqli_errno($con)) {
   header("HTTP/1.1 500 Internal Server Error");
   echo $query.'\n';
   echo mysqli_error($con);
}
else
{
   $rows = array();
   while($r = mysqli_fetch_assoc($sth)) {
     $rows[] = $r;
   }
   $res = json_encode($rows);
    echo $res;
    mysqli_free_result($sth);
}
mysqli_close($con);
?>
The script takes the query from the POST data and submits it to the database.
The result is then written in JSON format.

B4A code

Our application displays a list of countries. When the user presses on a country, its population is retrieved from the database and displayed.

upload_2016-8-3_13-4-25.png



The code sends the query and then when the result arrives the JSON is parsed and displayed.
Note that in this case the JSON object is made of an array of one or more maps.

Edit: Code updated to use OkHttpUtils2.
 

Attachments

  • MySQL.zip
    8 KB · Views: 17,451
Last edited:

Declan

Well-Known Member
Licensed User
Longtime User
Thanks, that seems to be working, but I get an "Error: Not Found".
My app is attached and only has slight changes to the Tutorial.
Note that it is better (simpler, more powerful, with better performance and safer) to use jRDC instead of the PHP script.
But, what would this entail for a total novice like myself?
 

Attachments

  • iStock.zip
    10.4 KB · Views: 490

Declan

Well-Known Member
Licensed User
Longtime User
The fill error I receive is:
[errormessage=Not Found, httputils2service=null, jobname=productlist, main=null, mlink=[url]http://197.189.232.202/wamp/scripts/istockserver.php[/url], password=, reg=anywheresoftware.b4a.http.HttpClientWrapper $HttpUriRequestWrapper@82ce5fa, success=false, target=class anywheresoftware.b4a.samples.mysql.main, taskid=1, username=]
 

Declan

Well-Known Member
Licensed User
Longtime User
OK, there is definitely something wrong with the syntax of:
B4X:
job.PostString("http://197.189.232.202/istockserver.php", Query)
If I use the above, I get an error that the file is not found.
However, if I place the php file into a website folder:
B4X:
job.PostString("http://www.ecowatch.co.za/istockserver.php", Query)
The file is found and runs.
BUT, I have encountered another problem.
This is the debug log and error:
B4X:
LogCat connected to: B4A-Bridge: alps M7L
--------- beginning of main
--------- beginning of system
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Service (service1) Create **
** Service (service1) Start **
Connected to B4A-Bridge (Wifi)
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:anywheresoftware.b4a.samples.mysql
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Service (httputils2service) Create **
** Service (httputils2service) Start **
Response from server: <?



$databasehost = "localhost";

$databasename = "istock";

$databaseusername ="root";

$databasepassword = "Ecowatch!@#$%";



$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);

}

?>
main_jobdone (B4A line: 64)
PRODUCTS = parser.NextArray 'returns a list wi
java.lang.RuntimeException: JSON Array expected.
    at anywheresoftware.b4a.objects.collections.JSONParser.NextArray(JSONParser.java:62)
    at anywheresoftware.b4a.samples.mysql.main._jobdone(main.java:520)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
    at anywheresoftware.b4a.keywords.Common$5.run(Common.java:981)
    at android.os.Handler.handleCallback(Handler.java:815)
    at android.os.Handler.dispatchMessage(Handler.java:104)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5624)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
** Activity (main) Resume **

Here is my code:
B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MySQL Example
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

'Activity module
Sub Process_Globals
    Private PRODUCTS_LIST = "PRODUCTS_LIST", PRODUCT_BARCODE = "PRODUCT_BARCODE" As String
End Sub

Sub Globals
    Type TwoLines (First As String, Second As String)
    Dim lblPopulation As Label
    Dim ListView1 As ListView
    Dim lblCountry As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("1")
    FetchCountriesList
End Sub
Sub FetchCountriesList
    ProgressDialogShow("Fetching list of products")
    'Gets all the available countries
'    ExecuteRemoteQuery("SELECT name, id FROM countries ORDER BY id", PRODUCTS_LIST)
    ExecuteRemoteQuery("SELECT Description, ID FROM prodlisting ORDER BY ID", PRODUCTS_LIST)
End Sub


Sub ListView1_ItemClick (Position As Int, Value As Object)
    Dim tl As TwoLines
    tl = Value
    lblCountry.Text = tl.Second
    lblPopulation.Text = "Calling server..."
'    ExecuteRemoteQuery("SELECT population FROM countries WHERE id='" & tl.First & "'", PRODUCT_BARCODE)
    ExecuteRemoteQuery("SELECT BarCode FROM prodlisting WHERE ID='" & tl.First & "'", PRODUCT_BARCODE)
End Sub

Sub ExecuteRemoteQuery(Query As String, JobName As String)
    Dim job As HttpJob
    job.Initialize(JobName, Me)
'    job.PostString("http://www.b4x.com/android/countries.php", Query)
    job.PostString("http://www.ecowatch.co.za/istockserver.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
        parser.Initialize(res)
        Select Job.JobName
            Case PRODUCTS_LIST
                Dim PRODUCTS As List
                PRODUCTS.Initialize
                PRODUCTS = parser.NextArray 'returns a list with maps
                For i = 0 To PRODUCTS.Size - 1
                    Dim m As Map
                    m = PRODUCTS.Get(i)
                    'We are using a custom type named TwoLines (declared in Sub Globals).
                    'It allows us to later get the two values when the user presses on an item.
                    Dim tl As TwoLines
                    tl.First = m.Get("ID")
                    tl.Second = m.Get("Description")
                    ListView1.AddTwoLines2(tl.First, tl.Second, tl)
                Next
            Case PRODUCT_BARCODE
                Dim l As List
                l = parser.NextArray
                If l.Size = 0 Then
                    lblPopulation.Text = "N/A"
                Else
                    Dim m As Map
                    m = l.Get(0)
                    lblPopulation.Text = NumberFormat2(m.Get("BarCode"),0, 0, 0, True) & " (K)"
                End If
        End Select
    Else
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Please, if someone could help me overcome this, I would me muchos grateful.
 

Declan

Well-Known Member
Licensed User
Longtime User
The correct answer is this:
Note that it is better (simpler, more powerful, with better performance and safer) to use jRDC instead of the PHP script.
I am now attempting to setup a RDC with the JDBC.
I have a server running Windows Server 2008 R2.
When I test from my browser, I get the following error:
RemoteServer is running (Sat Feb 20 10:01:21 CAT 2016)
java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
driver:
B4X:
mysql-connector-java-5.1.38-bin.jar
config.properties:
B4X:
#Lines starting with '#' are comments.
#Backslash character at the end of line means that the command continues in the next line.
DriverClass=com.mysql.jdbc.Driver
JdbcUrl=jdbc:mysql://localhost/test?characterEncoding=utf8

#SQL Server
#DriverClass=net.sourceforge.jtds.jdbc.Driver
#JdbcUrl=jdbc:jtds:sqlserver://<database server ip>/<database>
User=root
Password=xxxxx
ServerPort=17178
#If Debug is true then this file will be reloaded on every query.
#This is useful if you need to modify the queries.
Debug=true

#commands
sql.create_table=CREATE TABLE animals (\
     id INT NOT NULL AUTO_INCREMENT,\
     name CHAR(30) NOT NULL,\
     image BLOB,\
     PRIMARY KEY (id))
sql.insert_animal=INSERT INTO animals VALUES (null, ?,?)
sql.select_animal=SELECT name, image FROM animals WHERE name = ?
RunRLC.Bat:
B4X:
"C:\Program Files\Java\jre1.8.0_73\bin\java" -Xmx256m -cp .;libs\*;jdbc_driver\* anywheresoftware.b4a.remotedatabase.RemoteServer
pause

I have given the required port assignments on the firewall.
There is something wrong with my configuration/setup and I cannot work this one out.
 

Declan

Well-Known Member
Licensed User
Longtime User
OK - Eish, got it working.
I created a new "fresh" MySQL connection and all is working
 

sultan87

Active Member
Licensed User
Longtime User
hello,
I have a problem trying to use it in your mysql project and adapt it to access my data base located on servers Free
Where do I put the .php file (gesttherm.php)
that put in lines

$ DatabaseHost = "localhost";
$ Databasename = "xxxx";
$ DatabaseUserName = "xxxx";
$ Databasepassword = "xxxxx";

best regards
 

Alisson

Active Member
Licensed User
Sultan87, with the page istockserver.php.

$ DatabaseHost = "localhost";
$ Databasename = "name_your_database";
$ DatabaseUserName = "name_to_acssess_database";
$ Databasepassword = "password_to_access_database";
 

sultan87

Active Member
Licensed User
Longtime User
Sultan87, with the page istockserver.php.

$ DatabaseHost = "localhost";
$ Databasename = "name_your_database";
$ DatabaseUserName = "name_to_acssess_database";
$ Databasepassword = "password_to_access_database";
thank's
quid istockserver.php
best regards
 

kostefar

Active Member
Licensed User
Longtime User
Dear All,

Maybe I missed it, but I cannot find it written anywhere here how one can insert a binary (image, mp3, zip etc) into a remote mysql table from b4x. I´m using php inbetween my android and mysql, so a bit of direction with what to put there wouldn´t be such a bad thing.. :)

Thanks!
 

macerau

Member
Licensed User
Longtime User
Please help me,
I know that it is simple, but I'm not finding the solution.
got a:
Dim LL List
upload_2016-3-29_14-13-40.png


I want to turn this into a MAP and use like this:
Dim m The Map
Dim c the string

m = LL.Get (0)

c = m.Get ("Camp1") 'AND C = "-"

or

c = m.Get (1) "AND C =" - "

where I am going wrong?
thank you
 

Paul Edwards

Member
Licensed User
Longtime User
Hi Erel,

Tutorial is very good.

I have a working database and can connect to it and list queries on my android device.

One of the fields in my database is DATE and the field prints as YYYY-MM-DD on my android device. To get around this I have tried to use SQL functions such as CONVERT() and DATE_FORMAT() but with no success. I want to achieve DD-MM-YYYY on the android device. Is there a B4A function that I can use instead and do the processing client-side?

Thanks
Paul
 
Status
Not open for further replies.
Top