Push
FMD uses UnifiedPush to receive push notifications from FMD Server. Without a working UnifiedPush setup, you won't receive commands from FMD Server. Hence you need to have a distributor app installed on your phone. FMD Server will act as the application server, and e.g. ntfy Server will act as the push server.
The recommended distributor apps are:
After installing a push distributor app, return to the FMD Server settings screen in FMD Android. This should trigger FMD to retry registering itself with the distributor app.
No sensitive data is sent in push notifications, they are only used to wake up FMD.
Using a private ntfy server
First, note that FMD Server and ntfy are mutually exclusive. I.e., you can self-host FMD Server while using the hosted ntfy.sh. If you do host your own ntfy instance, make sure to:
- Configure your ntfy server URL in the ntfy app under Settings -> Default Server
- Enable anonymous write access to
up*
topics: https://docs.ntfy.sh/config/#example-unifiedpush
How it should look like
ntfy Overview | ntfy Topic Details | FMD Android settings |
---|---|---|
![]() | ![]() | ![]() |
You can delete this topic if you want the FMD app to re-register itself. | This is the topic URL that FMD Server will try and access. | Return to this page, and FMD will automatically re-register itself with ntfy with a new topic. |
Debugging ntfy+FMD issues
Step 1: Try sending a push to your phone with fmd ring
First, bring the FMD app into the background. Just return to the Android home screen.
Then try ringing your phone from the web interface:
If everything is set up correctly, your phone should start ringing.
fmd ring
requires that you have granted the "Overlay" permission (also called "Display Over Other Apps").
Otherwise ringing won't work (independent of push)!
This is a known to be non-ideal and is tracked in https://gitlab.com/fmd-foss/fmd-android/-/issues/145.
Step 2: Did the ntfy app receive a push?
For this step, you need a working adb setup. XDA has a guide for how to set it up.
Now run adb logcat | grep --context 50 Ntfy
.
You should see something like this:
10-03 15:42:51.267 23995 D NtfySubscriberService: [https://ntfy.sh/up0UUUUexample] Received notification: Notification(id=lN0ADDmW7OkA, subscriptionId=68793504, timestamp=1696340571, title=, message={
10-03 15:42:51.267 23995 D NtfySubscriberService: "message": "fmd app wakeup",
10-03 15:42:51.267 23995 D NtfySubscriberService: "priority": 5
10-03 15:42:51.267 23995 D NtfySubscriberService: }, encoding=, notificationId=-975333244, priority=3, tags=, click=, icon=null, actions=null, attachment=null, deleted=false)
10-03 15:42:51.287 14374 D NtfySubscriberService: [https://ntfy.sh/up0UUUUexample] Dispatching notification Notification(id=lN0ADDmW7OkA, subscriptionId=68793504, timestamp=1696340571, title=, message={
10-03 15:42:51.287 14374 D NtfySubscriberService: "message": "fmd app wakeup",
10-03 15:42:51.287 14374 D NtfySubscriberService: "priority": 5
10-03 15:42:51.287 14374 D NtfySubscriberService: }, encoding=, notificationId=-975333244, priority=3, tags=, click=, icon=null, actions=null, attachment=null, deleted=false)
10-03 15:42:51.287 14374 D NtfyNotifDispatch: Dispatching Notification(id=lN0ADDmW7OkA, subscriptionId=68793504, timestamp=1696340571, title=, message={
10-03 15:42:51.287 14374 D NtfyNotifDispatch: "message": "fmd app wakeup",
10-03 15:42:51.287 14374 D NtfyNotifDispatch: "priority": 5
10-03 15:42:51.287 14374 D NtfyNotifDispatch: }, encoding=, notificationId=-975333244, priority=3, tags=, click=, icon=null, actions=null, attachment=null, deleted=false) for subscription Subscription(id=68793504, baseUrl=https://ntfy.sh, topic=up0UUUUexample, instant=true, mutedUntil=0, minPriority=0, autoDelete=-1, insistent=-1, lastNotificationId=ySoszjv9NmkD, icon=null, upAppId=de.nulide.findmydevice, upConnectorToken=dummy, displayName=null, dedicatedChannels=false, totalCount=2, newCount=2, lastActive=1696340527, state=CONNECTED)
10-03 15:42:51.287 14374 D NtfyUpDistributor: Sending MESSAGE to de.nulide.findmydevice (token=dummy): 51 bytes
10-03 15:42:51.295 24066 I PushReceiver: Received push message
10-03 15:42:51.302 3126 W JobScheduler: Job didn't exist in JobStore: 922a1e2 #u0a295/109 de.nulide.findmydevice/.services.FMDServerCommandDownloadService
10-03 15:42:51.381 24066 I FMDServerCommandDownloadService: Received remote command 'ring'
10-03 15:42:51.421 3057 I ActivityTaskManager: START u0 {flg=0x10000000 cmp=de.nulide.findmydevice/.ui.RingerActivity (has extras)} from uid 10295
10-03 15:42:51.421 3057 W ActivityTaskManager: Background activity start for de.nulide.findmydevice allowed because SYSTEM_ALERT_WINDOW permission is granted.
10-03 15:42:51.425 3057 V SplashScreenExceptionList: SplashScreen checking exception for package de.nulide.findmydevice (target sdk:33) -> false
The first part (the log lines with Ntfy*
) are logged by the ntfy.
If these are missing, then the ntfy app did not receive a push from your ntfy server.
Recall that the ntfy app (the UnifiedPush distributor) forwards the push to the FMD app. This is the second part of the log above. You can see how FMD receives the push and starts the RingerActivity from the background.
Step 3: Check that push is working with ntfy.sh
Make sure to do steps 1+2 with the official ntfy.sh server.
If they fail, then something is wrong with the ntfy app or your FMD server.
If it works for ntfy.sh but not your self-hosted ntfy server, then read on.
Step 4: Is the ntfy topic writable?
Copy the UnifiedPush topic URL from the ntfy app, and try manually accessing it:
$ curl -d "test" https://push.example.com/upR6Ufp5tyxEsP
{"id":"BIcaP7vAUaJD","time":1697182419,"expires":1697355219,"event":"message","topic":"upR6Ufp5tyxEsP","message":"test"}
This simulates what FMD Server will do. If this curl
command fails, e.g. with:
$ curl -d "test" https://push.example.com/upR6Ufp5tyxEsP
{"code":40301,"http":403,"error":"forbidden","link":"https://ntfy.sh/docs/publish/#authentication"}
then you should read the ntfy docs: https://docs.ntfy.sh/config/#example-unifiedpush
You can either make all topic URLs writable (up*
) or only your specific one (upR6Ufp5tyxEsP
).
If you only make your specific one writable, then if you delete that topic in the ntfy app and a new one is generated, remember to allowlist it again!
Step 5: It still fails
Give it a break, sleep over it, and try again debugging tomorrow. If it still fails, search the known issues, and maybe open a new one and ask for help.