Android Kotlin Project – Online Food Delivery App

Hey there, Android enthusiasts, greetings from TechVidvan. Today we are going to see and learn how to implement an Android project that is an online food delivery app in Android Studio. We’ll understand the complete project development in this article.

Online food delivery applications are useful for getting food from your preferred restaurants to your home without having to go to the restaurant in person. Users of this Android application will have access to a large selection of restaurants from which to choose and place orders.

About Android Kotlin Online Food Delivery App

It will be advantageous for beginners to learn about app development using Kotlin and how to fetch data from JSON files. You will become accustomed to using Android Studio and Kotlin to develop and add functionalities to the application. The online food delivery application will provide users with a list of food establishments to choose from and place an order from that establishment accordingly.

Details about the user interface are as follows:

1. A splash screen activity displaying the name of the application will appear when the app is first launched.

2. After the splash screen, the user interface will show a list of restaurants from which they can select one to place an order.

3. After the user selects a restaurant, the UI displays the food items the restaurant can deliver. Below each food item that is available, there is an “Add to cart” button that the customer can click on to include that specific food item in their order.

4. After the user has added all the food items to their order and clicked on the button ‘Checkout’, the UI will show the preview of their order, also, the user is required to fill up some details in order to complete the order.

5. Once the user clicks on the ‘Place your Order’ button, the UI will display an ‘Order placed successfully’ message on the screen.

Features of the Android Kotlin Online Food Delivery Application:

1. Users can place food orders from the restaurants of their choice without going there in person with the assistance of the Android application.

2. The user can choose from a list of restaurants provided by the application.

3. A range of food items on the menu are accessible for online delivery at each and every restaurant mentioned in the Android app.

4. The user has the option to order up to 10 portions of each meal item from the chosen restaurant.

5. The consumer has the option to quickly evaluate their order and the amount that must be paid at delivery before finalizing the transaction.

6. The preview of the order contains all the items added to the cart by the user, subtotal of each and every individual item, at the bottom, the final amount inclusive of delivery charges is displayed too.

Prerequisites for Online Food Delivery App Using Android Kotlin

To develop this Android Kotlin application, the requirements and prerequisites are as follows:

1. Kotlin: You first need to be familiar with Kotlin programming. Given that we will write the app code in the programming language Kotlin, it is necessary.
2. XML: Another crucial component of our Android application is XML. It will be applied to the development of the application’s user interface.
3. Android Studio: The core of our application is Android Studio because that is how we will develop it. Also included with Android Studio is an Android virtual device that can be used to test the functionality of applications.

Download Android Kotlin Online Food Delivery App Project

Please download the source code of Android Kotlin Online Food Delivery Project: Android Kotlin Online Food Delivery Project Code.

Steps to Create Online Food Delivery App using Android Kotlin

We’ll now start working on developing an online food ordering app. Before putting the code into practice, we will learn about its purpose and function throughout this article. So, let’s look at the files and functions needed to run the code:

You must complete a set of steps in order to create this Android online food delivery app. We are here to walk you through every stage of developing an app.

1. Extract all the files from the downloaded zip file to the location of your choice.
2. Open Android Studio.
3. Click on File, then Open.
4. Find and select the folder you extracted earlier and click on OK.

food delivere

Before going through the files that are responsible for the UI and functionality of the application, you will have to follow some things mentioned as follow:

1. Create a new folder, ‘raw’, in the ‘res’ file directory. Inside the raw folder, create a new file, ‘restaurant.json’. This json file will contain the list of restaurants, food items, price of each item, etc.

[
  {
    "name":"McDonald's",
    "address":"Empire Building, No 134 to 136",
    "delivery_charge": 5,
    "image":"https://upload.wikimedia.org/wikinews/en/9/97/Mcdonalds-logo.JPG",
    "hours":{
      "Sunday":"11:00 AM - 7:00 PM",
      "Monday":"10:00 AM - 10:00 PM",
      "Tuesday":"10:00 AM - 10:00 PM",
      "Wednesday":"10:00 AM - 8:00 PM",
      "Thursday":"10:00 AM - 10:00 PM",
      "Friday":"10:00 AM - 10:00 PM",
      "Saturday":"9:00 AM - 2:00 PM"
    },
    "menus": [
      {
        "name": "Chocolate Shake",
        "price": 120,
        "url": "https://i.pinimg.com/564x/65/c9/94/65c9945af0188e99b76b2ede42833781.jpg"
      },
      {
        "name": "Strawberry Shake",
        "price": 120,
        "url": "https://i.pinimg.com/564x/61/75/ff/6175ff149c27c64ce1f20717a3b56ba6.jpg"
      },
      {
        "name": "Pizza McPuff",
        "price": 35,
        "url": "https://live.staticflickr.com/8232/8477233192_f893a154a3_c.jpg"
      },
      {
        "name": "McNuggets",
        "price": 90,
        "url": "https://i.pinimg.com/564x/15/4f/19/154f19252423d4689dbd56abe9e55fbf.jpg"
      },
      {
        "name": "Veg Maharaja Mac",
        "price": 160,
        "url": "https://i.pinimg.com/564x/8f/32/72/8f32721adbb11e95a251a9922ead3762.jpg"
      },
      {
        "name": "Chicken Wrap",
        "price": 145,
        "url": "https://i.pinimg.com/236x/11/d2/ff/11d2ff0f50c34b4ff16d13e48bba98ad.jpg"
      }
    ]
  }]

2. To be able to use the above json file and fetch data from it, you will have to add some dependencies in the ‘build.gradle’ file.

implementation "com.github.bumptech.glide:glide:4.12.0"
implementation "com.google.code.gson:gson:2.9.0"

Online Food Delivery

Let’s go through each file in this project one at a time as we comprehend how the application works.

1. The “activity_splash” is an XML file which is responsible for creating splash activity when the application is launched.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".SplashActivity"
    android:background="@color/purple_200">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="serif"
        android:text="Online Food Delivery App"
        android:textColor="@color/white"
        android:textSize="32dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.425" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="serif"
        android:text="TechVidvan"
        android:textColor="@color/white"
        android:textSize="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.484" />

</androidx.constraintlayout.widget.ConstraintLayout>

Online Food Delivery output

2. The “activity_main” is an XML file which is responsible for creating the user interface to display the list of restaurants.

<androidx.constraintlayout.widget.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"
    android:background="@color/purple_200"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewRestaurant"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:paddingBottom="20dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

outpt Online Food Delivery

3. The “recycler_restaurant_list_row” is a XML file containing a card view which specifies the way in which each restaurant should be displayed in the main activity.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:cardCornerRadius="10dp"
        android:layout_margin="20dp"
        >
        <ImageView android:id="@+id/thumbImage"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_gravity="start"
            android:layout_margin="10dp"
            />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_marginStart="140dp"
            android:layout_gravity="center_vertical">

            <TextView android:id="@+id/tvRestaurantName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textStyle="bold"
                android:textColor="@color/purple_500"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:layout_marginEnd="10dp"
                />
            <TextView android:id="@+id/tvRestaurantAddress"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textStyle="bold"
                android:textColor="@color/black"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                />

            <TextView android:id="@+id/tvRestaurantHours"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textStyle="bold"
                android:textColor="@color/black"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                />


        </LinearLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

recycler restaurant list row

4. The “activity_restaurant_menu” is an XML file responsible for UI where the available food items are displayed.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".RestaurantMenuActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/menuRecyclerVuew"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_margin="10dp"
        android:paddingBottom="80dp" />

    <TextView android:id="@+id/checkoutButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Checkout"
        android:textSize="16sp"
        android:textStyle="bold"
        android:gravity="center"
        android:padding="10dp"
        android:layout_margin="10dp"
        android:textColor="@color/white"
        android:background="@drawable/button_bg"/>

</androidx.constraintlayout.widget.ConstraintLayout>

activity restaurant menu

5. The “activity_place_your_model” is an XML file which is responsible for creating UI where the order preview will be displayed.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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=".PlaceYourOrderActivity"
    android:paddingBottom="10dp"
    >
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <TextView android:id="@+id/tvCustomerDetails"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_margin="10dp"
            android:text="Customer Details"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <EditText android:id="@+id/inputName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvCustomerDetails"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter your name"/>

        <EditText android:id="@+id/inputAddress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputName"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter your address" />

        <EditText android:id="@+id/inputCity"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputAddress"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter your city" />

        <EditText android:id="@+id/inputState"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputCity"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter your state" />

        <EditText android:id="@+id/inputZip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputState"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter your zip"
            android:inputType="number"
            android:maxLength="6" />

        <TextView android:id="@+id/tvCardDetails"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/inputZip"
            android:layout_margin="10dp"
            android:text="Card Details"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <EditText android:id="@+id/inputCardNumber"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvCardDetails"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter Card Number"
            android:inputType="number"
            android:maxLength="16"/>

        <EditText android:id="@+id/inputCardExpiry"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputCardNumber"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter Card expiry(mm/yyyy)"
            android:maxLength="6"/>

        <EditText android:id="@+id/inputCardPin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/inputCardExpiry"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginTop="05dp"
            android:layout_marginBottom="05dp"
            android:hint="Enter Card pin(3 digits)"
            android:inputType="number"
            android:maxLength="3"/>

        <TextView android:id="@+id/tvTotalItems"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/inputCardPin"
            android:layout_margin="10dp"
            android:text="Total items in cart"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/cartItemsRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvTotalItems"
            android:nestedScrollingEnabled="false"/>

        <TextView android:id="@+id/tvSubtotal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cartItemsRecyclerView"
            android:layout_margin="10dp"
            android:text="Sub total"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/tvSubtotalAmount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/cartItemsRecyclerView"
            android:layout_margin="10dp"
            android:text="Rs. 0.0"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/tvDeliveryCharge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvSubtotal"
            android:layout_margin="10dp"
            android:text="Delivery Charge"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/tvDeliveryChargeAmount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvSubtotal"
            android:layout_margin="10dp"
            android:text="Rs. 0.0"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/tvTotal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvDeliveryCharge"
            android:layout_margin="10dp"
            android:text="Total"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/tvTotalAmount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvDeliveryCharge"
            android:layout_margin="10dp"
            android:text="Rs. 0.0"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <TextView android:id="@+id/buttonPlaceYourOrder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvTotal"
            android:text="Place your order"
            android:textSize="16sp"
            android:textStyle="bold"
            android:gravity="center"
            android:textColor="@color/white"
            android:padding="10dp"
            android:layout_margin="10dp"
            android:background="@drawable/button_bg"
            />


    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

activity place your model

6. ‘activity_order_succes’ is an XML file responsible for creating the UI of the activity when the order is placed by the user.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
    >


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:textSize="30sp"
        android:textStyle="bold"
        android:text="Order placed successfully."
        android:layout_margin="30dp"
        />

    <TextView android:id="@+id/buttonDone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Done"
        android:textSize="16sp"
        android:textStyle="bold"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="@color/white"
        android:layout_margin="10dp"
        android:background="@drawable/button_bg"
        />


</androidx.constraintlayout.widget.ConstraintLayout>

activity success order

7. ‘SplashActivity’ is a kotlin file which is responsible for displaying the splash screen when the application is initialized.

class SplashActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        val actionBar = supportActionBar
        actionBar!!.hide()

        Handler().postDelayed({
            startActivity(Intent(this@SplashActivity, MainActivity::class.java))
            finish()
        }, 2000)
    }
}

8. ‘MainActivity.kt’ is a kotlin file which is responsible for fetching the names of restaurants from the json file and displaying a list of restaurants to the user.

class MainActivity : AppCompatActivity(), RestaurantListAdapter.RestaurantListClickListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val actionBar: ActionBar? = supportActionBar
        actionBar?.setTitle("Restaurant List")

        val restaurantModel = getRestaurantData()
        initRecyclerView(restaurantModel)
    }

    private fun initRecyclerView(restaurantList: List<RestaurentModel?>?) {
        val recyclerViewRestaurant = findViewById<RecyclerView>(R.id.recyclerViewRestaurant)
        recyclerViewRestaurant.layoutManager = LinearLayoutManager(this)
        val adapter = RestaurantListAdapter(restaurantList, this)
        recyclerViewRestaurant.adapter =adapter
    }

    private fun getRestaurantData(): List<RestaurentModel?>? {
        val inputStream: InputStream = resources.openRawResource(R.raw.restuarant)
        val writer: Writer = StringWriter()
        val buffer = CharArray(1024)
        try {
            val reader: Reader = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
            var n : Int
            while (reader.read(buffer).also { n = it } != -1) {
                writer.write(buffer, 0, n)

            }

        }catch (e: Exception){}
        val jsonStr: String = writer.toString()
        val gson = Gson()
        val restaurantModel = gson.fromJson<Array<RestaurentModel>>(jsonStr, Array<RestaurentModel>::class.java).toList()

        return restaurantModel
    }

    override fun onItemClick(restaurantModel: RestaurentModel) {
        val intent = Intent(this@MainActivity, RestaurantMenuActivity::class.java)
        intent.putExtra("RestaurantModel", restaurantModel)
        startActivity(intent)
    }
}

