如何在后台保留 android webview(使用位置)

How to keep android webview in the background (using the location)

我在 Android Studio 制作的 webview 中有一个 PWA,只要用户在前台有互联网、gps 和应用程序,它就可以完美地获取用户的位置。

我的问题是当他们最小化或关闭应用程序时。我需要继续收集用户的位置。

有什么方法可以让我的 webview 允许我的 PWA 在后台或应用程序关闭时继续收集位置?

您应该使用带有部分唤醒锁的前台服务,以防止 phone 休眠。 以下是实现唤醒锁的前台服务 Class 示例:

public class ICService extends Service {
    
    private static final int ID = 1;                        // The id of the notification
    
    private NotificationCompat.Builder builder;
    private NotificationManager mNotificationManager;
    private PowerManager.WakeLock wakeLock;                 // PARTIAL_WAKELOCK
    
    /**
     * Returns the instance of the service
     */
    public class LocalBinder extends Binder {
        public ICService getServiceInstance(){
            return ICService.this;
        }
    }
    private final IBinder mBinder = new LocalBinder();      // IBinder
    
    @Override
    public void onCreate() {
        super.onCreate();
        // PARTIAL_WAKELOCK
        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"INSERT_YOUR_APP_NAME:wakelock");
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        startForeground(ID, getNotification());
        return START_NOT_STICKY;
    }
    
    @SuppressLint("WakelockTimeout")
    @Override
    public IBinder onBind(Intent intent) {
        if (wakeLock != null && !wakeLock.isHeld()) {
            wakeLock.acquire();
        }
        return mBinder;
    }
    
    @Override
    public void onDestroy() {
        // PARTIAL_WAKELOCK
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
        super.onDestroy();
    }

    private Notification getNotification() {
        final String CHANNEL_ID = "YOUR_SERVICE_CHANNEL";

        builder = new NotificationCompat.Builder(this, CHANNEL_ID);
        //builder.setSmallIcon(R.drawable.ic_notification_24dp)
        builder.setSmallIcon(R.mipmap.YOUR_RESOURCE_ICON)
            .setColor(getResources().getColor(R.color.colorPrimaryLight))
            .setContentTitle(getString(R.string.app_name))
            .setShowWhen(false)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .setOngoing(true)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .setContentText(composeContentText());

        final Intent startIntent = new Intent(getApplicationContext(), ICActivity.class);
        startIntent.setAction(Intent.ACTION_MAIN);
        startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        startIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 1, startIntent, 0);
        builder.setContentIntent(contentIntent);
        return builder.build();
    }
}

显然,您还必须为您的应用禁用电池优化。 您可以浏览此服务的真实工作示例 here.

不要忘记在 AndroidManifest.xml 中将您的服务类型声明为“位置”,以便在 运行背景:

<!-- Recommended for Android 9 (API level 28) and lower. -->
<!-- Required for Android 10 (API level 29) and higher. -->
<service
    android:name="MyGPSService"
    android:foregroundServiceType="location" ... >
    <!-- Any inner elements would go here. -->
</service>

请注意,在前台访问 GPS 后,无需请求 android.permission.ACCESS_BACKGROUND_LOCATION 权限即可继续在后台接收位置:android.permission.ACCESS_FINE_LOCATION(以及 android.permission.ACCESS_COARSE_LOCATION 如果你使用 API31+) 就足够你使用了。