Android Apps

How to Make a Dating App: Free Android Code and What a Real App Needs

Build the core of a dating app with the whole code in MainActivity: profile cards, like and skip, and a match. Then what a real dating app needs (accounts, photos, chat, video calls, safety), the Google Play rules for dating apps, and a ready video dating app.

A dating app showing a profile card with like and skip buttons and a match screen

A dating app looks complicated, but its heart is simple: show a person, let the user like or skip, and when two people like each other, it is a match. Everything else (accounts, photos, chat, calls, safety) is built around that loop.

This guide builds that core with the whole code in MainActivity, then explains what a real dating app needs around it, the Google Play rules that dating apps are checked against, and a ready video dating app you can start from.

The core: the whole code in MainActivity

  1. In Android Studio choose New Project → Empty Activity, language Kotlin.
  2. Replace everything in MainActivity.kt with the code below. No permissions are needed for this first version.
  3. Run it, then like or skip each profile. Two of the sample profiles like you back, and those become matches.
package com.example.dating   // keep the package line Android Studio made for you

import android.app.AlertDialog
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.view.Gravity
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

data class Profile(val name: String, val age: Int, val city: String, val bio: String, val likesYou: Boolean)

class MainActivity : ComponentActivity() {

    // Sample profiles. A real app loads them from your server.
    private val profiles = listOf(
        Profile("Ayesha", 24, "Lahore", "Coffee, books and long drives.", likesYou = true),
        Profile("Sara", 26, "Karachi", "Designer. Loves the sea and street food.", likesYou = false),
        Profile("Hina", 23, "Islamabad", "Hiking on weekends, coding on weekdays.", likesYou = true),
        Profile("Zara", 27, "Dubai", "Travel, photography and good music.", likesYou = false),
    )
    private var current = 0
    private val matches = mutableListOf<String>()

    private lateinit var photo: TextView
    private lateinit var title: TextView
    private lateinit var bio: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        photo = TextView(this).apply {
            textSize = 72f
            gravity = Gravity.CENTER
            setTextColor(Color.WHITE)
            background = GradientDrawable().apply { cornerRadius = 48f; setColor(Color.rgb(236, 72, 153)) }
            height = 700
        }
        title = TextView(this).apply { textSize = 26f; setPadding(0, 32, 0, 8) }
        bio = TextView(this).apply { textSize = 17f }
        val skip = Button(this).apply { text = "Skip" }
        val like = Button(this).apply { text = "Like" }
        val buttons = LinearLayout(this).apply {
            gravity = Gravity.CENTER
            addView(skip)
            addView(like)
        }
        val screen = LinearLayout(this).apply {
            orientation = LinearLayout.VERTICAL
            addView(photo)
            addView(title)
            addView(bio)
            addView(buttons)
        }
        setContentView(screen)

        // Keep the card clear of the status bar and the navigation bar (Android 15 and newer)
        ViewCompat.setOnApplyWindowInsetsListener(screen) { view, insets ->
            val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            view.setPadding(40, bars.top + 40, 40, bars.bottom + 40)
            insets
        }

        skip.setOnClickListener { next() }
        like.setOnClickListener {
            val profile = profiles.getOrNull(current) ?: return@setOnClickListener
            if (profile.likesYou) {   // both liked each other
                matches += profile.name
                AlertDialog.Builder(this)
                    .setTitle("It's a match!")
                    .setMessage("You and ${profile.name} like each other. Say hello!")
                    .setPositiveButton("OK", null)
                    .show()
            }
            next()
        }
        show()
    }

    private fun next() {
        current++
        show()
    }

    private fun show() {
        val profile = profiles.getOrNull(current)
        if (profile == null) {
            photo.text = "\u2764"
            title.text = "No more profiles"
            bio.text = if (matches.isEmpty()) "No matches yet." else "Your matches: " + matches.joinToString()
            return
        }
        photo.text = profile.name.first().toString()
        title.text = "${profile.name}, ${profile.age} \u00b7 ${profile.city}"
        bio.text = profile.bio
    }
}
PartWhat it does
data class ProfileOne person: name, age, city, a short bio, and (only in this demo) whether they like you
The cardA coloured box with the first letter, then the name, age and city, and the bio. A real app shows photos here.
like and skipMove to the next profile; a like on someone who likes you back opens “It's a match!”
matchesThe list of matches, shown when there are no more profiles

