Notification Listener
Postingan ini membahas Notification Listener, aplikasi Android yang menangkap notifikasi sistem dan meneruskannya sebagai payload JSON ke endpoint HTTP. Anda akan mempelajari pengenalan fitur, cara deploy backend (Express lokal atau Cloudflare Workers), serta langkah cara menggunakan aplikasinya.
Daftar Isi
- Pengenalan Aplikasi
- Deploy Backend
- Setup Aplikasi Android
- Cara Menggunakan
- Uji dan Verifikasi
- Tips Produksi
Pengenalan Aplikasi

- Tangkap Notifikasi: memantau notifikasi dari aplikasi yang dipilih atau semua aplikasi.
- Forward ke Webhook: kirim JSON via
POSTke endpoint/webhook. - Reliabilitas: antrean + retry saat offline menggunakan WorkManager.
- Keamanan: dukungan header
X-API-Key, penyimpanan terenkripsi untuk API key. - Deteksi Rupiah: field
amountDetecteduntuk nominal yang terdeteksi. - Log: tampilan log ringkas di aplikasi untuk debug cepat.
Deploy Backend
A. Express (Lokal/Server Anda)
Backend bawaan berada di folder backend/. Cocok untuk pengujian lokal atau server sendiri.
cd backend
npm install
# Konfigurasi environment
cat > .env << 'EOF'
PORT=3000
API_KEY=your-secret-api-key
EOF
# Jalankan server
npm run dev # mode development
# atau
npm start # mode production
# Endpoint:
# http://localhost:3000/health
# http://localhost:3000/webhookB. Cloudflare Workers (Tanpa Server)

Alternatif tanpa server dengan latensi rendah. Butuh akun Cloudflare dan Wrangler CLI (npm i -g wrangler).
1) Prasyarat
- Akun Cloudflare aktif.
- Node.js LTS terpasang.
- Wrangler CLI:
npm i -g wranglerkemudianwrangler login.
2) Siapkan Proyek Worker
# Inisialisasi proyek Worker (ES Modules)
mkdir notification-worker && cd notification-worker
wrangler init --yes --type=javascript
mkdir -p src && touch src/worker.jsexport default {
async fetch(request, env) {
const url = new URL(request.url);
const cors = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type, X-API-Key",
"Access-Control-Allow-Methods": "POST, OPTIONS"
};
if (request.method === "OPTIONS") return new Response(null, { headers: cors });
if (request.method === "POST" && url.pathname === "/webhook") {
const apiKey = request.headers.get("X-API-Key");
if (!apiKey || apiKey !== env.API_KEY) {
return new Response(JSON.stringify({ ok:false, error:"Unauthorized" }), { status:401, headers:{ "Content-Type":"application/json", ...cors }});
}
let body;
try { body = await request.json(); }
catch { return new Response(JSON.stringify({ ok:false, error:"Invalid JSON" }), { status:400, headers:{ "Content-Type":"application/json", ...cors }}); }
const { deviceId, packageName, text, amountDetected } = body || {};
if (!deviceId || !packageName || !text) {
return new Response(JSON.stringify({ ok:false, error:"Missing fields" }), { status:422, headers:{ "Content-Type":"application/json", ...cors }});
}
console.log("Notif:", packageName, amountDetected);
return new Response(JSON.stringify({ ok:true }), { status:200, headers:{ "Content-Type":"application/json", ...cors }});
}
if (url.pathname === "/") return new Response("Notification Worker OK", { headers: cors });
return new Response("Not Found", { status:404, headers: cors });
}
};3) Konfigurasi wrangler.toml
name = "notification-listener-webhook"
main = "src/worker.js"
compatibility_date = "2024-12-01"
workers_dev = true
[vars]
# Tambahan variabel non-rahasia jika diperlukan
# (Opsional) Custom domain
# routes = [{ pattern = "webhook.domain-anda.com/*", custom_domain = true }]
# (Opsional) Binding D1/KV/Queues
# [[d1_databases]]
# binding = "DB"
# database_name = "notification-listener-db"
# database_id = "<id-d1-anda>"
# [[queues.producers]]
# binding = "NOTIF_QUEUE"
# queue = "notification-queue"
4) Set Secret & Deploy
# Set secret API_KEY yang akan dibaca di env.API_KEY
wrangler secret put API_KEY
# Deploy ke Cloudflare Workers
wrangler deploy
# Lihat URL hasil deploy (workers.dev)
# Contoh: https://notification-listener-webhook.<akun>.workers.dev/webhook
# Pantau log realtime
wrangler tail5) Uji Endpoint
curl -X POST "https://notification-listener-webhook.<akun>.workers.dev/webhook" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-secret-api-key" \
-d '{
"deviceId":"550e8400-e29b-41d4-a716-446655440000",
"packageName":"id.dana",
"text":"Anda menerima Rp 100.000",
"amountDetected":"100000"
}'Catatan produksi: batasi CORS ke domain Anda (ganti * dengan domain), gunakan custom domain + HTTPS bila perlu, dan pertimbangkan D1/KV/Queues untuk penyimpanan/antrian.
6) Setting Database D1 (Lengkap)
Opsional tetapi direkomendasikan jika ingin menyimpan histori notifikasi. Langkah-langkah berikut mencakup pembuatan database, binding di wrangler.toml, inisialisasi schema, verifikasi, dan tips pengembangan lokal.
A) Buat Database & Binding
# Login Cloudflare dan buat D1
wrangler login
wrangler d1 create notification-listener-db
# Salin database_id dari output perintah iniGo to wrangler.toml dan tambahkan binding berikut menggunakan database_id milik Anda:
[[d1_databases]]
binding = "DB"
database_name = "notification-listener-db"
database_id = "<id-d1-anda>"B) Inisialisasi Schema
-- schema.sql (minimal)
CREATE TABLE IF NOT EXISTS notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
package_name TEXT NOT NULL,
text TEXT,
amount_detected TEXT,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT UNIQUE NOT NULL,
last_seen TEXT DEFAULT (datetime('now'))
);# Terapkan schema (pilih salah satu cara)
# 1) Menggunakan file
printf "%s" "CREATE TABLE IF NOT EXISTS notifications (id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT NOT NULL, package_name TEXT NOT NULL, text TEXT, amount_detected TEXT, created_at TEXT DEFAULT (datetime('now')));
CREATE TABLE IF NOT EXISTS devices (id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT UNIQUE NOT NULL, last_seen TEXT DEFAULT (datetime('now')));" > schema.sql
wrangler d1 execute notification-listener-db --file=schema.sql
# 2) Jalankan per perintah
wrangler d1 execute notification-listener-db --command="CREATE TABLE IF NOT EXISTS notifications (id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT NOT NULL, package_name TEXT NOT NULL, text TEXT, amount_detected TEXT, created_at TEXT DEFAULT (datetime('now')));"
wrangler d1 execute notification-listener-db --command="CREATE TABLE IF NOT EXISTS devices (id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT UNIQUE NOT NULL, last_seen TEXT DEFAULT (datetime('now')));"C) Verifikasi & Query Contoh
# Lihat daftar tabel
wrangler d1 execute notification-listener-db --command="SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"
# Ambil 10 notif terakhir
wrangler d1 execute notification-listener-db --command="SELECT id, package_name, amount_detected, created_at FROM notifications ORDER BY id DESC LIMIT 10;"D) Catatan Dev Lokal
- Remote binding: gunakan
wrangler dev --remoteagar Worker lokal memakai D1 cloud Anda. - Migrasi: Anda juga dapat memakai
wrangler d1 migrationsuntuk mengelola perubahan schema secara bertahap.
Setup Aplikasi Android

