I created this app for Client, who needed an app that would copy only the mobile number from a text. I created it for him in just five hours and he was very happy. I created it with Jetpack Compose and Kotlin. I am providing my Jetpack Compose code below. If you find any errors in it, please let me know. Thank you very much.
package com.example.coppier
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.android.gms.ads.*
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
class MainActivity : ComponentActivity() {
private var mInterstitialAd: InterstitialAd? = null
var copyCount = 0 // ✅ count copied numbers
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ✅ Initialize Ads
MobileAds.initialize(this) {}
// ✅ Load first ad on app open
loadInterstitialAd()
setContent {
CoppierApp()
}
// ✅ Show ad once at app open
showInterstitialAd()
}
fun loadInterstitialAd() {
val adRequest = AdRequest.Builder().build()
InterstitialAd.load(
this,
"", // Test ID (replace with real later)
adRequest,
object : InterstitialAdLoadCallback() {
override fun onAdLoaded(interstitialAd: InterstitialAd) {
mInterstitialAd = interstitialAd
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
mInterstitialAd = null
}
})
}
fun showInterstitialAd() {
mInterstitialAd?.show(this)
mInterstitialAd = null
loadInterstitialAd() // reload after show
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CoppierApp() {
val context = LocalContext.current
val activity = (context as? MainActivity)
var inputText by remember { mutableStateOf("") }
var numbers by remember { mutableStateOf<List<String>>(emptyList()) }
var currentIndex by remember { mutableStateOf(0) }
var finished by remember { mutableStateOf(false) }
LaunchedEffect(inputText) {
numbers = parseNumbers(inputText)
currentIndex = 0
finished = false
}
Scaffold(
topBar = {
TopAppBar(
title = { Text("COPPIER", color = Color.White, fontWeight = FontWeight.Bold) },
colors = TopAppBarDefaults.topAppBarColors(containerColor = Color(0xFF009688))
)
}
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(listOf(Color(0xFF80DEEA), Color(0xFF004D40)))
)
.padding(padding)
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Card(
modifier = Modifier.weight(1f).padding(end = 8.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
shape = RoundedCornerShape(12.dp),
elevation = CardDefaults.elevatedCardElevation(6.dp)
) {
Box(modifier = Modifier.padding(12.dp)) {
Text("This App is created by Nasir Ali",
fontSize = 14.sp,
color = Color(0xFF00796B)
)
}
}
Button(
onClick = { dialNumber(context, "") },
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4CAF50))
) {
Text("Contact Me", fontWeight = FontWeight.Bold)
}
}
OutlinedTextField(
value = inputText,
onValueChange = { inputText = it },
label = { Text("Paste your numbers here (one per line)") },
modifier = Modifier
.fillMaxWidth()
.height(160.dp),
shape = RoundedCornerShape(12.dp)
)
if (numbers.isNotEmpty()) {
val number = numbers.getOrNull(currentIndex) ?: ""
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(containerColor = Color.White),
shape = RoundedCornerShape(16.dp),
elevation = CardDefaults.elevatedCardElevation(8.dp)
) {
Column(
modifier = Modifier.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Current Number", color = Color.Gray)
Text(number,
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
color = Color(0xFF00796B)
)
Text("Index: ${currentIndex + 1} / ${numbers.size}", color = Color.Gray)
}
}
Button(
onClick = {
if (!finished) {
copyToClipboard(context, number)
// ✅ Increase counter
activity?.copyCount = activity?.copyCount?.plus(1) ?: 0
// ✅ Show Interstitial after every 100 copies
if ((activity?.copyCount ?: 0) >= 100) {
activity?.copyCount = 0
activity?.showInterstitialAd()
}
if (currentIndex < numbers.lastIndex) {
currentIndex++
} else {
finished = true
Toast.makeText(context, "All numbers copied", Toast.LENGTH_SHORT).show()
// ✅ Show ad when finished
activity?.showInterstitialAd()
}
}
},
enabled = !finished,
colors = ButtonDefaults.buttonColors(
containerColor = if (!finished) Color(0xFFFF5722) else Color.Gray
),
shape = RoundedCornerShape(50.dp),
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
) {
Text(if (!finished) "Copy & Next" else "Finished")
}
}
}
}
}
// ✅ Only copy mobile numbers like 03xxxxxxxxx
fun copyToClipboard(context: Context, text: String) {
val regex = Regex("\b03\d{9}\b")
val match = regex.find(text)
val numberOnly = match?.value ?: ""
if (numberOnly.isNotEmpty()) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("copied_number", numberOnly))
Toast.makeText(context, "Copied: $numberOnly", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "No valid number found", Toast.LENGTH_SHORT).show()
}
}
fun parseNumbers(text: String): List =
text.split("\n").map { it.trim() }.filter { it.isNotEmpty() }
fun dialNumber(context: Context, phone: String) {
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:$phone"))
context.startActivity(intent)
}