You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android后台持续定位传输问题求助:无需Google API

How to Keep a Location-Tracking App Running Persistently in the Background (No 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:
    <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+ -->
    
    On Android 10+, you must explicitly ask users for background location permission (not just foreground access).
  • 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's onCreate() method, and return START_STICKY from onStartCommand() 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:20:26