پوش Basic4Android
نصب، رضایت، Inbox بدون سرور، دریافت پسزمینه، تمدید توکن و رفع خطا.
پوش Basic4Android / B4A — نسخه ۱
اعلان این اتصال در نوار اعلان سیستمعامل نمایش داده میشود؛ کارت داخل اپ ساخته نمیشود. سرور اختصاصی ناشر، JWT و کلید خصوصی در اپ لازم نیست. روش استاندارد از FCM/APNs یا Web Push استفاده میکند؛ روش مستقیم از خود دیدنکس میخواند. مجوز و رضایت واقعی مخاطب در هر دو لازم است.
روش دریافت را انتخاب کنید
- استاندارد: آمادهسازی و کد ابتدای همین صفحه مربوط به FCM/Web Push است. - مستقیم، بدون Firebase: به بخش «اتصال مستقیم بدون Firebase» در ادامه همین صفحه بروید؛ وابستگی و تنظیمات FCM بخش استاندارد را نصب نکنید. محدودیت پسزمینه همانجا نوشته شده است. - فقط یک روش را برای هر نصب فعال کنید. برای تغییر روش، adapter قبلی را close/dispose و روش جدید را فعال کنید؛ برای توقف دریافت unsubscribe لازم است.
شناسه جایگاه چیست و از کجا بگیرم؟
پوش در دیدنکس از شناسه عمومی یکی از جایگاههای فعال همان رسانه برای پیدا کردن اپ یا سایت شما استفاده میکند. پیشوند واقعی این شناسه UNT_ است. این مقدار نام اپ، شناسه بسته، شناسه رسانه با پیشوند AST_، توکن FCM یا کلید API نیست و محرمانه نیست.
در پنل ناشر، «جایگاههای تبلیغ» را باز کنید؛ شناسه زیر نام جایگاه دیده میشود. همان شناسه کامل را کپی کنید. راه سادهتر: در «پوش ← اتصال رسانهها»، برای رسانه خود «کد پوش» را بزنید و پلتفرم را انتخاب کنید؛ کد با شناسه واقعی شما ساخته میشود و نیازی به حدس یا جایگزینی دستی ندارد.
در مثال عمومی زیر، placementId یا PlacementId یا PLACEMENT_ID متغیری برای نگهداری همین شناسه است. متن PASTE_YOUR_PLACEMENT_ID_HERE فقط محل جایگزینی است و شناسه قابل استفاده نیست. آن را با شناسه کامل جایگاه خودتان که با UNT_ شروع میشود عوض کنید. یک جایگاه فعال کافی است؛ جایگاه مخصوص پوش و نمایش تبلیغ برای عضوکردن مخاطب لازم نیست. رسانه نیز باید فعال و تأییدشده باشد و پوش آن در پنل فعال شده باشد.
| مقدار | محل دریافت / کاربرد |
|---|---|
شناسه جایگاه (UNT_…) | پنل ناشر ← جایگاههای تبلیغ؛ ورودی ایجاد کنترلر پوش |
| شناسه بسته | تنظیمات پروژه اپ؛ باید با رسانه اپ ثبتشده یکسان باشد |
| دامنه دیدنکس | نشانی همین سرویس؛ سرور اختصاصی ناشر لازم نیست |
| کلید خصوصی API | داخل اپ یا مرورگر قرار نمیگیرد |
اگر inactive_inventory دیدید، فعال و تأییدبودن رسانه و فعالبودن جایگاه همان رسانه را بررسی کنید. کپیکردن شناسه از یک حساب یا رسانه دیگر اتصال را درست نمیکند.
روش استاندارد — آمادهسازی
کلاسهای DidnexAds، DidnexPush و DidnexIntegrity جدید را جایگزین کنید؛ نسخه پوش جداگانه و تکراری نصب نکنید. JavaObject، OkHttpUtils2، JSON، RuntimePermissions و FirebaseNotifications را فعال و google-services.json همان package را در پوشه پروژه قرار دهید. فایل integrations/FirebaseMessaging.bas را به عنوان Receiver با نام FirebaseMessaging اضافه یا در Receiver موجود ادغام کنید؛ service قدیمی دوم نسازید. Receiver تنظیمات عمومی origin/unit/topics را از ثبت موفق SDK میخواند و شناسه دوم لازم ندارد. Receive خودش Notification سیستمعامل میسازد؛ Push_Message و Panel لازم نیست. تست پسزمینه را روی Release انجام دهید؛ اجرای Debug زیر IDE معیار دریافت پسزمینه نیست. برای لغو، Wait For (Push.Unsubscribe) Complete (Ok As Boolean) را اجرا و در قطع شبکه دوباره تلاش کنید.
در Libraries Manager خود B4A، FirebaseAnalytics و FirebaseNotifications را انتخاب کنید؛ FirebaseMessaging نام Receiver و نوع داخل کتابخانه است، نه نام فایل macro. سه macro صحیح در بخش Manifest همین راهنما آمدهاند. مرجع رسمی: https://www.b4x.com/android/forum/threads/b4x-firebase-push-notifications-2023.148715/
کد اتصال استاندارد
Sub Process_Globals
Private Permissions As RuntimePermissions
Private Fcm As FirebaseMessaging
End Sub
Sub Globals
Private Const PlacementId As String = "PASTE_YOUR_PLACEMENT_ID_HERE"
Private Ads As DidnexAds
Private Push As DidnexPush
Private EnableButton As Button
End Sub
Sub Activity_Create(FirstTime As Boolean)
Ads.Initialize(Me,"Ads","https://didnex.com",Application.PackageName)
Push = Ads.CreatePush(PlacementId,Me,"Push")
Try
Fcm.Initialize("Fcm")
Catch
Log("firebase_configuration_required")
End Try
EnableButton.Initialize("EnableButton")
EnableButton.Text="فعالسازی اعلان"
Activity.AddView(EnableButton,8dip,8dip,100%x-16dip,48dip)
End Sub
Sub EnableButton_Click
If Push.NotificationsEnabled = False Then
Permissions.CheckAndRequest("android.permission.POST_NOTIFICATIONS")
Wait For Activity_PermissionResult(Permission As String, Result As Boolean)
If Result = False Then Return
End If
If Fcm.IsInitialized = False Then Return
If Fcm.Token = "" Then Return
Wait For (Push.SubscribeFcm(Fcm.Token,True,Array As String("general"))) Complete (Subscribed As Boolean)
If Subscribed = False Then Log("push_connection_required")
End Sub
Sub Activity_Resume
Wait For (Push.HandleIntent(Activity.GetStartingIntent)) Complete (Payload As Map)
End Sub
Sub Activity_Pause(UserClosed As Boolean)
If UserClosed Then Push.Close
End Sub
Sub Push_Opened(Payload As Map)
' Real notification tap: navigate only to routes accepted by your app.
End Sub
Sub Ads_Event(Detail As Map)
End Sub
Sub Push_Error(Code As String)
Log("Didnex push: " & Code)
End SubManifest و مجوز روش استاندارد
AddPermission(android.permission.INTERNET)
AddPermission(android.permission.POST_NOTIFICATIONS)
CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)
CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)
CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)
' Add integrations/FirebaseMessaging.bas as a Receiver named FirebaseMessaging.
' Add google-services.json; enable FirebaseNotifications and RuntimePermissions.تنظیم یکباره ناشر
در «پوش ← اتصال رسانهها»، پوش همان رسانه فعال و تأییدشده را روشن کنید. فقط اگر روش استاندارد FCM را انتخاب کردهاید، JSON حساب سرویس همان پروژه Firebase را فقط در پنل ثبت کنید؛ کلید خصوصی Service Account نباید داخل اپ، مخزن عمومی یا مرورگر باشد. google-services.json و GoogleService-Info.plist تنظیمات کلاینت اپ هستند و با Service Account فرق دارند. iOS در روش استاندارد به کلید APNs و قابلیت Push Notifications همان bundle نیاز دارد. برای وب، VAPID را دیدنکس ایجاد میکند و Service Worker روی دامنه خود ناشر است. سرویس OneSignal وابستگی این اتصال نیست؛ مخاطبان، صف و آمار در دیدنکس مدیریت میشوند.
کلاینت تبلیغات و پوش را مشترک نگه دارید. init هیچ اجازهای درخواست نمیکند. فعالسازی را فقط در پاسخ به دکمه رضایت انجام دهید؛ برای راهاندازی بعدی، restore صرفاً رضایت قبلی را بازیابی میکند و مجوز تازه نمیخواهد. توکن تازه را دوباره ثبت و opt-out را به unsubscribe متصل کنید. close/dispose فقط شنونده محلی را میبندد؛ برای لغو عضویت سرور، unsubscribe لازم است. خطاها را کنترل کنید تا اپ به کار عادی ادامه دهد. اگر Firebase یا Service Worker دارید، callbackها را ادغام کنید و سرویس/worker تکراری نسازید.
تأیید ایمیل، مربوط به حساب ناشر در پنل است؛ کاربر نهایی اپ برای دریافت تبلیغ یا پوش، به حساب دیدنکس یا ورود نیاز ندارد. رضایت و مجوز اعلان همچنان الزامی است.
لینک مقصد اعلان
لینک لمس، دکمه و گونه میتواند HTTP یا HTTPS هر دامنه باشد؛ محدود به رسانه نیست. لینک اجرایی، فایل، داده و اطلاعات ورود رد میشوند. خالی یعنی صفحه اصلی سایت یا صفحه انتشار اپ. این مجوز برای مقصد است؛ اتصال سرویس و رسید فقط HTTPS خود دیدنکس است. Worker روی سایت ناشر نصب میشود. پشتیبانی HTTP در دستگاه نیازمند SDK همین انتشار است.
تست دستگاه
۱. بسته جدید همین پلتفرم و adapter آن را در اپ جایگزین کنید؛ آپدیت سرور بهتنهایی SDK نصبشده روی دستگاه را تغییر نمیدهد. خروجی Release واقعی بگیرید. مجوز را با دکمه فعالسازی دریافت کنید.
۲. در پنل باید اشتراک FCM یا Web Push دیده شود؛ Inbox برای ارسال پنل کافی نیست. اعلان آزمایشی بفرستید. در پیشزمینه، پسزمینه و شروع سرد با لمس اعلان، نوار اعلان سیستمعامل را بررسی کنید؛ صفحه اپ نباید کارت اعلان اضافه کند.
۳. رد مجوز، اینترنت قطع، پیام منقضی و پیام تکراری را بررسی کنید؛ نباید delivered جعلی ساخته شود. بعد از لغو عضویت، ارسال بعدی نباید مخاطب را صف کند. اعلان قبلاً تحویلشده به provider ممکن است هنوز در مسیر باشد. receipt حاوی دسترسی خصوصی است و نباید وارد گزارش عمومی شود.
۴. دریافت پذیرفتهشده توسط FCM به معنی دیدهشدن نیست. در بعضی اعلانهای پسزمینه، OS بدون اجرای SDK نمایش میدهد و delivered قابل گزارش نیست؛ آن را از accepted حدس نزنید. روی Android بدون Google Play Services یا بدون دسترسی شبکه به FCM، این مسیر ممکن است آماده نباشد. محدودیت سیستمعامل را با پیام داخل اپ جایگزین نکنید.
انتخاب مسیر و محدودیت مستقیم
برای فعالسازی روش مستقیم، روشنبودن پوش رسانه کافی است؛ Service Account، google-services.json و VAPID لازم نیست. هنگام ارسال پنل، همه مسیرهای اعلان بهصورت پیشفرض مخاطب هستند؛ در تنظیمات بیشتر میتوانید فقط «مستقیم» یا فقط «استاندارد» را انتخاب کنید. یک نصب همزمان یک مسیر فعال دارد؛ تغییر روش، اشتراک روش قبلی را لغو میکند. controller/adapter قبلی را قبل از انتخاب تازه close کنید و فقط controller انتخابشده را restore کنید. برای انصراف مخاطب از همه اعلانهای این نصب unsubscribe را به کار ببرید.
در Android بومی، B4A، Flutter Android، Unity Android و Godot Android دریافت دورهای JobScheduler با حداقل ۱۵ دقیقه ممکن است. این زمانبندی دقیق نیست و سیستم میتواند آن را عقب بیندازد. در iOS، React Native و وب دریافت مستقیم فقط زمان فعالیت اپ/صفحه است؛ برای دریافت از راه دور هنگام بستهبودن، مسیر استاندارد را انتخاب کنید. nativeBuild=not_run را به معنی تست دستگاه نگیرید.
API قدیمی
Inbox صرفاً برای سازگاری و ارسال صریح deliveryChannel=inbox باقی مانده و مسیر پنل نیست. برچسبها، بخش مخاطب، quiet hours و هویت امضاشده در همان کنترلر قابل استفادهاند. اتصال عادی به سرور اختصاصی ناشر نیاز ندارد؛ اگر هویت امضاشده کاربر خودتان را میخواهید، فقط تولید همان proof به سرور امن خودتان نیاز دارد.
رفتار اعلان استاندارد
پیام notification+data در پسزمینه توسط provider به سیستمعامل میرسد؛ آن را دوباره نمایش ندهید. در پیشزمینه، adapter این بسته اعلان بومی میسازد. accepted پذیرش سرویس است؛ delivered ثبت اعلان در سیستمعامل از دید SDK و opened لمس واقعی است. حالت مزاحم نشوید، محدودیت باتری یا Force Stop ممکن است نمایش را محدود کند.
مرجع رسمی
https://www.b4x.com/android/forum/threads/b4x-firebase-push-notifications-2023.148715/ https://www.b4x.com/android/help/firebasenotifications.html
اتصال مستقیم بدون Firebase
کلاسهای SDK را مثل تبلیغات اضافه کنید. فایل integrations/direct/didnex-direct-push.jar را به پوشه Additional Libraries بیسیک۴اندروید کپی کنید و #AdditionalJar نمونه را در Main بگذارید. JavaObject، JSON، OkHttpUtils2 و RuntimePermissions لازماند؛ FirebaseNotifications و FirebaseAnalytics برای این روش لازم نیستند. کد integrations/direct/Manifest.txt را در Manifest Editor بگذارید. JAR از دو سورس Java همراه ساخته شده و BUILD.json هش آنها را دارد؛ این به معنی اجرای B4A IDE یا تست دستگاه نیست.
#Region Project Attributes
#ApplicationLabel: Didnex Direct Push
#VersionCode: 1
#VersionName: 1
#AdditionalJar: didnex-direct-push
#End Region
Sub Process_Globals
End Sub
Sub Globals
Private Ads As DidnexAds
Private Push As DidnexPush
Private RP As RuntimePermissions
Private EnableButton As Button
End Sub
Sub Activity_Create(FirstTime As Boolean)
Ads.Initialize(Me,"Ads","https://didnex.com",Application.PackageName)
Push=Ads.CreatePush("PASTE_YOUR_PLACEMENT_ID_HERE",Me,"Push")
Push.RestoreDirect
EnableButton.Initialize("EnableButton")
EnableButton.Text="فعالسازی اعلان مستقیم"
Activity.AddView(EnableButton,0,0,100%x,52dip)
Wait For (Push.HandleIntent(Activity.GetStartingIntent)) Complete (Opened As Map)
End Sub
Sub EnableButton_Click
If Push.NotificationsEnabled=False Then
RP.CheckAndRequest("android.permission.POST_NOTIFICATIONS")
Wait For Activity_PermissionResult(Permission As String,Granted As Boolean)
If Granted=False Then Return
End If
Wait For (Push.EnableDirect(True,True,Array As String("general"))) Complete (Enabled As Boolean)
Log("Didnex direct enabled: " & Enabled)
End Sub
Sub Push_Error(Code As String)
Log("Didnex push: " & Code)
End Sub
Sub Push_Opened(Payload As Map)
' A real OS-notification tap. Validate its HTTPS destination before navigation.
End Sub
Sub Ads_Event(Detail As Map)
End Sub
Sub Activity_Resume
Push.SetActive(True)
End Sub
Sub Activity_Pause(UserClosed As Boolean)
Push.SetActive(False)
End Sub
' Opt-out: Wait For (Push.Unsubscribe) Complete (Unsubscribed As Boolean)Manifest مستقیم
AddPermission(android.permission.INTERNET)
AddPermission(android.permission.POST_NOTIFICATIONS)
AddPermission(android.permission.RECEIVE_BOOT_COMPLETED)
AddApplicationText(<service android:name="com.didnex.ads.DidnexDirectPush$Job" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />)محدودیت دریافت مستقیم
دریافت فعال حدود هر ۶۰ ثانیه و دریافت دورهای با JobScheduler حداقل هر ۱۵ دقیقه است. سیستم میتواند کار را عقب بیندازد. پارامتر دوم EnableDirect اگر False باشد پسزمینه خاموش میشود. به Receiver فایربیس نیاز ندارید.