PUSH API · v1a
Android SDK
確認日:2026-09-11。外部コンソールの項目名は変更される場合があります。公式ガイドのリンクと実際のSDKバージョンも確認してください。
始める前に:3つの接続を区別する
SDKの導入、プッシュサービスの設定、端末登録は別の手順です。ライブラリのビルド成功だけでは通知の配信を確認できません。ご自身の端末1台で順番に確認してください。
- 組織・プロジェクト・アプリ環境を選びます。AndroidとiOSでは、それぞれのアプリとプッシュサービス設定を使います。
- 設定 → プッシュサービス接続でFCMまたはAPNsを設定し、検証状態を確認します。
/app-environments/{appEnvironmentId}/providers - 設定 → SDK接続から同じ環境の公開キーを用意します。既存アプリはstorageNamespaceを維持します。顧客向けSDKの接続先は固定で、モバイルアプリにサーバーAPIキーは埋め込まないでください。
/app-environments/{appEnvironmentId}/settings/sdk
0. FirebaseとFCMを準備する
- Firebase Consoleでプロジェクトを選び、実際のビルドvariantのapplicationIdでAndroidアプリを登録します。
- ダウンロードしたgoogle-services.jsonをアプリモジュールに配置します。既にFirebaseを利用している場合は、プロジェクトとパッケージの一致を確認して既存設定を維持します。
- Project settings → Service accounts → Firebase Admin SDKから承認済みのサービスアカウントJSONを用意します。キー作成は秘密の認証情報を発行する操作なので、組織の権限・保管方針に従ってください。
- Kitsのプッシュサービス接続でサービスアカウントJSONを選びます。project_idとclient_emailはファイルから読み取るため、送信者IDを推測する必要はありません。別プロジェクトの認証情報は現在未対応です。
// Project build.gradle.kts: merge into the existing plugins block.
plugins {
id("com.google.gms.google-services") version "4.5.0" apply false
}
// app/build.gradle.kts: merge, do not replace the existing Android setup.
plugins {
id("com.google.gms.google-services")
}
dependencies {
// Reference version compiled by the Kits sample; not a latest-version claim.
implementation("com.google.firebase:firebase-messaging:25.1.1")
}上記はKitsサンプルでコンパイルする基準バージョンで、最新版を示すものではありません。既存のFirebase BoM/version catalogと互換性を確認し、重複定義は避けてください。Kits AARはFirebaseをインストールしません。
新しい管理型SDKの簡単連携
import com.marcocorp.kits.push.fcm.Kits
// Once in Application.onCreate, with the push-fcm module:
Kits.initialize(this, publicKey)SDKが本番URLと既定ストレージを提供し、認証設定をダッシュボードから読みます。更新版SDKはユーザー・イベント・活動の収集を既定で有効にし、保存済みの収集拒否を維持します。同意前はcollectionEnabled=falseで収集を保留できます。既存アプリは更新や鍵交換で以前のnamespaceを維持してください。APNsの既定はproductionで、開発署名ではsandboxを明示します。
push-fcmがFirebase Messagingサービスとトークン更新を担当します。google-services.jsonとGoogle servicesプラグインはアプリに必要です。権限・クリックにはKitsのAPIを使い、既存ActivityのonNewIntentはKits.handleNotificationIntentへ渡します。
| 共通の任意設定 | 意味・既定値 |
|---|---|
collectionEnabled | 収集の統合設定・true。falseで開始すると収集を保留。既定のtrueで保存済みの拒否は解除しません |
foregroundPresentationPolicy | フォアグラウンド表示方針・PRESENT / .present |
shouldDisplay | 任意の表示コールバック・省略時は許可、エラー時は非表示 |
identityAuthProvider | VERIFIEDのアカウント証明プロバイダー・省略 |
audienceCollectionEnabled | 基本ユーザー情報・セッション収集・true。明示的なfalseは維持 |
notificationEventsEnabled | 実際の受信・タップ報告・true。メッセージのtrack_eventsも必要 |
observationOptions | persistNotificationEvents・true / activityDistributionEnabled・true |
同意前に収集を保留するには、初期化オプションでcollectionEnabled=falseを指定します。同意後はKits.setCollectionEnabled(true)で開始し、falseで停止します。通知の受信拒否やサーバーに保存済みの記録の削除とは別です。個別機能で明示したfalseは統合設定で有効にしても維持します。iOS拡張の受信報告は別途設定します。
Android固有設定はandroid: KitsAndroidOptions(FCMモード・通知リソース)、iOS固有設定はios: KitsIOSOptions(APNs環境・delegate連携)にまとめます。shouldDisplayはフォアグラウンド表示と新Android SDKによる表示を制御しますが、iOSや旧Android SDKでOSが表示するバックグラウンド通知は遮断できません。初期化だけでは権限を要求しません。
以下のcore専用設定・OSコールバック例は手動の低レベル連携を維持する場合のみ使います。上記の管理型初期化は、この連携をSDKが担当します。
対応条件はAndroid API 24以上です。SDKコアにはKotlin標準ライブラリ以外のFirebase・UIフレームワーク依存はありません。Firebaseの設定とコールバックの連携はアプリ側で行います。
1. 承認済みのSDKを用意する
管理型連携にはcom.marcocorp.kits:push-fcmと同じ版のcoreが必要です。以下のAPIに対応する検証済みリリースをapprovedKitsVersionに指定してください。Maven Centralでの公開は前提にしません。検証済みソースからのみ、次の操作でローカルMavenに配置できます。
./gradlew :push:publishToMavenLocal :push-fcm:publishToMavenLocal利用するアプリの既存のリポジトリ設定にローカルリポジトリを追加し、依存関係を設定します。承認済みの社内配布リポジトリを使う場合は、組織の設定に従ってください。
// settings.gradle.kts — use only an approved local artifact
dependencyResolutionManagement {
repositories {
mavenLocal()
google()
mavenCentral()
}
}
// app/build.gradle.kts
dependencies {
// Set approvedKitsVersion to the reviewed managed SDK release.
implementation("com.marcocorp.kits:push-fcm:$approvedKitsVersion")
}2. アプリの起動時に設定する
import android.app.Application
import com.marcocorp.kits.push.KitsPush
import com.marcocorp.kits.push.KitsPushClient
import com.marcocorp.kits.push.KitsPushConfiguration
import com.marcocorp.kits.push.KitsFcmMode
// Legacy core integration only: preserve the exact namespace already used by this app.
// New integrations use Kits.initialize(this, publicKey); the SDK manages storage.
// Merge into your existing Application; define BuildConfig fields in the host.
class MyApp : Application() {
lateinit var kitsPush: KitsPushClient
private set
override fun onCreate() {
super.onCreate()
kitsPush = KitsPush.configure(
context = this,
configuration = KitsPushConfiguration(
publicKey = BuildConfig.KITS_PUBLIC_KEY,
storageNamespace = BuildConfig.KITS_STORAGE_NAMESPACE,
fcmMode = KitsFcmMode.FID,
),
)
}
}BuildConfigの値はアプリ側で定義します。このcore例は手動OS連携を維持する場合のみ使い、管理型Kits.initializeと同時に初期化しないでください。同じプロセス・名前空間では設定を一致させます。
3. FCMモードとコールバックをつなぐ
この例はFIDモードです。対応するFirebase Messagingをアプリ側で設定し、次の項目をmanifestに追加します。
<meta-data
android:name="firebase_messaging_installation_id_enabled"
android:value="true" />FirebaseMessagingServiceとFirebaseMessaging.register()の呼び出しは、アプリ側で管理します。サービスはexported=falseで登録してください。以下のkitsPushはApplicationで作成した同じインスタンスです。状態の監視にはKitsSyncStateをインポートします。
// FirebaseMessagingService callbacks in FID mode
override fun onRegistered(fid: String) {
kitsPush.registerFirebaseInstallationIdAsync(fid)
}
override fun onUnregistered(fid: String) {
kitsPush.unregisterFirebaseInstallationIdAsync(fid)
}
// Observe server acknowledgement; close this listener when its owner is finished.
val subscription = kitsPush.addSyncStateListener { state ->
if (state is KitsSyncState.Synced) {
// Latest desired device state acknowledged by Kits.
}
}接続例:Manifestと実際のFCMコールバック
以下はFIDモードの部分例です。.MyAppと.AppMessagingServiceを実際のクラス名に合わせます。既存のApplicationやFirebaseMessagingServiceがある場合は、競合する別実装を追加せず既存のハンドラーに統合してください。
<!-- Merge into app/src/main/AndroidManifest.xml. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application android:name=".MyApp">
<meta-data
android:name="firebase_messaging_installation_id_enabled"
android:value="true" />
<service android:name=".AppMessagingService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
// MyApp is your existing Application subclass and owns kitsPush.
class AppMessagingService : FirebaseMessagingService() {
private val kitsPush get() = (application as MyApp).kitsPush
override fun onRegistered(installationId: String) {
kitsPush.registerFirebaseInstallationIdAsync(installationId)
}
override fun onUnregistered(installationId: String) {
kitsPush.unregisterFirebaseInstallationIdAsync(installationId)
}
override fun onMessageReceived(message: RemoteMessage) {
val payload = kitsPush.handleForegroundMessage(message.data)
// Route a recognized payload through your existing foreground UI.
// If null, continue the host's other-provider handling.
}
}
// After Firebase initialization and your host's consent decision:
// manual FID refresh; the callbacks above receive the identifier.
FirebaseMessaging.getInstance().register().addOnFailureListener {
// Show a safe retry state. Never log credentials or push addresses.
}権限の要求と表示の確認
- Android 13以降では、適切なユーザー操作をきっかけにPOST_NOTIFICATIONSを要求します。ダイアログ前後や設定アプリから戻った際に実際の権限を読み、reportPermissionAsyncへ渡します。
- 未要求と拒否を区別します。AndroidにはiOSと同じ全状態のenumがないため、ホスト側の権限要求履歴と現在の通知許可を組み合わせて判断します。
- Android 8以降では通知チャネルも確認します。アプリ全体が許可されていても、チャネルが無効だと表示されない場合があります。アイコン・チャネル・タップ時の遷移・フォアグラウンド表示はホストが管理します。
5. ダッシュボードと端末で最後まで確認する
- SDKの同期後、同じアプリ環境のオーディエンス → プッシュ購読でインストールを探します。ID・プラットフォーム・権限・受信設定を確認し、トークンの原文は共有しません。
- ご自身のインストールだけをテスト端末に指定し、直接送信で選びます。テストとして記録しても実際に通知され、権限・同意・プッシュサービス検証は省略されません。まず画像なしのSERVICE通知1件で確認します。
- 配信管理 → 送信済みメッセージでリクエストと個別配信結果を確認します。ダッシュボード/APIの送信元と通常/テストの目的は別項目です。受付やプッシュサービスの受理は端末表示・タップの成功ではありません。
- フォアグラウンド・バックグラウンド・通知タップによるコールドスタート・拒否後の再許可を別々に確認します。画像・タグ・多言語・受信観測は基本配信を確認してから追加します。
失敗している手順から確認する
| 症状 | 最初の確認 |
|---|---|
| インストールが表示されない | アプリ環境・公開キー・APIオリジン・ネットワーク・SDKエラーを確認します。configure/Queuedはサーバーの成功ではありません。最初の対処としてDBやアプリデータを削除しないでください。 |
| FCM_MODE_MISMATCH / Firebase callback | ManifestフラグとKitsFcmModeを一致させ、variantのgoogle-services.json・Google Play services・サービス登録を確認します。FIDと従来トークンを取り違えないでください。 |
| 受け付けたのに通知が来ない | 個別配信結果 → プッシュサービスのエラー → OS権限と受信設定 → チャネル/集中モード → フォアグラウンド表示の順に確認します。最初の結果を見る前に繰り返し送信しないでください。 |
| 通知が重複する | OneSignalとKitsの両方が送信していないか、OS表示の通知をアプリが再表示していないか確認します。各サーバーイベントの担当を既存プラットフォームとKitsのどちらかに明示してください。 |
4. 権限・受信設定・通知を扱う
- 実際のOS通知権限を読み取り、reportPermissionAsyncに渡します。同意があると決めつけたり、SDKへの報告でOSの権限が変わると考えたりしないでください。
- アプリ内でのユーザーの選択をsetPushPreferenceAsyncに渡します。マーケティング同意とは別に扱います。
- 実際のフォアグラウンド受信をkitsPush.handleForegroundMessage(message.data)に渡します。通知のタップはActivity.onCreateとonNewIntentからhandleNotificationIntentへ渡し、onNewIntentではsetIntentも更新します。
- 認識できないペイロードは、アプリの既存ハンドラーに渡します。画面遷移やリンクを開く処理はアプリ側で判断し、SDKが自動で行うことはありません。
- Queuedはローカルの待機状態です。サーバーへの反映はKitsSyncState.Syncedで確認します。明示的に同期を要求する場合はsynchronizeAsyncを使ってください。
任意:実際の受信・タップの観測
収集の既定値を更新したSDKソースではnotificationEventsEnabledとpersistNotificationEventsが既定でtrueです。公開済みの旧版とは異なる場合があるため、導入するリリースを確認してください。メッセージのtrack_events=trueは別途必要で、省略したAPIフィールドや保存済み下書きのfalseは自動変更しません。保存済みの収集拒否とcollectionEnabled=falseが優先されます。アプリの同意・プライバシー表示も確認してください。
// Optional argument in KitsPushConfiguration, after host consent:
notificationEventsEnabled = true
// Forward actual callbacks:
kitsPush.handleForegroundMessage(message.data)
kitsPush.handleNotificationIntent(intent)メッセージに{"track_events": true}を追加します。報告にはサーバー発行のkits_delivery_idと正確なバージョンマーカーが必要です。この予約IDを自作しないでください。CLICKEDからRECEIVEDは作られず、プッシュサービスの受理や表示を受信として推定しません。
独自の連携ではreportNotificationReceivedAsync(data, callback)またはreportNotificationClickedAsync(data, callback)を使えます。結果はmain looperに届きます。FCMのバックグラウンドnotification+dataのOS_DISPLAYは受信コールバックなしでOSが表示するため、タップのextrasから受信を作らないでください。
認証拒否(401)などの恒久的な失敗を無制限に再試行しません。記録の報告は通知の配信や分析の完了状態を変更しません。
メッセージ詳細のSDK記録は自動で読み込み、表示中は最大5分間、5秒ごとに更新します。グラフはサーバーに記録が届いた時刻を使うため、端末の実際のクリック時刻とは異なる場合があります。更新したり後から開いたりしても保存済みの時間別記録を確認できます。
バックグラウンド受信の記録
ANDROID_APP_DISPLAY_V1対応のサーバーとpush-fcm SDKを組み合わせると、画像なしの通知をdata-onlyで送り、SDKが受信して表示します。画像付き通知は画像表示を維持するためOS表示を使い、バックグラウンドの受信記録が欠ける場合があります。初期化はKits.initialize(this, publicKey)のままです。旧SDKとcoreのみの手動連携ではOS表示を維持します。対応サーバーを先に公開してから、新SDKを含むアプリを配信してください。
任意:アプリがフォアグラウンドで表示する通知のボタン
実際のフォアグラウンド受信後にアプリが通知を表示すると判断した場合のみ使います。categoryはローカルで選択し、新しいAndroidのwireフィールドではありません。ヘルパーは通知を表示せず、PendingIntentも実行しません。
val actions = KitsNotificationActions(listOf(KitsNotificationCategory("ORDER_V1",
listOf(KitsNotificationAction("VIEW_ORDER", "View order", R.drawable.ic_order)))))
actions.addToForegroundNotification(builder, message.data, "ORDER_V1", isAppForeground) { action ->
// Host-owned: unique per delivery/action, immutable explicit Activity PendingIntent.
hostPendingIntentFor(action.identifier, message.data)
}
// Host owns permission, channel, contentIntent, deduplication and notify().既存のactionsがない新しいbuilderに最大3個のローカルボタンを追加します。別のpayload・未登録category・false foregroundではfactoryを実行しません。画面遷移には直接Activity PendingIntentを使い、Receiver/Service trampolineは使わないでください。実際のタップをhandleNotificationIntentに渡すとCLICKEDのみを報告し、action IDの分析は収集しません。
SDKのログインとログアウト
- 認証モードはプロジェクト環境ごとに1つで、その環境のすべてのアプリに適用されます。プロジェクト環境の最初のアプリはBASICで始まり、後から追加したアプリはその環境のモードに従います。新SDKの簡単初期化はダッシュボードの設定を自動取得し、アプリ側での再指定は不要です。BASICでは顧客認証callback・JWT発行API・署名鍵は不要です。BASICはexternal IDの所有権を検証しないため、同じ環境のクライアントが別のUIDを名乗り、その通知を受け取る可能性があります。この制約を受け入れる環境で使用してください。VERIFIEDの認証失敗からBASICへ自動切替しません。
- VERIFIEDでは信頼できる顧客バックエンドのJWTが必要です。アプリ起動時にSDKの認証callbackを設定します。顧客バックエンドはセッションと有効なアカウントを検証し、要求されたexternal_idがセッションのUIDと一致することを確認してからcreateIdentityTokenSignerでJWTをローカル署名します。Kitsへのトークン発行HTTPリクエストはなく、既定TTLは300秒です。アプリから受け取ったユーザーIDだけを信用しないでください。
- 顧客環境でgenerateIdentityKeyPairを使い、鍵ペアを一度生成します。Dashboardのプロジェクト設定→SDK接続で、プロジェクト環境にkeyIdとpublicKeyPemだけを登録し、privateKeyPemは顧客バックエンドの秘密情報ストアに保管します。登録した公開鍵は、そのプロジェクト環境のすべてのアプリで共通です。秘密鍵をKitsにアップロードしないでください。新しい公開鍵の登録、署名鍵の切替、古い鍵の失効の順にローテーションします。JWTの署名・検証失敗を旧方式の発行や未検証ログインへ自動迂回しないでください。
- 両モードとも自身のインストールのdeviceTokenでGET /v1/installations/{id}/identityを読み、POST /v1/installations/{id}/identityで紐付けを変更します。VERIFIED LOGINはtokenのみ、BASIC LOGINはexternal_idのみを送信します。LOGOUTではtokenとexternal_idの両方を省略します。SDKがexpected_binding_id、operation_id、永続保存、直列化、再試行を管理します。証明や端末トークンをログに残さないでください。
- SDKは操作のモードを保存し、旧journalはVERIFIEDとして読みます。別モードで再起動した場合は完了状態を先に確認し、異なるモードの未完了LOGINをIDENTITY_AUTH_MODE_CHANGEDで停止します。現在のセッションでloginを再実行すると、ログアウトbarrierを経て選択したモードの新しい操作を作成します。
- 新しいAUTOフローはGET /v1/installations/{id}/identity-policyでbindingと設定revisionを同時に読みます。新しいLOGINのexpected_policy_revisionが変わると409 IDENTITY_REBIND_CONFLICTで再確認します。取得失敗や不正な応答をBASICと推測しません。送信済み操作は先に結果を確認し、VERIFIEDの証明を勝手に省略しません。LOGOUTは設定取得なしで既存のidentity経路を使います。明示的モードと旧journalも互換性を維持します。
- JWTはES256、aud=kits:identity、端末が属するアプリ環境のiss、identity.external_id、整数秒のiat/expを使用します。TTLは1–3600秒で、端末・binding・operationには固定されません。盗まれた場合、有効期間中に別の認証済みインストールで再利用される可能性があり、内容は暗号化されません。HTTPSとCache-Control: no-storeを使い、秘密鍵・JWT・リクエスト本文をログに残さないでください。メッセージごとのJWT発行は不要です。
- 旧方式との互換性としてidentity.createTokenとPOST /v1/identity-tokensは既存のkitid1証明用に残りますが、新しい連携では非推奨です。この旧HTTP経路だけがidentity:writeサーバーキーとインストール・binding・operationの情報を必要とします。ローカルJWT署名にKits APIキーは不要で、messages.createは別のmessages:sendサーバーキーを使用します。
- ローカルキューへの保存は、サーバーでログアウトが完了したことを意味しません。identityStateで確認済みの結果を確認してください。このフローと既存のバックエンドidentify/logoutを同時に実行しないでください。
以下の鍵設定と署名例はVERIFIEDのみで必要です。
import { createIdentityTokenSigner } from '@marco-inc/kits-node';
// VERIFIED backend only: load the private key from your secret store.
const signer = createIdentityTokenSigner({
appEnvironmentId, keyId, privateKeyPem, ttlSeconds: 300,
});
// In an authenticated handler, after checking the active account:
if (request.external_id !== verifiedUid) throw new Error('Session changed');
const result = signer.sign(verifiedUid); // {token, expires_at}; no HTTP call
// Return only to the authenticated app with Cache-Control: no-store.以下はログインイベント、ログアウトイベント、状態確認それぞれの例です。まとめて順番に実行しないでください。
// In Application.onCreate, once (managed push-fcm module):
Kits.initialize(this, publicKey)
// On authenticated login:
Kits.login(userID)
// On logout (a separate event):
Kits.logout()
// Remote confirmation, not just local queuing:
Kits.identityState()通知のステータスバーアイコン
管理型push-fcm SDKはkits_notification_small_iconを既定の小アイコンに使います。同じ名前のリソースをアプリに追加すると置き換えられます。ダッシュボードへのアップロードではなく、アプリのビルドに含める必要があります。
app/src/main/res/drawable-mdpi/kits_notification_small_icon.png // 24 × 24 px
app/src/main/res/drawable-hdpi/kits_notification_small_icon.png // 36 × 36 px
app/src/main/res/drawable-xhdpi/kits_notification_small_icon.png // 48 × 48 px
app/src/main/res/drawable-xxhdpi/kits_notification_small_icon.png // 72 × 72 px
app/src/main/res/drawable-xxxhdpi/kits_notification_small_icon.png // 96 × 96 px透明な背景に白い単色シルエットを使用してください。Androidはアルファを使って表示するため、背景付きカラーロゴやadaptive launcher iconは四角になったり正しく表示されない場合があります。単色vector drawableも使用できます。SDKのmanifestが既定の小アイコンを参照するため、アプリ側への重複設定は不要です。
メッセージごとの変更はプッシュ作成→詳細オプション→Android設定→小アイコンリソースで、ic_stat_analysisなど拡張子なしの名前を入力します。APIフィールドはandroid_small_iconです。受信側のアプリに含まれている必要があり、URLは使用できません。フォアグラウンドでの個別アイコンには対応SDKリリースが必要です。
リリースでリソースを縮小する場合、名前だけで参照する追加のアイコン・サウンドを保持してください。既存のkeep設定に実際のファイル名を追加し、リリースAPKでも確認してください。
<!-- app/src/main/res/raw/kits_resource_keep.xml -->
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@drawable/ic_stat_analysis,@raw/analysis_done" />ダッシュボードでAndroid通知チャンネルを管理
- Androidアプリ環境→アプリ設定→通知チャンネルで、チャンネルやグループを追加します。名前・説明は端末の通知設定に表示されます。
- 重要度・サウンド・振動・LED・バッジ・ロック画面表示を設定して保存します。チャンネル管理サーバーと同期対応Android SDKの両方が必要です。管理型初期化に追加のチャンネルコードは不要です。
- プッシュ作成→詳細オプション→Android設定→通知チャンネルで名前を選択します。未選択時はアプリの既定値を使います。アプリのコードで作成したチャンネルIDも入力できます。
既存の名前・説明・アーカイブ状態は変更できます。登録後に動作を変更する場合は新しいチャンネルを作成しますが、ユーザーの拒否を回避するために使わないでください。アーカイブは新規選択から隠し、端末からは削除しません。チャンネルグループはAndroid設定の整理用で、通知のgroup keyとは別です。
会話・投稿ごとに通知をまとめる
android_group対応サーバーとAndroid SDK 0.7.3以降が必要です。サーバーからメッセージごとにグループIDを指定できます。同じIDの個別通知を残してまとめます。チャンネルやandroid_notification_tagによる置き換えとは別です。
"android_group": "chat:room-1"
// Optional app fallback when the server does not specify android_group:
<string name="kits_notification_group_key_field" translatable="false">chatId</string>サーバーのIDが優先され、未指定ならdata.chatIdなどアプリで設定したデータ項目の値を使います。どちらもなければまとめません。通知は1つのグループに属しますが、IDはメッセージごとに変更でき、新しい会話や投稿のためのアプリ更新は不要です。chat:とpost:でIDの衝突を避けられます。
SDKが表示するAndroidのテキスト通知に適用され、画像通知やOS直接表示には適用されません。iOSでは既存のios_thread_idを使ってください。