- Build APK:
./gradlew assembleDebuglalu install:adb install app/build/outputs/apk/debug/app-debug.apk. - Buka aplikasi, aktifkan Akses Notifikasi hingga status “Granted”.
- Isi Endpoint URL:
http://<host>:3000/webhook(Express) atauhttps://<subdomain>.workers.dev/webhook(Workers). - Opsional: isi API Key untuk dikirim sebagai header
X-API-Key. - Opsional: atur Filter Package (mis.
id.dana, com.whatsapp) atau aktifkan “Forward semua aplikasi”. - Simpan pengaturan dan kecualikan dari optimasi baterai agar layanan berjalan stabil.
Cara Menggunakan
- Pastikan backend aktif dan dapat diakses publik.
- Jalankan aplikasi dan gunakan fitur uji kirim atau tunggu notifikasi nyata.
- Periksa log di aplikasi untuk status terkini pengiriman.
- Validasi di backend apakah menerima
200 OKdan payload sesuai.
Uji dan Verifikasi
# Uji ke Express lokal
curl -X POST "http://localhost:3000/webhook" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-secret-api-key" \
-d '{
"deviceId":"550e8400-e29b-41d4-a716-446655440000",
"packageName":"id.dana",
"text":"Anda menerima Rp 100.000",
"amountDetected":"100000"
}'
# Uji ke Cloudflare Workers
curl -X POST "https://notification-listener-webhook.<akun>.workers.dev/webhook" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-secret-api-key" \
-d '{
"deviceId":"550e8400-e29b-41d4-a716-446655440000",
"packageName":"id.dana",
"text":"Anda menerima Rp 100.000",
"amountDetected":"100000"
}'Tips Produksi
- CORS: batasi
Access-Control-Allow-Originke domain Anda. - Custom Domain: gunakan HTTPS di server sendiri atau
routesuntuk Workers. - Reliabilitas: pantau log backend, gunakan antrian/penyimpanan sesuai kebutuhan.
- Performa Perangkat: kecualikan dari optimasi baterai agar layanan foreground stabil.
Repository: github.com/Wimboro/NotificationListener