9. ‘RestaurantListAdapter.kt’ is an adapter which sets the restaurant data in the MainActivity’s recycler view.

class RestaurantMenuActivity : AppCompatActivity(), MenuListAdapter.MenuListClickListener {

    private var itemsInTheCartList: MutableList<Menus?>? = null
    private var totalItemInCartCount = 0
    private  var menuList: List<Menus?>? = null
    private var menuListAdapter: MenuListAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_restaurant_menu)

        val restaurantModel = intent?.getParcelableExtra<RestaurentModel>("RestaurantModel")

        val actionBar: ActionBar? = supportActionBar
        actionBar?.setTitle(restaurantModel?.name)
        actionBar?.setSubtitle(restaurantModel?.address)
        actionBar?.setDisplayHomeAsUpEnabled(true)

        menuList = restaurantModel?.menus

        initRecyclerView(menuList)
        checkoutButton.setOnClickListener {
            if(itemsInTheCartList != null && itemsInTheCartList!!.size <= 0) {
                Toast.makeText(this@RestaurantMenuActivity, "Please add some items in cart", Toast.LENGTH_LONG).show()
            }
            else {
                restaurantModel?.menus = itemsInTheCartList
                val intent = Intent(this@RestaurantMenuActivity, PlaceYourOrderActivity::class.java)
                intent.putExtra("RestaurantModel", restaurantModel)
                startActivityForResult(intent, 1000)
            }
        }

    }
    private fun initRecyclerView(menus: List<Menus?>?) {
        menuRecyclerVuew.layoutManager = GridLayoutManager(this, 2)
        menuListAdapter = MenuListAdapter(menus, this)
        menuRecyclerVuew.adapter =menuListAdapter
    }

    override fun addToCartClickListener(menu: Menus) {
        if(itemsInTheCartList == null) {
            itemsInTheCartList = ArrayList()
        }
        itemsInTheCartList?.add(menu)
        totalItemInCartCount = 0
        for(menu in itemsInTheCartList!!) {
            totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
        }
        checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"

    }

    override fun updateCartClickListener(menu: Menus) {
        val index = itemsInTheCartList!!.indexOf(menu)
        itemsInTheCartList?.removeAt(index)
        itemsInTheCartList?.add(menu)
        totalItemInCartCount = 0
        for(menu in itemsInTheCartList!!) {
            totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
        }
        checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"
    }

    override fun removeFromCartClickListener(menu: Menus) {
        if(itemsInTheCartList!!.contains(menu)) {
            itemsInTheCartList?.remove(menu)
            totalItemInCartCount = 0
            for(menu in itemsInTheCartList!!) {
                totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
            }
            checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId) {
            android.R.id.home -> finish()
            else -> {}
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode == 1000 && resultCode == RESULT_OK) {
            finish()
        }
    }
}

10. “RestaurantMenuActivity” is a class which is responsible for fetching the details from json file about a particular restaurant and displaying it to the user.

class RestaurantMenuActivity : AppCompatActivity(), MenuListAdapter.MenuListClickListener {

