Generate push icon
This commit is contained in:
parent
5843b3e33a
commit
f00687d20e
7 changed files with 90 additions and 0 deletions
|
|
@ -36,6 +36,17 @@
|
|||
android:grantUriPermissions="true">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<!-- FCM uses these when it renders a notification-payload message itself
|
||||
(app backgrounded/killed). Without an explicit monochrome small icon
|
||||
it falls back to the full-color adaptive launcher icon, which many
|
||||
Android builds render as a blank square or drop entirely. -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@drawable/ic_stat_notify" />
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
android:value="@string/default_notification_channel_id" />
|
||||
</application>
|
||||
|
||||
<!-- Permissions -->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package social.flotilla;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
|
|
@ -10,6 +13,28 @@ public class MainActivity extends BridgeActivity {
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
registerPlugin(AndroidPushFallbackPlugin.class);
|
||||
createPushNotificationChannel();
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
// Ensures the channel named by the FCM default_notification_channel_id metadata
|
||||
// exists. FCM does not create it for us; if it's missing when a notification
|
||||
// arrives, Android falls back to a generic "Miscellaneous" channel. Channels
|
||||
// persist once created, so doing this on launch is sufficient.
|
||||
private void createPushNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationManager manager = getSystemService(NotificationManager.class);
|
||||
String id = getString(R.string.default_notification_channel_id);
|
||||
|
||||
if (manager != null && manager.getNotificationChannel(id) == null) {
|
||||
NotificationChannel channel = new NotificationChannel(
|
||||
id,
|
||||
"Notifications",
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
);
|
||||
channel.setDescription("New messages and activity");
|
||||
manager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,5 @@
|
|||
<string name="title_activity_main">Flotilla</string>
|
||||
<string name="package_name">social.flotilla</string>
|
||||
<string name="custom_url_scheme">social.flotilla</string>
|
||||
<string name="default_notification_channel_id">flotilla_push</string>
|
||||
</resources>
|
||||
|
|
|
|||
3
build.sh
3
build.sh
|
|
@ -40,3 +40,6 @@ npx @capacitor/assets generate \
|
|||
--iconBackgroundColorDark '#222222' \
|
||||
--splashBackgroundColor '#ffffff' \
|
||||
--splashBackgroundColorDark '#191E24'
|
||||
|
||||
# @capacitor/assets doesn't generate Android notification icons
|
||||
node scripts/generate-notification-icon.mjs
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
"postcss": "^8.5.15",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-svelte": "^3.4.1",
|
||||
"sharp": "0.35.0-rc.0",
|
||||
"svelte": "^5.55.9",
|
||||
"svelte-check": "^4.3.5",
|
||||
"tailwindcss": "^4.2.2",
|
||||
|
|
|
|||
BIN
pnpm-lock.yaml
BIN
pnpm-lock.yaml
Binary file not shown.
49
scripts/generate-notification-icon.mjs
Normal file
49
scripts/generate-notification-icon.mjs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env node
|
||||
// Generates the Android notification (status-bar) small icon from the app's
|
||||
// source logo. @capacitor/assets does NOT produce notification icons, so the
|
||||
// build pipeline calls this after `@capacitor/assets generate` to keep the
|
||||
// notification icon in sync with a custom platform logo (VITE_PLATFORM_LOGO).
|
||||
//
|
||||
// A notification small icon must be a monochrome silhouette: Android renders
|
||||
// only its alpha channel and tints it. We take the logo's alpha channel as the
|
||||
// shape and fill it white, with a little transparent padding so it isn't
|
||||
// edge-to-edge in the status bar.
|
||||
import sharp from "sharp"
|
||||
import {mkdir} from "node:fs/promises"
|
||||
import {dirname, join} from "node:path"
|
||||
|
||||
const source = process.argv[2] || "assets/logo.png"
|
||||
const resDir = process.argv[3] || "android/app/src/main/res"
|
||||
|
||||
// density bucket -> small-icon size in px
|
||||
const densities = {mdpi: 24, hdpi: 36, xhdpi: 48, xxhdpi: 72, xxxhdpi: 96}
|
||||
|
||||
const generate = async (size, out) => {
|
||||
const pad = Math.round(size * 0.14)
|
||||
const inner = size - pad * 2
|
||||
|
||||
// The logo's alpha channel is the shape we want to render.
|
||||
const alpha = await sharp(source)
|
||||
.resize(inner, inner, {fit: "contain", background: {r: 0, g: 0, b: 0, alpha: 0}})
|
||||
.ensureAlpha()
|
||||
.extractChannel(3)
|
||||
.toColourspace("b-w")
|
||||
.raw()
|
||||
.toBuffer()
|
||||
|
||||
await sharp({
|
||||
create: {width: inner, height: inner, channels: 3, background: {r: 255, g: 255, b: 255}},
|
||||
})
|
||||
.joinChannel(alpha, {raw: {width: inner, height: inner, channels: 1}})
|
||||
.extend({top: pad, bottom: pad, left: pad, right: pad, background: {r: 0, g: 0, b: 0, alpha: 0}})
|
||||
.png()
|
||||
.toFile(out)
|
||||
|
||||
console.log(`wrote ${out} (${size}px)`)
|
||||
}
|
||||
|
||||
for (const [density, size] of Object.entries(densities)) {
|
||||
const out = join(resDir, `drawable-${density}`, "ic_stat_notify.png")
|
||||
await mkdir(dirname(out), {recursive: true})
|
||||
await generate(size, out)
|
||||
}
|
||||
Loading…
Reference in a new issue