B4A=true Group=Default Group ModulesStructureVersion=1 Type=Service Version=11.5 @EndOfDesignText@ #Region Service Attributes #StartAtBoot: True #ExcludeFromLibrary: True #StartCommandReturnValue: android.app.Service.START_STICKY #End Region Sub Process_Globals Dim pnreciver As PNBroadcastReceiver Dim awak As PhoneWakeState Private listener As NotificationListener Private Const SERVICE_RESTART_DELAY As Long = 5 * 60 * 1000 '5 دقیقه Private serviceTimer As Timer Private isServiceRunning As Boolean End Sub Sub Service_Create Try 'تنها یک بار WakeLock بگیر (برای شروع کار) awak.PartialLock awak.KeepAlive(True) 'true برای نگه داشتن قفل 'شنونده‌های سیستم listener.Initialize("listener") 'تنظیم Broadcast Receiver pnreciver.Initialize("pnreciver") pnreciver.AddAction("android.intent.action.SCREEN_ON") pnreciver.AddAction("android.intent.action.SCREEN_OFF") pnreciver.AddAction("android.intent.action.BATTERY_CHANGED") pnreciver.AddAction("android.intent.action.TIME_TICK") pnreciver.AddAction("android.provider.Telephony.SMS_RECEIVED") pnreciver.RegisterReceiver 'تایمر برای راه‌اندازی کنترل شده serviceTimer.Initialize("serviceTimer", SERVICE_RESTART_DELAY) serviceTimer.Enabled = False isServiceRunning = True 'راه‌اندازی سرویس اصلی با تاخیر CallSubDelayed2(FirebaseMessaging, "SubscribeToTopics", 5000) Catch Log("Error in Service_Create: " & LastException) 'در صورت خطا، با تاخیر مجدد راه‌اندازی کن StartServiceAt(Me, DateTime.Now + 10000, True) End Try End Sub Sub pnreciver_OnReceive(Action As String, keys() As String, Data As Object) Try Log("Broadcast received: " & Action) Select Case Action Case "android.intent.action.SCREEN_ON" 'وقتی صفحه روشن می‌شود EnsureServicesRunning Case "android.intent.action.SCREEN_OFF" 'وقتی صفحه خاموش می‌شود 'می‌توانیم برخی عملیات را متوقف کنیم awak.KeepAlive(False) Case "android.intent.action.BATTERY_CHANGED" 'وقتی وضعیت باتری تغییر می‌کند CheckBatteryAndAdjust Case "android.intent.action.TIME_TICK" 'هر دقیقه (برای بررسی وضعیت) CheckAndRestartIfNeeded Case "android.provider.Telephony.SMS_RECEIVED" 'پیامک دریافت شده HandleSmsBroadcast(Data) End Select Catch Log("Error in pnreciver_OnReceive: " & LastException) End Try End Sub Sub EnsureServicesRunning 'بررسی می‌کند که سرویس‌ها در حال اجرا هستند یا نه If Not(isServiceRunning) Then isServiceRunning = True StartService(FirebaseMessaging) CallSubDelayed2(FirebaseMessaging, "SubscribeToTopics", 3000) End If End Sub Sub CheckBatteryAndAdjust 'بررسی وضعیت باتری و تنظیم رفتار Dim bat As BatteryManager bat.Initialize If bat.Charging Then 'در حال شارژ - می‌توانیم بیشتر فعال باشیم awak.KeepAlive(True) serviceTimer.Interval = 2 * 60 * 1000 '2 دقیقه Else 'باتری - صرفه‌جویی در مصرف awak.KeepAlive(False) serviceTimer.Interval = 10 * 60 * 1000 '10 دقیقه End If If bat.Percent < 20 Then 'باتری کم - کاهش فعالیت serviceTimer.Enabled = False awak.KeepAlive(False) End If End Sub Sub CheckAndRestartIfNeeded 'بررسی سلامت سرویس‌ها Try 'بررسی اتصال اینترنت Dim conn As Phone If conn.GetDataState = "DISCONNECTED" Then 'اگر اینترنت قطع بود، منتظر بمان Return End If 'بررسی فعال بودن سرویس اصلی If Not(IsServiceRunning(FirebaseMessaging)) Then Log("Main service not running, restarting...") StartService(FirebaseMessaging) CallSubDelayed2(FirebaseMessaging, "SubscribeToTopics", 2000) End If 'راه‌اندازی تایمر برای بررسی مجدد If Not(serviceTimer.Enabled) Then serviceTimer.Enabled = True End If Catch Log("Error in CheckAndRestartIfNeeded: " & LastException) End Try End Sub Sub HandleSmsBroadcast(Data As Object) 'فوروارد کردن intent دریافت SMS به سرویس اصلی Dim in As Intent in = Data 'راه‌اندازی سرویس FirebaseMessaging با intent Dim starter As Intent starter.Initialize("", "") starter.SetComponent("anywheresoftware.b4a.samples.firebase.messaging/" & ".firebasemessaging") starter.PutExtra("sms_intent", in) StartService(starter) End Sub Sub Service_Start (StartingIntent As Intent) Try 'تنها کاری که اینجا باید بکنیم، راه‌اندازی تایمر برای بررسی است If Not(serviceTimer.Enabled) Then serviceTimer.Enabled = True End If 'بررسی اولیه CheckAndRestartIfNeeded 'اگر intent خاصی داریم، آن را پردازش کن If StartingIntent.IsInitialized Then If listener.HandleIntent(StartingIntent) Then Return End If 'Foreground mode برای اندروید 8+ If GetDeviceSDKVersion >= 26 Then StartForegroundWithNotification End If Catch Log("Error in Service_Start: " & LastException) Finally 'همیشه WakeLock را آزاد کن (به جز در موارد خاص) awak.KeepAlive(False) End Try End Sub Sub StartForegroundWithNotification 'برای اندروید 8+ باید notification نمایش دهیم Dim n As Notification n.Initialize2(n.IMPORTANCE_LOW) n.Icon = "icon" n.SetInfo("سرویس", "در حال اجرا...", "") Service.StartForeground(1, n) End Sub Sub GetDeviceSDKVersion As Int Dim r As Reflector r.Target = r.GetStaticField("android.os.Build$VERSION", "SDK_INT") Return r.GetField("SDK_INT") End Sub Sub IsServiceRunning(ServiceName As String) As Boolean 'بررسی می‌کند که سرویس در حال اجرا است یا نه Try Dim r As Reflector Dim context As JavaObject context.InitializeContext Dim manager As JavaObject manager = r.RunStaticMethod("android.app.ActivityManager", "getService", Null, Null) Dim runningServices As List runningServices = manager.RunMethodJO("getRunningServices", _ Array(100)).RunMethod("toArray", Null) For Each rs As JavaObject In runningServices Dim serviceInfo As JavaObject = rs.RunMethodJO("service", Null) Dim className As String = serviceInfo.GetField("className") If className.Contains(ServiceName.ToLowerCase) Then Return True End If Next Return False Catch Log("Error checking service: " & LastException) Return False End Try End Sub Sub serviceTimer_Tick 'هر چند دقیقه یکبار بررسی سلامت serviceTimer.Enabled = False CheckAndRestartIfNeeded 'تایمر را مجدداً فعال کن serviceTimer.Enabled = True End Sub Sub Service_Destroy Try Log("Service is being destroyed") 'آزاد کردن منابع isServiceRunning = False If serviceTimer.IsInitialized Then serviceTimer.Enabled = False End If awak.ReleaseKeepAlive awak.ReleasePartialLock If pnreciver.IsInitialized Then pnreciver.UnregisterReceiver End If 'برای اندروید 8+، foreground mode را متوقف کن If GetDeviceSDKVersion >= 26 Then Service.StopForeground(True) End If 'راه‌اندازی مجدد کنترل شده (اگر نیاز است) StartServiceAt(Me, DateTime.Now + SERVICE_RESTART_DELAY, True) Catch Log("Error in Service_Destroy: " & LastException) 'در صورت خطا، بعد از 10 ثانیه مجدداً تلاش کن StartServiceAt(Me, DateTime.Now + 10000, True) End Try End Sub