    private var itemsInTheCartList: MutableList<Menus?>? = null
    private var totalItemInCartCount = 0
    private  var menuList: List<Menus?>? = null
    private var menuListAdapter: MenuListAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_restaurant_menu)

        val restaurantModel = intent?.getParcelableExtra<RestaurentModel>("RestaurantModel")

        val actionBar: ActionBar? = supportActionBar
        actionBar?.setTitle(restaurantModel?.name)
        actionBar?.setSubtitle(restaurantModel?.address)
        actionBar?.setDisplayHomeAsUpEnabled(true)

        menuList = restaurantModel?.menus

        initRecyclerView(menuList)
        checkoutButton.setOnClickListener {
            if(itemsInTheCartList != null && itemsInTheCartList!!.size <= 0) {
                Toast.makeText(this@RestaurantMenuActivity, "Please add some items in cart", Toast.LENGTH_LONG).show()
            }
            else {
                restaurantModel?.menus = itemsInTheCartList
                val intent = Intent(this@RestaurantMenuActivity, PlaceYourOrderActivity::class.java)
                intent.putExtra("RestaurantModel", restaurantModel)
                startActivityForResult(intent, 1000)
            }
        }

    }
    private fun initRecyclerView(menus: List<Menus?>?) {
        menuRecyclerVuew.layoutManager = GridLayoutManager(this, 2)
        menuListAdapter = MenuListAdapter(menus, this)
        menuRecyclerVuew.adapter =menuListAdapter
    }

    override fun addToCartClickListener(menu: Menus) {
        if(itemsInTheCartList == null) {
            itemsInTheCartList = ArrayList()
        }
        itemsInTheCartList?.add(menu)
        totalItemInCartCount = 0
        for(menu in itemsInTheCartList!!) {
            totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
        }
        checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"

    }

    override fun updateCartClickListener(menu: Menus) {
        val index = itemsInTheCartList!!.indexOf(menu)
        itemsInTheCartList?.removeAt(index)
        itemsInTheCartList?.add(menu)
        totalItemInCartCount = 0
        for(menu in itemsInTheCartList!!) {
            totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
        }
        checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"
    }

    override fun removeFromCartClickListener(menu: Menus) {
        if(itemsInTheCartList!!.contains(menu)) {
            itemsInTheCartList?.remove(menu)
            totalItemInCartCount = 0
            for(menu in itemsInTheCartList!!) {
                totalItemInCartCount = totalItemInCartCount + menu?.totalInCart!!
            }
            checkoutButton.text = "Checkout (" + totalItemInCartCount +") Items"
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId) {
            android.R.id.home -> finish()
            else -> {}
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode == 1000 && resultCode == RESULT_OK) {
            finish()
        }
    }
}

11. “MenuListAdapter” is a class which is responsible for setting the food items in the recycler view of RestaurantMenuActivity.

class MenuListAdapter(val menuList: List<Menus?>?, val clickListener: MenuListClickListener): RecyclerView.Adapter<MenuListAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): MenuListAdapter.MyViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.menu_list_row, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MenuListAdapter.MyViewHolder, position: Int) {
        holder.bind(menuList?.get(position)!!)
    }

    override fun getItemCount(): Int {
        return if(menuList == null)return 0 else menuList.size
    }

    inner class MyViewHolder(view: View): RecyclerView.ViewHolder(view) {
        var thumbImage: ImageView = view.thumbImage
        val menuName: TextView = view.menuName
        val menuPrice: TextView = view.menuPrice
        val addToCartButton: TextView = view.addToCartButton
        val addMoreLayout: LinearLayout = view.addMoreLayout
        val imageMinus: ImageView = view.imageMinus
        val imageAddOne: ImageView = view.imageAddOne
        val tvCount: TextView = view.tvCount

        fun bind(menus: Menus) {
            menuName.text = menus?.name
            menuPrice.text = "Price: Rs. ${menus?.price}"
            addToCartButton.setOnClickListener {
                menus?.totalInCart = 1
                clickListener.addToCartClickListener(menus)
                addMoreLayout?.visibility = View.VISIBLE
                addToCartButton.visibility = View.GONE
                tvCount.text = menus?.totalInCart.toString()
            }
            imageMinus.setOnClickListener {
                var total: Int =  menus.totalInCart
                total--
                if(total > 0) {
                    menus?.totalInCart = total
                    clickListener.updateCartClickListener(menus)
                    tvCount.text = menus?.totalInCart.toString()
                } else {
                    menus.totalInCart = total
                    clickListener.removeFromCartClickListener(menus)
                    addMoreLayout.visibility = View.GONE
                    addToCartButton.visibility = View.VISIBLE
                }
            }
            imageAddOne.setOnClickListener {
                var total: Int  = menus.totalInCart
                total++
                if(total <= 10) {
                    menus.totalInCart = total
                    clickListener.updateCartClickListener(menus)
                    tvCount.text = total.toString()
                }
            }

            Glide.with(thumbImage)
                .load(menus?.url)
                .into(thumbImage)
        }
    }

    interface MenuListClickListener {
        fun addToCartClickListener(menu: Menus)
        fun updateCartClickListener(menu: Menus)
        fun removeFromCartClickListener(menu: Menus)
    }
}

12. ‘PlaceYourOrderActivity.kt’ is a class which is responsible for the functioning of the activity where the user has to fill required details for delivery and will display the preview of the order.

class PlaceYourOrderActivity : AppCompatActivity() {

