Headless JS 的替代品

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

我正在尝试编写一个 React Native 应用程序,每 15 分钟运行一些处理。具体来说:我想从开放的第 3 方 API 获取状态,并在该状态发生更改时创建通知。

我想我可以使用 React Native 模块Headless JS 来做到这一点:

  1. 使用本机模块创建工作管理器:

a. JS端:

import { NativeModules } from "react-native";

const { WorkerModule } = NativeModules;

WorkerModule.configureWorker();

b.本机端:

class WorkerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {  
  
    var context = reactContext.getApplicationContext()  
  
    override fun getName() = "WorkerModule"  
  
    @ReactMethod fun configureWorker() {  
        val periodicRequest = PeriodicWorkRequest  
            .Builder(MyWorker::class.java, 15, TimeUnit.MINUTES)  
            .setInitialDelay(10, TimeUnit.SECONDS)  
            .build()  
  
        WorkManager  
            .getInstance(this.context)  
            .enqueueUniquePeriodicWork("unique_work_name", ExistingPeriodicWorkPolicy.UPDATE, periodicRequest)  
    }  
}

  1. 使用 Headless JS 注册 javascript 函数(根据 HeadlessJS 文档)

a. JS端:

AppRegistry.registerHeadlessTask("myBackgroundFetchFunction", (...args) => {
    console.log('woo! im a react native background javascript task')
    // do my fetch and notification logic in javascript
});

b. 本机侧

class JsTaskService : HeadlessJsTaskService() {  
    override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? {  
        return intent.extras?.let {  
            HeadlessJsTaskConfig(  
                "myBackgroundFetchFunction",  
                null,
                5000, // timeout for the task  
                true // optional: defines whether or not the task is allowed in foreground.  
                // Default is false            )  
        }  
    }  
}
  1. 使用本机工作人员使用 Headless JS 调用我的 javascript 函数:
class MyWorker(context: Context, private val workParams: WorkerParameters) : Worker(context, workParams) {  
    override fun doWork(): Result {  
        Log.d("MyWorker", "im a background task running in kotlin")
        val service = Intent(applicationContext, JsTaskService::class.java);  
  
        HeadlessJsTaskService.acquireWakeLockNow(applicationContext)  
    
        applicationContext.startForegroundService(service) 

        // or for older version of android:
        // applicationContext.startService(service) 
        return Result.success()  
    }  
}
  1. 在AndroidManifest中注册服务:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">  
  ...
  <application 
      android:name=".MainApplication" 
      android:label="@string/app_name" 
      android:icon="@mipmap/ic_launcher" 
      android:roundIcon="@mipmap/ic_launcher_round" 
      android:allowBackup="true" 
      android:theme="@style/AppTheme"
  >      
    ...    
    <service android:name=".....JsTaskService" />  
    <service        
        android:name="androidx.work.impl.foreground.SystemForegroundService"  
        android:foregroundServiceType="shortService" />  
  </application>
</manifest>

但是,在运行 Android 14 的设备上,我在尝试运行该行时遇到错误

applicationContext.startForegroundService(service)

android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false

我理解这是因为在 Android 14 上不再可以从后台服务启动前台服务。

我还发现 Headless JS 没有得到 React Native 团队的积极支持或推荐,并且没有在 Meta 内部使用


问题:

  1. 我们必须有哪些替代方案才能在 React Native 应用程序的后台运行 javascript 代码?
  2. 是否有任何示例可以遵循并允许 javascript 函数在最新版本的 Android 14 SDK 版本 34+ 上的 React Native 应用程序后台运行?
javascript android react-native kotlin
1个回答
0
投票

Workers处于后台,后台任务一般不能启动前台任务(也有一些例外)。 你根本不应该有服务,你应该直接在你的工作线程中做任何事情,而不需要服务。

顺便说一句——这确实不太适合 ReactNative。 我强烈考虑原生编写它,RN 与 Android 的后台处理并没有真正很好地配合,并且对于希望在后台运行而不被杀死的东西来说,启动时间和内存成本很高。 我认为你可以让它发挥作用,但这不是我建议的。

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