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

Android应用关闭时发送通知:非前台服务的位置监听方案咨询

无需前台服务实现APP关闭时的位置监听与通知方案

针对你需要在APP关闭时监听位置并发送通知的需求,有以下几种替代前台服务的方案:

1. Google Geofencing API(首选方案)

这是专门为「进入/离开特定地理区域触发事件」设计的系统级API,无需APP持续运行或前台服务,系统会在满足条件时主动触发回调,即使APP处于关闭状态也能正常工作。

实现步骤:

  • 申请权限:需要ACCESS_FINE_LOCATION(或ACCESS_COARSE_LOCATION),Android 10及以上额外需要ACCESS_BACKGROUND_LOCATION。
  • 创建Geofence:定义目标地点的坐标、范围半径,以及触发条件(如进入区域)。
  • 注册Geofence:通过GeofencingClient将Geofence与PendingIntent绑定,触发时系统会发送该Intent到你的广播接收器。

示例代码:

创建并注册Geofence

// 构建Geofence对象
Geofence targetGeofence = new Geofence.Builder()
        .setRequestId("remind_office") // 唯一标识
        .setCircularRegion(39.9042, 116.4074, 500) // 纬度、经度、半径(米)
        .setExpirationDuration(Geofence.NEVER_EXPIRE) // 永不过期
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER) // 触发条件:进入区域
        .build();

// 构建Geofencing请求
GeofencingRequest geofencingRequest = new GeofencingRequest.Builder()
        .addGeofence(targetGeofence)
        .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) // 初始进入也触发
        .build();

// 创建PendingIntent,触发时通知广播接收器
PendingIntent geofenceIntent = PendingIntent.getBroadcast(
        getApplicationContext(),
        0,
        new Intent(getApplicationContext(), GeofenceTriggerReceiver.class),
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE
);

// 注册Geofence
GeofencingClient geofencingClient = LocationServices.getGeofencingClient(this);
geofencingClient.addGeofences(geofencingRequest, geofenceIntent)
        .addOnSuccessListener(aVoid -> Log.d("Geofence", "注册成功"))
        .addOnFailureListener(e -> Log.e("Geofence", "注册失败:" + e.getMessage()));

广播接收器处理触发事件

public class GeofenceTriggerReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        GeofencingEvent event = GeofencingEvent.fromIntent(intent);
        if (event.hasError()) {
            Log.e("Geofence", "触发错误:" + event.getErrorCode());
            return;
        }

        int transitionType = event.getGeofenceTransition();
        if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
            // 用户进入目标区域,发送提醒通知
            sendReminderNotification(context, "已到达预设地点", "该处理待办事项啦");
        }
    }

    private void sendReminderNotification(Context context, String title, String content) {
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    "location_remind", "位置提醒", NotificationManager.IMPORTANCE_DEFAULT
            );
            manager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "location_remind")
                .setSmallIcon(R.drawable.ic_notify)
                .setContentTitle(title)
                .setContentText(content)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true);

        manager.notify(1, builder.build());
    }
}

注意事项:

  • 每个APP最多可注册100个Geofence;
  • 设备重启后Geofence会失效,需在BOOT_COMPLETED广播接收器中重新注册;
  • 部分厂商系统可能需要将APP加入后台白名单,否则可能无法触发。

2. WorkManager 结合周期性位置查询

如果你的场景不是固定区域提醒,而是需要定期检查位置,可以用WorkManager实现周期性后台任务,即使APP关闭也能执行位置查询逻辑。

实现步骤:

  • 创建Worker类:在doWork()方法中获取当前位置并判断是否满足提醒条件;
  • 配置周期性任务:用PeriodicWorkRequest设置任务执行间隔(系统最小允许15分钟);
  • 申请后台位置权限:Android 10+必须申请ACCESS_BACKGROUND_LOCATION。

示例代码:

Worker类实现

public class LocationCheckWorker extends Worker {
    public LocationCheckWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        FusedLocationProviderClient locationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
        
        // 检查后台位置权限
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            return Result.failure();
        }

        // 获取最新位置
        locationClient.getLastLocation()
                .addOnSuccessListener(location -> {
                    if (location != null) {
                        // 对比当前位置与预设地点的距离
                        if (isNearTargetLocation(location)) {
                            sendReminderNotification(getApplicationContext());
                        }
                    }
                });

        return Result.success();
    }

    private boolean isNearTargetLocation(Location currentLoc) {
        // 预设地点坐标
        Location targetLoc = new Location("");
        targetLoc.setLatitude(39.9042);
        targetLoc.setLongitude(116.4074);
        // 判断距离是否小于500米
        return currentLoc.distanceTo(targetLoc) < 500;
    }

    private void sendReminderNotification(Context context) {
        // 实现通知发送逻辑,同Geofence示例
    }
}

启动周期性任务

// 每15分钟执行一次,允许±5分钟弹性时间
PeriodicWorkRequest checkRequest = new PeriodicWorkRequest.Builder(
        LocationCheckWorker.class,
        15, TimeUnit.MINUTES,
        5, TimeUnit.MINUTES
).build();

WorkManager.getInstance(getApplicationContext()).enqueue(checkRequest);

注意事项:

  • 系统会限制后台任务的执行频率,无法做到实时监听;
  • 频繁的位置查询会增加电池消耗,仅适合非实时的场景。

3. 权限与系统限制说明

  • Android 10及以上必须申请ACCESS_BACKGROUND_LOCATION权限,且用户可随时在系统设置中关闭该权限,需处理权限被拒绝的情况;
  • 国内厂商(小米、华为、OPPO等)的系统可能有严格的后台管控,需引导用户将APP加入「后台运行白名单」或关闭「省电模式」,否则任务可能无法正常触发。

内容的提问来源于stack exchange,提问作者nortain32

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:21:05