    var placeYourOrderAdapter: PlaceYourOrderAdapter? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_place_your_order)

        val restaurantModel: RestaurentModel? = intent.getParcelableExtra("RestaurantModel")
        val actionbar: ActionBar? = supportActionBar
        actionbar?.setTitle(restaurantModel?.name)
        actionbar?.setSubtitle(restaurantModel?.address)
        actionbar?.setDisplayHomeAsUpEnabled(true)

        buttonPlaceYourOrder.setOnClickListener {
            onPlaceOrderButtonCLick(restaurantModel)
        }

        initRecyclerView(restaurantModel)
        calculateTotalAmount(restaurantModel)
    }

    private fun initRecyclerView(restaurantModel: RestaurentModel?) {
        cartItemsRecyclerView.layoutManager = LinearLayoutManager(this)
        placeYourOrderAdapter = PlaceYourOrderAdapter(restaurantModel?.menus)
        cartItemsRecyclerView.adapter =placeYourOrderAdapter
    }

    private fun calculateTotalAmount(restaurantModel: RestaurentModel?) {
        var subTotalAmount = 0f
        for(menu in restaurantModel?.menus!!) {
            subTotalAmount += menu?.price!!  * menu.totalInCart

        }
        tvSubtotalAmount.text = "Rs."+ String.format("%.2f", subTotalAmount)
        tvDeliveryChargeAmount.text = "Rs."+String.format("%.2f", restaurantModel.delivery_charge?.toFloat())
        subTotalAmount += restaurantModel?.delivery_charge?.toFloat()!!
        tvTotalAmount.text = "Rs."+ String.format("%.2f", subTotalAmount)
    }

    private fun onPlaceOrderButtonCLick(restaurantModel: RestaurentModel?) {
        if(TextUtils.isEmpty(inputName.text.toString())) {
            inputName.error =  "Enter your name"
            return
        } else if(TextUtils.isEmpty(inputAddress.text.toString())) {
            inputAddress.error =  "Enter your address"
            return
        } else if(TextUtils.isEmpty(inputCity.text.toString())) {
            inputCity.error =  "Enter your City Name"
            return
        } else if(TextUtils.isEmpty(inputZip.text.toString())) {
            inputZip.error =  "Enter your Zip code"
            return
        } else if( TextUtils.isEmpty(inputCardNumber.text.toString())) {
            inputCardNumber.error =  "Enter your credit card number"
            return
        } else if( TextUtils.isEmpty(inputCardExpiry.text.toString())) {
            inputCardExpiry.error =  "Enter your credit card expiry"
            return
        } else if( TextUtils.isEmpty(inputCardPin.text.toString())) {
            inputCardPin.error =  "Enter your credit card pin/cvv"
            return
        }
        val intent = Intent(this@PlaceYourOrderActivity, SuccessOrderActivity::class.java)
        intent.putExtra("RestaurantModel", restaurantModel)
        startActivity(intent)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId) {
            android.R.id.home -> finish()
            else -> {}
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onBackPressed() {
        super.onBackPressed()
        setResult(RESULT_CANCELED)
        finish()
    }
}

13. ‘SuccessOrderActivity’ is a class which is displays the success order activity once the order has been placed.

class SuccessOrderActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_success_order)

        val restaurantModel: RestaurentModel? = intent.getParcelableExtra("RestaurantModel")
        val actionbar: ActionBar? = supportActionBar
        actionbar?.setTitle(restaurantModel?.name)
        actionbar?.setSubtitle(restaurantModel?.address)
        actionbar?.setDisplayHomeAsUpEnabled(false)

        buttonDone.setOnClickListener {
            startActivity(Intent(this@SuccessOrderActivity, MainActivity::class.java))
            setResult(RESULT_OK)
            finish()
        }
    }
}

Android Online Food Delivery Output:

1. Splash Screen:

android kotlin Splash Screen

 

2. List of restaurants:

android kotlin List of restaurants

 

3. Restaurant Menu Items:

Restaurant Menu Items output

Restaurant Menu Items
4. Details form for successful delivery:

successful delivery

5. Order preview:

Order preview

6. Order placed:

android kotlin order successful

Summary

So in this Android Kotlin Online Food Delivery App, we have learned how to create and develop an online food ordering application in Android Studio. This project is highly beneficial for beginners since it familiarizes users with utilizing XML to create user interfaces, switching between activities by clicking a button, using a JSON file to extract data, and displaying the fetched data on the activity. We sincerely hope you enjoyed it, and we are sure you will enjoy implementing it in reality.