In a real app the likesYou field is never on the phone: likes are saved on your server, and the server decides when two likes make a match. That way nobody can see who liked them before they like back.

What a real dating app needs

FeatureHow it is usually built
Accounts and an 18+ checkSign-up on your server, with the birth date checked and the account deletable
Profiles with photosUploads resized on the server, and checked before others see them
DiscoveryYour server picks whom to show, for example people who are online or nearby
Likes and matchesStored on the server; a match is two likes in both directions
ChatA chat server such as ejabberd (XMPP), with online status and typing indicators
Video callsWebRTC with a TURN server, so calls connect on mobile data too
NotificationsNew matches, messages and incoming calls
SafetyBlock, report, a profanity filter and someone who reviews reports

The chat and call parts are covered in how to create a chat app, how video calling apps work and installing ejabberd and a TURN server.

Google Play rules for dating apps

  • User-generated content: because users post profiles, photos and messages, the app needs terms users accept, a way to report people and content, a way to block, and moderation that acts on reports.
  • No sexual content in the app, the store listing, the icon or the screenshots.
  • Adults only: set the target audience to 18+ and check the age at sign-up.
  • Account deletion: apps that let users create an account must let them delete it inside the app, and through a web page whose link you give in the Data safety form.
  • Honest profiles: no fake profiles that pretend to be real people to keep users chatting.

Common problems

ProblemCause and fix
Rejected for user-generated contentNo report or block option, or no terms. Add both to profiles and chats, and a terms screen at sign-up.
Rejected for account deletionNo delete option in the app, or no web link for it in the Data safety form. Add both.
Users leave because nobody is onlineNew dating apps feel empty. Start in one city or community, and show who is online first.
Video calls fail on mobile dataNo TURN server. Add coturn.

The full version: a ready video dating app

Our video dating app source code is a Kotlin and Jetpack Compose app that runs on your own ejabberd (XMPP) and coturn (TURN) servers, so you pay no per-minute call fees:

  • Sign-up and log-in on your own server, and a list of people who are online
  • One-to-one chat with a typing indicator and unread counts
  • Voice and video calls (WebRTC) with an incoming-call screen and notification, and call history with missed calls
  • Block and report (reports go to a moderator account) and a profanity filter
  • Profile with photo, edit profile, an 18+ age check and delete account
  • Light and dark design, and AdMob ads with Google's GDPR message

It comes with a ready ejabberd and TURN server folder and a step-by-step server guide.

Where to go next

Questions people ask

How do I make a dating app in Android Studio?
Start with the core loop: show a profile, let the user like or skip, and create a match when two people like each other. The MainActivity in this guide does that with sample profiles. A real app then adds accounts, photos, a server for likes and matches, chat, calls and safety features.
How does matching work in a dating app?
Each like is saved on your server. When the server sees that two people have liked each other, it creates a match and notifies both. The likes are never sent to the phones, so nobody can see who liked them first.
What server does a dating app need?
A server for accounts, profiles, likes and matches, a chat server such as ejabberd for messages, and a TURN server such as coturn for video calls.
Is a dating app allowed on Google Play?
Yes, if it follows the rules: report and block options and moderation for user content, no sexual content, an 18+ audience with an age check, account deletion in the app and through a web link, and no fake profiles.
Do dating apps need account deletion?
Yes. Google Play requires apps that let users create an account to let them delete it inside the app and through a web page, whose link you give in the Data safety form.
How do dating apps make money?
With ads (interstitials between screens and native ads in lists) and with paid features such as extra likes or seeing who liked you. Our chat app earns about $300 a month from 300 to 400 daily users with interstitials only.
How do I add video calls to a dating app?
Use WebRTC for the video, your chat server for the call setup, and a TURN server so calls connect on mobile data. Our video calling guide explains each part.
Is there ready source code for a video dating app?
Yes. Our video dating app source code has sign-up on your own server, online users, chat, voice and video calls, call history, block and report, a profanity filter, an 18+ check, account deletion and AdMob, with a ready ejabberd and TURN server folder.

Written by Habib Baloch

I build Android apps, websites and Ubuntu servers, and write down exactly how I did it.

Ask me about this guide →