Google officially announced Kotlin Support at Google I/O 2017. If you haven’t heard it yet, Kotlin is the brand new language for Android Application Development. It is developed by IntelliJ IDEA the same company that has given the Android Studio IDE. Today in this post we will learn how we can perform networking using Volley with Kotlin.
If you want to learn Kotlin from starting then go through this playlist.
Before going further you should get the Android Studio 3.0 Canary 1. You can also add Kotlin Plugin to your existing Android Studio.
So lets start. Again we will start with building database and php script. This time I will do it little differently. As we have already seen it many times. Still for building secured RESTful APIs using SLIM Framework you can check this tutorial.
Creating Database
- Open PhpMyAdmin and create the following table.
- Thats it for the database now we will create the PHP project.
Creating Web Services
- Now come inside htdocs folder (if you are using xampp) and create your project folder. Inside the project folder again create two folders named includes and v1.
- As you can see in the image I have my project directory named WebApi and inside that I have includes and v1.
- Now come inside includes and create a new PHP file named Constants.php.
1 2 3 4 5 6 7 8 |
<?php define('DB_HOST','localhost'); define('DB_USERNAME','root'); define('DB_PASSWORD',''); define('DB_NAME', 'simplifiedcoding'); |
- You should change the values accordingly here.
Connecting to Database
- Now create one more file here named DbConnect.php and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php class DbConnect { //Variable to store database link private $con; //Class constructor function __construct() { } //This method will connect to the database function connect() { //Including the constants.php file to get the database constants include_once dirname(__FILE__) . '/Constants.php'; //connecting to mysql database $this->con = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME); //Checking if any error occured while connecting if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); return null; } //finally returning the connection link return $this->con; } } |
Performing Database Operation
- Now we need another class to handle database operations. So create a file named DbOperation.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?php class DbOperation { private $con; function __construct() { require_once dirname(__FILE__) . '/DbConnect.php'; $db = new DbConnect(); $this->con = $db->connect(); } //adding a record to database public function createArtist($name, $genre){ $stmt = $this->con->prepare("INSERT INTO artists (name, genre) VALUES (?, ?)"); $stmt->bind_param("ss", $name, $genre); if($stmt->execute()) return true; return false; } //fetching all records from the database public function getArtists(){ $stmt = $this->con->prepare("SELECT id, name, genre FROM artists"); $stmt->execute(); $stmt->bind_result($id, $name, $genre); $artists = array(); while($stmt->fetch()){ $temp = array(); $temp['id'] = $id; $temp['name'] = $name; $temp['genre'] = $genre; array_push($artists, $temp); } return $artists; } } |
Handling API Calls
- Now come inside v1 folder and create a file named index.php, here we will handle all the API calls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<?php //adding dboperation file require_once '../includes/DbOperation.php'; //response array $response = array(); //if a get parameter named op is set we will consider it as an api call if(isset($_GET['op'])){ //switching the get op value switch($_GET['op']){ //if it is add artist //that means we will add an artist case 'addartist': if(isset($_POST['name']) && isset($_POST['genre'])){ $db = new DbOperation(); if($db->createArtist($_POST['name'], $_POST['genre'])){ $response['error'] = false; $response['message'] = 'Artist added successfully'; }else{ $response['error'] = true; $response['message'] = 'Could not add artist'; } }else{ $response['error'] = true; $response['message'] = 'Required Parameters are missing'; } break; //if it is getartist that means we are fetching the records case 'getartists': $db = new DbOperation(); $artists = $db->getArtists(); if(count($artists)<=0){ $response['error'] = true; $response['message'] = 'Nothing found in the database'; }else{ $response['error'] = false; $response['artists'] = $artists; } break; default: $response['error'] = true; $response['message'] = 'No operation to perform'; } }else{ $response['error'] = false; $response['message'] = 'Invalid Request'; } //displaying the data in json echo json_encode($response); |
Testing the API Calls
- Again I am using POSTMAN to test the API.
- So as you can see the API is working fine. You can get the source code from the below link.
[sociallocker id=1372] Web Service Code Download [/sociallocker]
Making Android Project with Kotlin
- Now create a new Android Studio project. Just remember you have to mark the Include Kotlin Support while creating the project.
- Now inside activity_main.xml create the following UI.
- You can use the following XML code for this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="net.simplifiedcoding.firstkotlinapp.MainActivity"> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add New Artist" android:textAppearance="@style/TextAppearance.AppCompat.Headline" tools:layout_editor_absoluteX="112dp" tools:layout_editor_absoluteY="16dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginTop="16dp" app:layout_constraintEnd_toEndOf="parent" /> <EditText android:id="@+id/editTextArtistName" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:ems="10" android:hint="Enter artist name" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="53dp" /> <Spinner android:id="@+id/spinnerGenre" android:layout_width="0dp" android:layout_height="wrap_content" android:entries="@array/genres" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="107dp" android:layout_marginTop="11dp" app:layout_constraintTop_toBottomOf="@+id/editTextArtistName" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" /> <Button android:id="@+id/buttonAddArtist" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="14dp" android:text="Add Artist" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/spinnerGenre" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="145dp" /> <Button android:id="@+id/buttonViewArtist" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="12dp" android:text="View Artists" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/buttonAddArtist" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="205dp" /> </android.support.constraint.ConstraintLayout> |
- For the spinner entries define the following array in your strings.xml file.
1 2 3 4 5 6 7 8 9 10 |
<array name="genres"> <item>Rock</item> <item>Pop</item> <item>Jazz</item> <item>Sufi</item> <item>Bollywood</item> <item>Hollywood</item> </array> |
- Now we will perform the Add operation using API Call.
Adding Volley to the Project
- Come inside app level build.gradle file and add the following dependencies.
1 2 3 |
compile 'com.android.volley:volley:1.0.0' |
Creating a Singleton Class for Volley
- If the application uses something frequently using a Single instance of that is a good idea. So here we will create a Singleton class for volley requests.
- Inside your package create a Kotlin file named VolleySingleton.kt and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package net.simplifiedcoding.firstkotlinapp import android.app.Application import com.android.volley.Request import com.android.volley.RequestQueue import com.android.volley.toolbox.Volley /** * Created by Belal on 5/16/2017. */ class VolleySingleton : Application() { override fun onCreate() { super.onCreate() instance = this } val requestQueue: RequestQueue? = null get() { if (field == null) { return Volley.newRequestQueue(applicationContext) } return field } fun <T> addToRequestQueue(request: Request<T>) { request.tag = TAG requestQueue?.add(request) } companion object { private val TAG = VolleySingleton::class.java.simpleName @get:Synchronized var instance: VolleySingleton? = null private set } } |
- Now we need to add the above class in the manifest.
1 2 3 4 5 6 7 8 9 10 11 12 |
<uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:name=".VolleySingleton" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> |
- As you can see I have also added the internet permission as it is required.
Creating and Object for holding EndPoints
- Create a new Kotlin file named EndPoints.kt and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package net.simplifiedcoding.firstkotlinapp /** * Created by Belal on 5/21/2017. */ object EndPoints { private val URL_ROOT = "http://192.168.1.106/WebApi/v1/?op=" val URL_ADD_ARTIST = URL_ROOT + "addartist" val URL_GET_ARTIST = URL_ROOT + "getartists" } |
- You can see we are storing the API URLs here. Make sure you have changed the IP accordingly.
Adding Data to MySQL using Volley with Kotlin
- Come inside MainActivity.kt and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
package net.simplifiedcoding.firstkotlinapp import android.content.Intent import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.widget.EditText import android.widget.Spinner import android.widget.Toast import com.android.volley.AuthFailureError import com.android.volley.Request import com.android.volley.Response import com.android.volley.VolleyError import com.android.volley.toolbox.StringRequest import org.json.JSONException import org.json.JSONObject class MainActivity : AppCompatActivity() { //edittext and spinner private var editTextArtistName: EditText? = null private var spinnerGenre: Spinner? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //getting it from xml editTextArtistName = findViewById(R.id.editTextArtistName) as EditText spinnerGenre = findViewById(R.id.spinnerGenre) as Spinner //adding a click listener to button findViewById(R.id.buttonAddArtist).setOnClickListener { addArtist() } //in the second button click //opening the activity to display all the artist //it will give error as we dont have this activity so remove this part for now to run the app findViewById(R.id.buttonViewArtist).setOnClickListener { val intent = Intent(applicationContext, ViewArtistsActivity::class.java) startActivity(intent) } } //adding a new record to database private fun addArtist() { //getting the record values val name = editTextArtistName?.text.toString() val genre = spinnerGenre?.selectedItem.toString() //creating volley string request val stringRequest = object : StringRequest(Request.Method.POST, EndPoints.URL_ADD_ARTIST, Response.Listener<String> { response -> try { val obj = JSONObject(response) Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show() } catch (e: JSONException) { e.printStackTrace() } }, object : Response.ErrorListener { override fun onErrorResponse(volleyError: VolleyError) { Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show() } }) { @Throws(AuthFailureError::class) override fun getParams(): Map<String, String> { val params = HashMap<String, String>() params.put("name", name) params.put("genre", genre) return params } } //adding request to queue VolleySingleton.instance?.addToRequestQueue(stringRequest) } } |
- Now run the application and test.
- You can see we got the success message. You can check the database the record should be there.
- Now we will try the second API call where we are fetching the values.
Fetching Data from MySQL using Volley with Kotlin
- Create a new Activity named ViewArtistsActivity and in the layout file write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="net.simplifiedcoding.firstkotlinapp.ViewArtistsActivity"> <ListView android:id="@+id/listViewArtists" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </android.support.constraint.ConstraintLayout> |
- As you can see we have only a single list here to display all the artists in a list. Now we also need a custom layout file for the list.
- So create a layout file named layout_list_artist.xml and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="Atif Aslam" android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" android:id="@+id/textViewName" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Rock" android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" android:id="@+id/textViewGenre" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> |
- Here we have only Two TextViews for name and genre.
- Now we will define the model for the Artist.
- So again create a new Kotlin class named Artist and write the following code.
1 2 3 4 5 6 7 8 9 |
package net.simplifiedcoding.firstkotlinapp /** * Created by Belal on 5/21/2017. */ class Artist(val name: String, val genre: String) |
- Now we will define our custom adapter. So we need one more class. I have created a class named ArtistList.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package net.simplifiedcoding.firstkotlinapp import android.app.Activity import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.TextView /** * Created by Belal on 5/21/2017. */ class ArtistList(private val context: Activity, internal var artists: List<Artist>) : ArrayAdapter<Artist>(context, R.layout.layout_list_artist, artists) { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val inflater = context.layoutInflater val listViewItem = inflater.inflate(R.layout.layout_list_artist, null, true) val textViewName = listViewItem.findViewById(R.id.textViewName) as TextView val textViewGenre = listViewItem.findViewById(R.id.textViewGenre) as TextView val artist = artists[position] textViewName.text = artist.name textViewGenre.text = artist.genre return listViewItem } } |
- Now come inside ViewArtistsActivity and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package net.simplifiedcoding.firstkotlinapp import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.widget.ListView import android.widget.Toast import com.android.volley.Request import com.android.volley.Response import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.Volley import org.json.JSONException import org.json.JSONObject class ViewArtistsActivity : AppCompatActivity() { private var listView: ListView? = null private var artistList: MutableList<Artist>? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_view_artists) listView = findViewById(R.id.listViewArtists) as ListView artistList = mutableListOf<Artist>() loadArtists() } private fun loadArtists() { val stringRequest = StringRequest(Request.Method.GET, EndPoints.URL_GET_ARTIST, Response.Listener<String> { s -> try { val obj = JSONObject(s) if (!obj.getBoolean("error")) { val array = obj.getJSONArray("artists") for (i in 0..array.length() - 1) { val objectArtist = array.getJSONObject(i) val artist = Artist( objectArtist.getString("name"), objectArtist.getString("genre") ) artistList!!.add(artist) val adapter = ArtistList(this@ViewArtistsActivity, artistList!!) listView!!.adapter = adapter } } else { Toast.makeText(getApplicationContext(), obj.getString("message"), Toast.LENGTH_LONG).show() } } catch (e: JSONException) { e.printStackTrace() } }, Response.ErrorListener { volleyError -> Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show() }) val requestQueue = Volley.newRequestQueue(this) requestQueue.add<String>(stringRequest) } } |
- Now try running the application again.
- Bingo! it is working fine. So this was volley with kotlin.
- You can get the source code for this volley with kotlin example from below.
[sociallocker id=1372] Volley With Kotlin Source Code [/sociallocker]
So thats all for this Volley with Kotlin example friends. You may have realized that Kotlin code is lesser as compared to the equivalent Java code. So try practicing Kotlin and once you are used to it you will find it much easier than Java. We will post more about Kotlin from scratch. Till then, please SHARE this post if you found it useful. Thank You 🙂