Android后台持续定位传输问题求助:无需Google API
Hey Andrea, I feel your frustration—Android's background execution restrictions have gotten incredibly strict over the years, especially for apps that need continuous location tracking without relying on Google Play Services. Let's break down why your current approaches are failing and walk through actionable fixes that work with native Android APIs.
1. Fix Your Foreground Service Implementation
Oreo (API 26) and later kill background services almost immediately, so Foreground Service is mandatory—but you need to do it right to avoid being flagged or terminated:
- Permissions First: Add these to your
AndroidManifest.xml:
On Android 10+, you must explicitly ask users for background location permission (not just foreground access).<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- Android 10+ --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- Android 12+ --> - Proper Notification: Android requires Foreground Services to show a persistent notification. Keep it low-priority to avoid annoying users, but don't try to hide it—system checks will flag hidden notifications as suspicious:
private fun buildForegroundNotification(): Notification { val channelId = "location_tracking_channel" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel(channelId, "Background Tracking", NotificationManager.IMPORTANCE_LOW) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } return NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle("App is running") .setContentText("Tracking location in background") .setPriority(NotificationCompat.PRIORITY_LOW) .build() } - Start Correctly: Call
startForeground(NOTIFICATION_ID, notification)immediately in your service'sonCreate()method, and returnSTART_STICKYfromonStartCommand()to tell the system to restart the service if it's killed.
2. Use Native LocationManager Instead of Google APIs
Since you can't use FusedLocationProvider, stick to Android's built-in LocationManager for location updates—it's lightweight and doesn't depend on Google Services:
private fun initLocationTracking() { val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager val locationListener = object : LocationListener { override fun onLocationChanged(location: Location) { // Send location to your server here sendLocationToServer(location.latitude, location.longitude) } override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} override fun onProviderEnabled(provider: String) {} override fun onProviderDisabled(provider: String) {} } // Request updates (adjust interval/distance based on your needs) try { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 60000, // 1-minute interval 10f, // Update only if device moves 10 meters locationListener ) // Fallback to network provider if GPS is disabled locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 60000, 10f, locationListener ) } catch (e: SecurityException) { // Handle missing permissions } }
3. Add Redundancy with WorkManager
Even with a Foreground Service, aggressive battery savers (like those on Xiaomi, Huawei, or Samsung) might kill your process. Use WorkManager (part of AndroidX, no Google Play Services required) to schedule periodic location checks as a backup:
- Add the dependency to your
build.gradle:implementation "androidx.work:work-runtime:2.8.1" - Create a Worker class to fetch and send location:
class LocationBackupWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { val locationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager try { val lastLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) ?: locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) lastLocation?.let { sendLocationToServer(it.latitude, it.longitude) } } catch (e: SecurityException) { return Result.failure() } return Result.success() } } - Schedule the worker to run every 15 minutes (minimum allowed interval for periodic work):
val workRequest = PeriodicWorkRequestBuilder<LocationBackupWorker>(15, TimeUnit.MINUTES) .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build()) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "LocationBackup", ExistingPeriodicWorkPolicy.KEEP, workRequest )
4. Handle Boot Completion and System Events
Ensure your app restarts after the device boots by registering a broadcast receiver for ACTION_BOOT_COMPLETED:
- Add to
AndroidManifest.xml:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <receiver android:name=".BootCompletedReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> - Implement the receiver:
class BootCompletedReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_BOOT_COMPLETED) { val serviceIntent = Intent(context, LocationTrackingService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(serviceIntent) } else { context.startService(serviceIntent) } // Reschedule WorkManager tasks here too } } }
5. Adapt to Manufacturer Restrictions
This is critical for Chinese OEMs (Xiaomi, Huawei, Oppo, Vivo) which have their own background kill switches:
- Guide Users to Whitelist Your App: Tell users to go to Settings > Apps > [Your App] > Battery > Allow background activity, and enable "Auto-start" or "Run in background" options.
- Avoid Overpowering the CPU: System processes that use too much battery or CPU are more likely to be killed. Optimize your location update interval and server requests to minimize resource usage.
Final Notes
There's no 100% guarantee your app will run forever (Android's security model is designed to prevent persistent background apps), but combining these strategies will give you the best shot at keeping your location tracking service running consistently.
内容的提问来源于stack exchange,提问作者Andrea

