即使从本机服务调用,React Native JS 中的 Headless JS 任务也不会运行

问题描述 投票:0回答:1

我试图通过将传入号码传递给处理数据的 Headless.js 来调用由 CallScreeningService 触发的 Headless 任务。它还触发了我的 RN 应用程序的前台服务。

来自我的 CallScreeningService.kt 和 CallHeadlessService.kt 的日志记录在 logcat 中,这表明它正在运行。我的前台服务也在运行。但不知何故 Headless.js 没有运行。

这是我的 CallScreeningService.kt

@RequiresApi(Build.VERSION_CODES.N)
class CallScreeningService: CallScreeningService() {
    @SuppressLint("VisibleForTests")
    @RequiresApi(Build.VERSION_CODES.Q)
    override fun onScreenCall(callDetails: Call.Details) {
        Log.d("Call_Receiver", "[SERVICE] Fetching caller number")
        val incomingNum = callDetails.handle.schemeSpecificPart
        Log.d("Call_Receiver", "[SERVICE] Incoming call from: $incomingNum")

        val intentForeground = Intent(this, CallForegroundService::class.java)
        startService(intentForeground)
        Log.d("Call_Receiver", "[FOREGROUND] Service called")

        val intent = Intent(this, CallHeadlessService::class.java)
        intent.putExtra("incomingNumber", incomingNum)
        this.startService(intent)

        HeadlessJsTaskService.acquireWakeLockNow(this)
        Log.d("Call_Receiver", "[MODULE] Headless task waking up")

        val response = CallResponse.Builder()
            .setDisallowCall(false)
            .setSilenceCall(false)
            .build()

        respondToCall(callDetails, response)
    }
}

这是我的CallHeadlessService.kt

package com.dev.justcall

import android.content.Intent
import android.util.Log
import com.facebook.react.HeadlessJsTaskService
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.jstasks.HeadlessJsTaskConfig

class CallHeadlessService : HeadlessJsTaskService() {
    override fun getTaskConfig(intent: Intent?): HeadlessJsTaskConfig {
        Log.d("Call_Receiver", "[HEADLESS] Task called")
        val incomingNumber = intent?.getStringExtra("incomingNumber") ?: ""
        Log.d("Call_Receiver", "[HEADLESS] Incoming Number: $incomingNumber")
        val taskData: WritableMap = Arguments.createMap()
        taskData.putString("incomingNumber", incomingNumber)
        Log.d("Call_Receiver", "[HEADLESS] Task Data: $taskData")

        return HeadlessJsTaskConfig(
            "IncomingCallTask",
            taskData,
            0,
            true
        )
    }
}

这是我的 Headless.js

import { AppRegistry, NativeModules } from "react-native";

//Import Javascript components
import CallerID from "./CallerID";
import CleanPhoneNumber from "./CleanPhoneNumber";
import StartPage from "../../app";
import { name as appName } from '../../app.json';

const { CallNativeModule } = NativeModules;

const handleIncomingCallTask = async (taskData) => {
    const { incomingNumber } = taskData;

    console.log('[HEADLESS] Task received incoming number:', incomingNumber);

    //Get wallet connection status and provider
    const { walletSigner } = global.appData;

    if (walletSigner) {
        console.log('[HEADLESS] User logged in');
        try {
            const cleanedPhoneNumber = await CleanPhoneNumber(incomingNumber);
    
            const profile = await CallerID(cleanedPhoneNumber, walletSigner);
    
            const name = profile[0];
            CallNativeModule.receiveCallerID(name, cleanedPhoneNumber);
            console.log('[HEADLESS] Caller ID sent to Native Module');
        } catch (error) {
            if (error.message.includes('[HEADLESS] Invalid phone number length.')) {
                console.log('[HEADLESS] Invalid phone number length.');
            } else if (error.message.includes('[HEADLESS] Phone number is not registered')) {
                console.log('[HEADLESS] Phone number is not registered.');
            } else {
                console.log('[HEADLESS] Error:', error);
            };
        };
    } else {
        console.log('[HEADLESS] User not logged in');
    };
};

console.log('[HEADLESS] App starting...');
AppRegistry.registerComponent(appName, () => StartPage);
AppRegistry.registerHeadlessTask('IncomingCallTask', () => handleIncomingCallTask);

该问题仅在运行前台服务时出现。当 RN 应用程序打开时,无头任务完美运行。

我怀疑这是前台服务启动和调用无头任务之间的延迟时间。但事实并非如此。

我希望能够在应用程序最初未运行时在前台运行无头任务。基本上 CallScreening 会触发前台服务来启动应用程序。

android react-native headless foreground-service callscreeningservice
1个回答
0
投票

为了启动前台服务,您需要运行

startForeground
并发出主动通知。
startService
不适用于在后台运行的前台任务,因为 api >=26。

这是在 React Native 中使用 Android 服务的示例,用于通过活动通知启动前台服务。

class SomeForegroundService : Service() {

    private val SERVICE_NOTIFICATION_ID = 12345
    private val CHANNEL_ID = "SOMENAME"


    private val handler: Handler = Handler()
    private val runnableCode: Runnable = object : Runnable {
        override fun run() {
            val context = applicationContext
            val service = Intent(context, CallHeadlessService::class.java)
            val bundle = Bundle()
            bundle.putString("foo", "bar")
            service.putExtras(bundle)
            context.startService(service)
            HeadlessJsTaskService.acquireWakeLockNow(context)
            handler.postDelayed(this, 3000)

        }
    }
    
    companion object {
            var isRunning = false
        }
    
        private fun createNotificationChannel() {
            // Create the NotificationChannel, but only on API 26+ because
            // the NotificationChannel class is new and not in the support library
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val importance = NotificationManager.IMPORTANCE_DEFAULT
                val channel = NotificationChannel(CHANNEL_ID, "Foreground Service Channel", importance)
                channel.description = "CHANNEL DESCRIPTION"
                val notificationManager = getSystemService(
                    NotificationManager::class.java
                )
                notificationManager.createNotificationChannel(channel)
            }
        }
    
        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    
            handler.post(runnableCode)
    
            isRunning = true
    
            createNotificationChannel()
            val notificationIntent = Intent(this, MainActivity::class.java)
            val contentIntent = PendingIntent.getActivity(
                this,
                0,
                notificationIntent,
                PendingIntent.FLAG_IMMUTABLE
            )
    
           
            val notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(this.resources.getIdentifier("launcher_icon", "mipmap", this.packageName))
                .setContentTitle("Some title")
                .setContentIntent(contentIntent)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build()
    
            startForeground(SERVICE_NOTIFICATION_ID, notification)
            return START_STICKY
        }
    
        override fun onDestroy() {
            super.onDestroy()
            handler.removeCallbacks(runnableCode)
            isRunning = false;
        }


    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.