Skip to content

Instantly share code, notes, and snippets.

@xArieN9x
Last active December 9, 2025 06:13
Show Gist options
  • Select an option

  • Save xArieN9x/0d4aa4744a95862506bded9bb308aae7 to your computer and use it in GitHub Desktop.

Select an option

Save xArieN9x/0d4aa4744a95862506bded9bb308aae7 to your computer and use it in GitHub Desktop.
CB
app/src/main/java/com/example/allinoneflushapp/MainActivity.kt
package com.example.allinoneflushapp
import android.app.Activity
import android.content.Intent
import android.net.VpnService
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
import java.net.URL
class MainActivity : AppCompatActivity() {
private lateinit var textViewIP: TextView
private lateinit var textViewDNS: TextView
private lateinit var networkIndicator: ImageView
private lateinit var btnDoAllJob: Button
private lateinit var btnStartVpn: Button
private val pandaPackage = "com.logistics.rider.foodpanda"
private val dnsList = listOf("1.1.1.1", "8.8.8.8", "9.9.9.9", "9.9.9.10")
private val vpnPermissionLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// user granted vpn permission; start service
startService(Intent(this, AppMonitorVPNService::class.java))
// tell service to establish with current dns
AppMonitorVPNService.rotateDNS(dnsList)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppGlobals.applicationContext = application
setContentView(R.layout.activity_main)
// KEEP ACCESSIBILITY ALIVE
startService(Intent(this, AnchorService::class.java))
textViewIP = findViewById(R.id.textViewIP)
textViewDNS = findViewById(R.id.textViewDNS)
networkIndicator = findViewById(R.id.networkIndicator)
btnDoAllJob = findViewById(R.id.btnDoAllJob)
btnStartVpn = findViewById(R.id.btnStartVpn)
updateIP()
rotateDNS()
startNetworkMonitor()
btnDoAllJob.setOnClickListener { doAllJobSequence() }
btnStartVpn.setOnClickListener { requestVpnPermission() }
}
private fun requestVpnPermission() {
val intent = VpnService.prepare(this)
if (intent != null) {
vpnPermissionLauncher.launch(intent)
} else {
// already granted
startService(Intent(this, AppMonitorVPNService::class.java))
AppMonitorVPNService.rotateDNS(dnsList)
}
}
private fun updateIP() {
CoroutineScope(Dispatchers.IO).launch {
val ip = try {
URL("https://api.ipify.org").readText().trim()
} catch (e: Exception) { null }
withContext(Dispatchers.Main) {
textViewIP.text = if (ip.isNullOrEmpty()) "Public IP: —" else "Public IP: $ip"
}
}
}
private fun rotateDNS() {
val selectedDNS = dnsList.random()
textViewDNS.text = "DNS: $selectedDNS"
AppMonitorVPNService.rotateDNS(dnsList = listOf(selectedDNS))
}
private fun startNetworkMonitor() {
CoroutineScope(Dispatchers.IO).launch {
while (true) {
val connected = AppMonitorVPNService.isPandaActive()
withContext(Dispatchers.Main) {
networkIndicator.setImageResource(
if (connected) R.drawable.green_circle else R.drawable.red_circle
)
}
delay(1500)
}
}
}
private fun doAllJobSequence() {
// 1. Force stop Panda + clear cache (accessibility)
AccessibilityAutomationService.requestClearAndForceStop(pandaPackage)
// 2. Toggle airplane (after a short delay to allow force-stop)
CoroutineScope(Dispatchers.Main).launch {
delay(3000)
AccessibilityAutomationService.requestToggleAirplane()
// 3. Wait for airplane cycle and network recovery then start/refresh VPN
delay(11000) // 8 sec ON + some buffer
requestVpnPermission()
// 4. After VPN ready, rotate DNS and refresh IP
delay(2000)
rotateDNS()
updateIP()
}
}
}
=========================================================================
app/src/main/java/com/example/allinoneflushapp/AccessibilityAutomationService.kt
package com.example.allinoneflushapp
import android.accessibilityservice.AccessibilityService
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.provider.Settings
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import androidx.annotation.RequiresApi
class AccessibilityAutomationService : AccessibilityService() {
companion object {
private val handler = Handler(Looper.getMainLooper())
private const val AIRPLANE_DELAY = 8000L
private val storageKeys = arrayOf("Storage usage", "Storage usage ", "Storage", "Storage & cache", "App storage")
private val forceStopKeys = arrayOf("Force stop", "Force stop ", "Force Stop", "Force Stop ", "Paksa berhenti", "Paksa Hentikan")
private val confirmOkKeys = arrayOf("OK", "Yes", "Confirm", "Ya", "Force stop ", "Force stop")
private val clearCacheKeys = arrayOf("Clear cache", "Clear cache ", "Clear Cache", "Clear Cache ", "Kosongkan cache")
fun requestClearAndForceStop(packageName: String) {
val ctx = AppGlobals.applicationContext
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
ctx.startActivity(intent)
handler.postDelayed({
val svc = AppGlobals.accessibilityService ?: return@postDelayed
// Click Force Stop in app info
val clicked = svc.findAndClick(*forceStopKeys)
if (clicked) {
// Confirm dialog - choose Force stop on dialog
handler.postDelayed({ svc.findAndClick(*confirmOkKeys) }, 700)
}
// After force stop, go to Storage usage then Clear cache
handler.postDelayed({
svc.findAndClick(*storageKeys)
handler.postDelayed({ svc.findAndClick(*clearCacheKeys) }, 900)
handler.postDelayed({ svc.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK) }, 1500)
}, 1600)
}, 1200)
}
fun requestToggleAirplane() {
val svc = AppGlobals.accessibilityService ?: return
svc.performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS)
handler.postDelayed({
// Try a few localized labels
val clicked = svc.findAndClick("Airplane mode", "Airplane mode ", "Airplane", "Mod Pesawat", "Mod Penerbangan", "Aeroplane mode")
if (!clicked) {
// fallback: try icon desc scanning
svc.findAndClick("Airplane")
}
// wait ON
SystemClock.sleep(AIRPLANE_DELAY)
// toggle OFF
svc.findAndClick("Airplane mode", "Airplane mode ", "Airplane", "Mod Pesawat", "Mod Penerbangan")
svc.performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME)
// Launch Foodpanda selepas 2 saat (bagi masa sistem stabil)
handler.postDelayed({
AppGlobals.accessibilityService?.launchPandaApp()
}, 2000)
}, 700)
}
}
override fun onServiceConnected() {
super.onServiceConnected()
AppGlobals.accessibilityService = this
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {}
override fun onInterrupt() {}
// Robust search + click using text, content description, viewId
fun findAndClick(vararg keys: Array<String>): Boolean {
// not used; kept for compatibility
return false
}
// ===========================================
// Auto Launch Panda App Helper
// ===========================================
fun launchPandaApp() {
try {
val pkg = "com.logistics.rider.foodpanda"
val launch = packageManager.getLaunchIntentForPackage(pkg)
if (launch != null) {
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(launch)
}
} catch (_: Exception) {}
}
fun findAndClick(vararg keys: String, maxRetries: Int = 6, delayMs: Long = 700L): Boolean {
repeat(maxRetries) {
val root = rootInActiveWindow
if (root != null) {
for (k in keys) {
// exact text matches
val nodes = root.findAccessibilityNodeInfosByText(k)
if (!nodes.isNullOrEmpty()) {
for (n in nodes) {
if (n.isClickable) { n.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true }
var p = n.parent
while (p != null) {
if (p.isClickable) { p.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true }
p = p.parent
}
}
}
// content-desc scan
val desc = findNodeByDescription(root, k)
if (desc != null) { desc.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true }
// viewId fallback
val idNode = findNodeByViewId(root, k)
if (idNode != null) {
if (idNode.isClickable) { idNode.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true }
var p = idNode.parent
while (p != null) {
if (p.isClickable) { p.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true }
p = p.parent
}
}
}
// try scroll to reveal hidden buttons
root.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)
}
Thread.sleep(delayMs)
}
return false
}
private fun findNodeByDescription(root: AccessibilityNodeInfo, text: String): AccessibilityNodeInfo? {
val stack = ArrayDeque<AccessibilityNodeInfo>()
stack.add(root)
while (stack.isNotEmpty()) {
val n = stack.removeFirst()
try {
val cd = n.contentDescription
if (cd != null && cd.toString().contains(text, true)) return n
} catch (_: Exception) {}
for (i in 0 until n.childCount) n.getChild(i)?.let { stack.add(it) }
}
return null
}
private fun findNodeByViewId(root: AccessibilityNodeInfo, idPart: String): AccessibilityNodeInfo? {
val stack = ArrayDeque<AccessibilityNodeInfo>()
stack.add(root)
while (stack.isNotEmpty()) {
val n = stack.removeFirst()
try {
val vid = n.viewIdResourceName
if (vid != null && vid.contains(idPart, true)) return n
} catch (_: Exception) {}
for (i in 0 until n.childCount) n.getChild(i)?.let { stack.add(it) }
}
return null
}
}
=========================================================================
app/src/main/java/com/example/allinoneflushapp/AppMonitorVPNService.kt
package com.example.allinoneflushapp
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.net.VpnService
import android.os.Build
import android.os.ParcelFileDescriptor
import androidx.core.app.NotificationCompat
import java.io.FileInputStream
class AppMonitorVPNService : VpnService() {
companion object {
private var pandaActive = false
private var dnsIndex = 0
private var instance: AppMonitorVPNService? = null
fun isPandaActive() = pandaActive
fun rotateDNS(dnsList: List<String>) {
if (instance == null) return
dnsIndex = (dnsIndex + 1) % dnsList.size
val nextDNS = dnsList[dnsIndex]
instance?.establishVPN(nextDNS)
}
}
private var vpnInterface: ParcelFileDescriptor? = null
private val CHANNEL_ID = "panda_monitor_channel"
private val NOTIF_ID = 1001
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
instance = this
createNotificationChannel()
startForeground(NOTIF_ID, createNotification("Panda Monitor running", connected = false))
// initial establish with default dns
establishVPN("8.8.8.8")
return START_STICKY
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val nm = getSystemService(NotificationManager::class.java)
val channel = NotificationChannel(CHANNEL_ID, "Panda Monitor", NotificationManager.IMPORTANCE_LOW)
nm?.createNotificationChannel(channel)
}
}
private fun createNotification(text: String, connected: Boolean): Notification {
val pi = PendingIntent.getActivity(
this, 0,
Intent(this, MainActivity::class.java),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
)
// use safe built-in icons instead of removed stat_sys_vpn
val smallIcon = if (connected) android.R.drawable.presence_online else android.R.drawable.presence_busy
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Panda Monitor")
.setContentText(text)
.setSmallIcon(smallIcon)
.setContentIntent(pi)
.setOngoing(true)
.build()
}
fun establishVPN(dns: String) {
try {
vpnInterface?.close()
} catch (_: Exception) {}
val builder = Builder()
builder.setSession("PandaMonitor")
.addAddress("10.0.0.2", 32)
.addDnsServer(dns)
.addRoute("1.1.1.1", 32)
.addRoute("0.0.0.0", 0)
try {
builder.addAllowedApplication("com.logistics.rider.foodpanda")
} catch (_: Exception) {}
vpnInterface = try {
builder.establish()
} catch (e: Exception) {
null
}
try {
startForeground(NOTIF_ID, createNotification("Panda Monitor (DNS: $dns)", connected = vpnInterface != null))
} catch (_: Exception) {}
// start monitoring
monitorTraffic()
}
private fun monitorTraffic() {
Thread {
while (true) {
try {
val fd = vpnInterface?.fileDescriptor
if (fd == null) {
pandaActive = false
Thread.sleep(1000)
continue
}
val input = FileInputStream(fd)
val available = try { input.available() } catch (_: Exception) { 0 }
pandaActive = available > 0
} catch (e: Exception) {
pandaActive = false
}
try { Thread.sleep(1000) } catch (_: Exception) {}
}
}.start()
}
override fun onDestroy() {
try { vpnInterface?.close() } catch (_: Exception) {}
pandaActive = false
instance = null
super.onDestroy()
}
}
=========================================================================
app/src/main/java/com/example/allinoneflushapp/AnchorService.kt
package com.example.allinoneflushapp
import android.app.Service
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.os.IBinder
class AnchorService : Service() {
override fun onCreate() {
super.onCreate()
val channelId = "cb_anchor_channel"
val nm = getSystemService(NotificationManager::class.java)
val channel = NotificationChannel(
channelId,
"CedokBooster Anchor",
NotificationManager.IMPORTANCE_LOW
)
nm.createNotificationChannel(channel)
val notif = Notification.Builder(this, channelId)
.setContentTitle("Cedok Booster Active")
.setContentText("Stabilizing accessibility service…")
.setSmallIcon(android.R.drawable.stat_notify_sync)
.setOngoing(true)
.build()
// KEEP ALIVE
startForeground(77, notif)
}
override fun onStartCommand(i: Intent?, f: Int, s: Int): Int {
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? = null
}
=========================================================================
codemagic.yaml
workflows:
android-release:
name: Android Release Workflow
max_build_duration: 60
environment:
java: 17
scripts:
- name: Build Debug APK using Gradle CLI
script: |
# Guna gradle CLI terus (sedia ada di Codemagic)
gradle clean assembleDebug
- name: Verify APK
script: |
ls -la app/build/outputs/apk/debug/
artifacts:
- app/build/outputs/**/*.apk
=========================================================================
app/src/main/res/xml/accessibility_service_config.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_service_description"
android:packageNames="com.android.settings,com.android.systemui,com.coloros.safecenter,com.coloros.notificationmanager"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeViewClicked"
android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestTouchExplorationMode"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="50"
android:canRetrieveWindowContent="true"
android:settingsActivity="com.example.allinoneflushapp.MainActivity" />
=========================================================================
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Internet + Network -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Accessibility priority -->
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<!-- Allow reading package info (helps find nodes in settings) -->
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<!-- Usage stats improves stability navigating Settings -->
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<!-- Foreground service for VPN -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<!-- For overlay popups (some devices require this) -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- Optional: log scan for debugging -->
<uses-permission android:name="android.permission.READ_LOGS" />
<application
android:allowBackup="true"
android:theme="@style/Theme.AppCompat.Light"
android:usesCleartextTraffic="false"
android:supportsRtl="true">
<!-- Main UI -->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- VPN service -->
<service
android:name=".AppMonitorVPNService"
android:permission="android.permission.BIND_VPN_SERVICE"
android:exported="true"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="vpn_tunnel"/>
</service>
<!-- Accessibility automation -->
<service
android:name=".AccessibilityAutomationService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true"
android:label="CB Accessibility Engine">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config"/>
</service>
<!-- AnchorService -->
<service
android:name=".AnchorService"
android:exported="false"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="keep_alive"/>
</service>
</application>
</manifest>
=========================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment