But seriously, write this as a blog post, more people need to know about this, and I'd like to have something "authoritative" to send references to.
Here's how you request a push token:
Intent intent = new Intent("com.google.iid.TOKEN_REQUEST");
intent.setPackage("com.google.android.gms");
intent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE));
intent.putExtra("sender", FCM_SENDER_ID);
intent.putExtra("subtype", FCM_SENDER_ID);
intent.putExtra("scope", "*");
intent.putExtra("kid", "|ID|1|");
context.sendBroadcast(intent);
Here are the two receivers: <receiver android:name=".PushNotificationReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
<receiver android:name=".api.PushSubscriptionManager$RegistrationReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
</intent-filter>
</receiver>
The first one is where you get notifications. The parameters you sent from the server will simply be your intent extras.The second one is where you get push tokens. There will be a "registration_id" extra string which is your token. It may start with "|ID|1|" (the "kid" parameter from the request, not quite sure what it does), in which case you need to remove that part.
You want to refresh your push token every time your app gets updated and also just periodically if you haven't done it in a while. I do it every 30 days.
Which is documented in this gist: https://gist.github.com/mar-v-in/2a054e3a4c0a508656549fc7d0a...
What prevents someone else from impersonating my app or other users on my app?
Now, I actually think this is a little too easy. What if I want to keep my ntfy server private for certain at-home uses? But still, very impressive. Element does it right, it at least asks you when you open the app (or it's in a setting or something). But I think UnifiedPush or ntfy instructions should make these steps more clear (or I failed to find it), even if just to say "it's actually that easy" to save our time looking.
BTW I'm working on porting ntfy to Sandstorm. Already works, I just have a handful of loose ends.
We are working on the documentation: https://codeberg.org/UnifiedPush/documentation/pulls/16