package com.vanta.smsgateway import android.Manifest import android.app.role.RoleManager import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.Bundle import android.provider.Telephony import android.widget.* import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class MainActivity : AppCompatActivity() { private lateinit var etUrl: EditText private lateinit var etKey: EditText private lateinit var btnStart: Button private lateinit var btnDefault: Button private lateinit var tvStatus: TextView private lateinit var tvSim: TextView private lateinit var tvDefault: TextView companion object { const val REQ_DEFAULT_SMS = 200 const val REQ_ROLE = 201 } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) etUrl = findViewById(R.id.et_url) etKey = findViewById(R.id.et_key) btnStart = findViewById(R.id.btn_start) btnDefault = findViewById(R.id.btn_default) tvStatus = findViewById(R.id.tv_status) tvSim = findViewById(R.id.tv_sim) tvDefault = findViewById(R.id.tv_default) val prefs = getSharedPreferences(SmsService.PREF_NAME, Context.MODE_PRIVATE) etUrl.setText(prefs.getString(SmsService.PREF_URL, "")) etKey.setText(prefs.getString(SmsService.PREF_KEY, "")) updateUI() btnStart.setOnClickListener { if (SmsService.isRunning) stopGateway() else requestAndStart() } btnDefault.setOnClickListener { if (isDefaultSmsApp()) restoreDefaultSmsApp() else requestDefaultSmsApp() } } override fun onResume() { super.onResume() updateUI() if (hasPhonePerm()) tvSim.text = SubscriptionHelper.describe(this) } private fun updateUI() { // Gateway running state if (SmsService.isRunning) { btnStart.text = "Stop Gateway" tvStatus.text = "● Running" tvStatus.setTextColor(getColor(android.R.color.holo_green_light)) } else { btnStart.text = "Start Gateway" tvStatus.text = "● Stopped" tvStatus.setTextColor(getColor(android.R.color.darker_gray)) } // Default SMS app state if (isDefaultSmsApp()) { btnDefault.text = "Restore Google Messages" tvDefault.text = "✓ SMS Gateway is default SMS app — sends as raw SMS" tvDefault.setTextColor(getColor(android.R.color.holo_green_light)) } else { btnDefault.text = "Set as Default SMS App" tvDefault.text = "⚠ Not default — messages may send as RCS" tvDefault.setTextColor(0xFFD29922.toInt()) } } private fun isDefaultSmsApp(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val rm = getSystemService(RoleManager::class.java) rm.isRoleHeld(RoleManager.ROLE_SMS) } else { Telephony.Sms.getDefaultSmsPackage(this) == packageName } } private fun requestDefaultSmsApp() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val rm = getSystemService(RoleManager::class.java) val intent = rm.createRequestRoleIntent(RoleManager.ROLE_SMS) startActivityForResult(intent, REQ_ROLE) } else { val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT) .putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName) startActivityForResult(intent, REQ_DEFAULT_SMS) } } private fun restoreDefaultSmsApp() { // Open default apps settings so user can switch back to Google Messages val intent = Intent(android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) startActivity(intent) Toast.makeText(this, "Set Google Messages as default SMS app", Toast.LENGTH_LONG).show() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQ_DEFAULT_SMS || requestCode == REQ_ROLE) { updateUI() if (isDefaultSmsApp()) { Toast.makeText(this, "✓ SMS Gateway is now default — raw SMS enabled", Toast.LENGTH_LONG).show() } } } private fun requestAndStart() { val perms = mutableListOf( Manifest.permission.SEND_SMS, Manifest.permission.READ_PHONE_STATE, Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, ) if (Build.VERSION.SDK_INT >= 33) perms += Manifest.permission.POST_NOTIFICATIONS val denied = perms.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED } if (denied.isEmpty()) startGateway() else ActivityCompat.requestPermissions(this, denied.toTypedArray(), 100) } override fun onRequestPermissionsResult(code: Int, perms: Array, results: IntArray) { super.onRequestPermissionsResult(code, perms, results) if (code == 100) { if (results.any { it != PackageManager.PERMISSION_GRANTED }) Toast.makeText(this, "Permissions required to send SMS", Toast.LENGTH_LONG).show() else startGateway() } } private fun startGateway() { val url = etUrl.text.toString().trim() val key = etKey.text.toString().trim() if (url.isEmpty() || key.isEmpty()) { Toast.makeText(this, "Enter server URL and API key", Toast.LENGTH_SHORT).show() return } getSharedPreferences(SmsService.PREF_NAME, Context.MODE_PRIVATE).edit() .putString(SmsService.PREF_URL, url) .putString(SmsService.PREF_KEY, key) .apply() val svc = Intent(this, SmsService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) startForegroundService(svc) else startService(svc) updateUI() tvSim.text = SubscriptionHelper.describe(this) } private fun stopGateway() { startService(Intent(this, SmsService::class.java).apply { action = SmsService.ACTION_STOP }) updateUI() } private fun hasPhonePerm() = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED }