Skip to content

Commit c158486

Browse files
committed
init
0 parents  commit c158486

42 files changed

Lines changed: 2989 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Gradle
2+
.gradle/
3+
build/
4+
**/build/
5+
6+
# Android
7+
local.properties
8+
*.apk
9+
*.aab
10+
*jks
11+
*idsig
12+
captures/
13+
14+
# IDE
15+
.idea/
16+
*.iml
17+
18+
# OS
19+
.DS_Store
20+
Thumbs.db

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 ItsAzni
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Notification Forwarder (Android)
2+
3+
Android app to listen for incoming notifications and forward them to a configurable webhook API.
4+
5+
## Features
6+
7+
- Notification capture using `NotificationListenerService`
8+
- Webhook forwarding with configurable URL, auth mode, and custom headers
9+
- Queue system with Room (durable local storage)
10+
- Retry system with WorkManager (network constraints + backoff)
11+
- Background support
12+
- Auto queue scheduling after reboot (`BOOT_COMPLETED`)
13+
14+
## Background Reliability Setup
15+
16+
1. Open app -> **Home**.
17+
2. Tap **Open Access Settings** and enable Notification Access.
18+
3. Tap **Open Battery Settings** and set app to no restriction if available.
19+
4. On some OEM ROMs (MIUI/ColorOS/Funtouch), enable Auto Start for the app.
20+
21+
## Build
22+
23+
```bash
24+
./gradlew assembleDebug
25+
```
26+
27+
## Local Webhook API (`webhook/`)
28+
29+
This repository includes a Node.js webhook receiver in `webhook/` for local testing.
30+
31+
### Setup
32+
33+
```bash
34+
cd webhook
35+
npm install
36+
cp .env.example .env
37+
```
38+
39+
### Run
40+
41+
```bash
42+
npm run start
43+
```
44+
45+
Default endpoint:
46+
47+
- `POST /webhook`
48+
49+
Health check:
50+
51+
- `GET /health`
52+
53+
Environment config (`webhook/.env`):
54+
55+
- `HOST`
56+
- `PORT`
57+
- `WEBHOOK_PATH`
58+
- `WEBHOOK_BEARER_TOKEN`
59+
- `WEBHOOK_LOG_FILE`
60+
- `JSON_LIMIT`
61+
62+
## Screenshots
63+
64+
### Home & Webhook Page
65+
66+
<img src="screenshots/home.jpg" alt="Home" width="240" />
67+
<img src="screenshots/webhook.jpg" alt="Webhook" width="240" />
68+
69+
### Filter & Queue Page
70+
71+
<img src="screenshots/filter.jpg" alt="Filter" width="240" />
72+
<img src="screenshots/queue.jpg" alt="Queue" width="240" />
73+
74+
## License
75+
76+
This project is licensed under the MIT License.
77+
See [LICENSE](LICENSE) for details.

app/build.gradle.kts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
plugins {
2+
id("com.android.application")
3+
id("org.jetbrains.kotlin.android")
4+
id("com.google.devtools.ksp")
5+
}
6+
7+
android {
8+
namespace = "com.itsazni.notificationforwarder"
9+
compileSdk = 36
10+
11+
defaultConfig {
12+
applicationId = "com.itsazni.notificationforwarder"
13+
minSdk = 26
14+
targetSdk = 36
15+
versionCode = 1
16+
versionName = "1.0"
17+
18+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
19+
}
20+
21+
buildTypes {
22+
release {
23+
isMinifyEnabled = false
24+
proguardFiles(
25+
getDefaultProguardFile("proguard-android-optimize.txt"),
26+
"proguard-rules.pro"
27+
)
28+
}
29+
}
30+
31+
compileOptions {
32+
sourceCompatibility = JavaVersion.VERSION_17
33+
targetCompatibility = JavaVersion.VERSION_17
34+
}
35+
36+
kotlinOptions {
37+
jvmTarget = "17"
38+
}
39+
40+
buildFeatures {
41+
compose = true
42+
}
43+
44+
composeOptions {
45+
kotlinCompilerExtensionVersion = "1.5.14"
46+
}
47+
48+
packaging {
49+
resources {
50+
excludes += "/META-INF/{AL2.0,LGPL2.1}"
51+
}
52+
}
53+
}
54+
55+
dependencies {
56+
val composeBom = platform("androidx.compose:compose-bom:2024.09.00")
57+
58+
implementation("androidx.core:core-ktx:1.13.1")
59+
implementation("androidx.activity:activity-compose:1.9.2")
60+
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.5")
61+
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.5")
62+
implementation("com.google.android.material:material:1.12.0")
63+
implementation("androidx.compose.material3:material3")
64+
implementation("androidx.compose.material:material-icons-extended")
65+
implementation("androidx.compose.ui:ui")
66+
implementation("androidx.compose.ui:ui-tooling-preview")
67+
implementation(composeBom)
68+
debugImplementation("androidx.compose.ui:ui-tooling")
69+
70+
implementation("androidx.work:work-runtime-ktx:2.9.1")
71+
72+
implementation("androidx.room:room-runtime:2.6.1")
73+
implementation("androidx.room:room-ktx:2.6.1")
74+
ksp("androidx.room:room-compiler:2.6.1")
75+
76+
implementation("com.squareup.okhttp3:okhttp:4.12.0")
77+
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
78+
implementation("com.google.code.gson:gson:2.11.0")
79+
}

app/proguard-rules.pro

Whitespace-only changes.

app/src/main/AndroidManifest.xml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<uses-permission android:name="android.permission.INTERNET" />
5+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
6+
7+
<application
8+
android:name=".NotificationForwarderApp"
9+
android:allowBackup="true"
10+
android:icon="@mipmap/ic_launcher"
11+
android:label="Notification Forwarder"
12+
android:networkSecurityConfig="@xml/network_security_config"
13+
android:roundIcon="@mipmap/ic_launcher_round"
14+
android:supportsRtl="true"
15+
android:theme="@style/Theme.NotificationForwarder">
16+
17+
<activity
18+
android:name=".MainActivity"
19+
android:exported="true">
20+
<intent-filter>
21+
<action android:name="android.intent.action.MAIN" />
22+
23+
<category android:name="android.intent.category.LAUNCHER" />
24+
</intent-filter>
25+
</activity>
26+
27+
<service
28+
android:name=".service.AppNotificationListenerService"
29+
android:exported="true"
30+
android:label="Notification Forwarder"
31+
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
32+
<intent-filter>
33+
<action android:name="android.service.notification.NotificationListenerService" />
34+
</intent-filter>
35+
</service>
36+
37+
<receiver
38+
android:name=".receiver.BootCompletedReceiver"
39+
android:enabled="true"
40+
android:exported="true">
41+
<intent-filter>
42+
<action android:name="android.intent.action.BOOT_COMPLETED" />
43+
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
44+
</intent-filter>
45+
</receiver>
46+
47+
</application>
48+
49+
</manifest>

0 commit comments

Comments
 (0)