我已经在使用 React Native + Expo 编码的 Android 应用程序中拥有一个运行良好的前台服务 (49)。我使用 Notifee 创建服务并显示通知来执行此操作。
在我的开发版本中,一切正常,工作完成得很好。但是,当我创建独立运行的预览版本时,前台服务看起来好像已经启动(通知显示),而所有其他事情似乎都没有启动。
前台服务只是尝试连接蓝牙设备,如果连接成功,获取RSSI并计算到设备的大概距离并断开连接。接下来,通过 REST API 通知我的服务器。所有这一切每 35 秒重复一次。
我将其添加到 AndroidManifest 中。
<service android:name="app.notifee.core.ForegroundService" android:foregroundServiceType="location|dataSync" android:directBootAware="true" />
以及此权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
但是服务看起来没有启动,因为我的后端服务器没有被 API 调用:\
此主题中的开发版本和预/产品版本之间有什么区别?我是否失去了一些事实?
提前感谢您的回答。
您面临的问题似乎与 Android 13+(SDK 34 或更高版本)的权限和服务声明有关。在 Android 13 中,位置和 dataSync 等新的前台服务类型需要特定的前台服务权限,并且需要显式声明和处理这些权限。
您的开发版本可以工作,因为它可能在较低的 SDK 版本上运行,或者因为开发版本中的权限处理更宽松。然而,在生产版本中,更严格的权限要求可能会导致服务无法正常运行。
解决问题的要点: 自定义前台服务权限:Android 13+ 要求您为特定前台服务类型(例如位置或数据同步)定义和请求自定义权限。不幸的是,这些权限(如 android.permission.FOREGROUND_SERVICE_LOCATION 和 android.permission.FOREGROUND_SERVICE_DATA_SYNC)并未在 React Native 或 Expo 中预先定义。
解决方案:创建自定义权限模块:您需要创建自定义本机模块以通过编程方式请求这些权限。以下是在 Kotlin 中实现它的方法:
创建
MyPermissionsModule.kt
:
科特林
package com.yourapp
import android.app.Activity
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import com.facebook.react.bridge.*
class MyPermissionsModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return "MyPermissionsModule"
}
@ReactMethod
fun requestForegroundServicePermissions(promise: Promise) {
val activity = currentActivity ?: run {
promise.reject("ERROR", "Activity is null")
return
}
if (android.os.Build.VERSION.SDK_INT >= 34) {
val permissions = arrayOf(
"android.permission.FOREGROUND_SERVICE_LOCATION",
"android.permission.FOREGROUND_SERVICE_DATA_SYNC"
)
ActivityCompat.requestPermissions(activity, permissions, 1)
promise.resolve(true)
} else {
promise.resolve(false)
}
}
}
添加到主应用程序: 在 MainApplication 的 getPackages 方法中注册您的模块:
科特林
packages.add(MyPermissionsModule(reactContext))
JavaScript端:使用React Native中的模块在启动前台服务之前请求权限:
javascript
import { NativeModules, Platform } from 'react-native';
const { MyPermissionsModule } = NativeModules;
const requestPermissions = async () => {
if (Platform.OS === 'android' && Platform.Version >= 34) {
try {
await MyPermissionsModule.requestForegroundServicePermissions();
} catch (error) {
console.error('Error requesting permissions:', error);
}
}
};
其他 AndroidManifest 条目:确保您已正确定义所需的权限和服务类型:
xml
<service
android:name="app.notifee.core.ForegroundService"
android:foregroundServiceType="location|dataSync"
android:directBootAware="true" />
在启动前台服务之前调用权限请求:在启动前台服务之前,调用 requestPermissions() 以确保授予必要的权限。
生产与开发构建:在开发中,权限的处理通常更宽松,或者可能默认为“授予”。在生产中,尤其是较新的 SDK 版本,需要显式请求和处理权限。
为什么这很重要: 如果没有明确请求前台服务类型的这些新权限,您的服务可能会显示通知但无法执行其预期任务。
此方法应该可以解决您的问题,并确保您的前台服务在开发和生产构建中一致工作。如果您需要进一步帮助,请告诉我!