Уведомления о геозонах не работают в фоновом режиме на Android ⇐ Android
-
Anonymous
Уведомления о геозонах не работают в фоновом режиме на Android
Я создал простое приложение для геозон, которое отлично работает, когда приложение находится на переднем плане, но когда приложение находится в фоновом режиме, я не получаю никаких уведомлений. Я запустил службу переднего плана и правильно зарегистрировал свои геозоны. Я также предоставил своему приложению разрешение ACCESS_BACKGROUND_LOCATION. Любая помощь будет оценена по достоинству.
вот код MapsActivity.java
Открытый класс MapsActivity расширяет FragmentActivity реализует OnMapReadyCallback, GoogleMap.OnMapLongClickListener { частная статическая окончательная строка TAG = «MapsActivity»; частная карта GoogleMap; частный GeofencingClient geofencingClient; частный GeofenceHelper geofenceHelper; частное окончательное плавающее значение GEOFENCE_RADIUS = 30; частная окончательная строка GEOFENCE_ID = "SOME_GEOFENCE_ID"; частный финал int FINE_LOCATION_ACCESS_REQUEST_CODE = 10001; частный финал int BACKGROUND_LOCATION_ACCESS_REQUEST_CODE = 10002; @Override protected void onCreate (Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.activity_maps); // Получите SupportMapFragment и получите уведомление, когда карта будет готова к использованию. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(это); geofencingClient = LocationServices.getGeofencingClient(this); geofenceHelper = новый GeofenceHelper (это); } /** * Управляет картой, когда она доступна. * Этот обратный вызов запускается, когда карта готова к использованию. * Здесь мы можем добавлять маркеры или линии, добавлять слушателей или перемещать камеру. В этом случае, * мы просто добавляем маркер возле Сиднея, Австралия. * Если на устройстве не установлены сервисы Google Play, пользователю будет предложено установить * это внутри SupportMapFragment. Этот метод будет запущен только после того, как пользователь * установил сервисы Google Play и вернулся в приложение. */ @Override public void onMapReady(GoogleMap googleMap) { mMap = GoogleMap; // Добавляем маркер в Сиднее и перемещаем камеру LatLng eiffel = новый LatLng(48.8589, 2.29365); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(eiffel, 16)); включитьUserLocation(); mMap.setOnMapLongClickListener(это); } частный недействительный EnableUserLocation () { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mMap.setMyLocationEnabled(истина); } еще { //Попросить разрешения if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { //Нам нужно показать пользователю диалоговое окно, объясняющее, почему необходимо разрешение, а затем запросить разрешение... ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); } еще { ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); } } } @Override public void onRequestPermissionsResult(int requestCode, разрешения @NonNull String[], @NonNull int[]grantResults) { если (requestCode == FINE_LOCATION_ACCESS_REQUEST_CODE) { if (grantResults.length > 0 && GrantResults[0] == PackageManager.PERMISSION_GRANTED) { //У нас есть разрешение mMap.setMyLocationEnabled(истина); } еще { //У нас нет разрешения.. } } если (requestCode == BACKGROUND_LOCATION_ACCESS_REQUEST_CODE) { if (grantResults.length > 0 && GrantResults[0] == PackageManager.PERMISSION_GRANTED) { //У нас есть разрешение Toast.makeText(this, «Вы можете добавить геозоны...», Toast.LENGTH_SHORT).show(); } еще { //У нас нет разрешения.. Toast.makeText(this, «Для срабатывания геозон необходим доступ к фоновому местоположению...», Toast.LENGTH_SHORT).show(); } } } @Override общественная недействительность onMapLongClick (LatLng latLng) { если (Build.VERSION.SDK_INT >= 29) { //Нам нужно разрешение на фоновый режим if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { handleMapLongClick (latLng); } еще { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { //Показываем диалог и спрашиваем разрешение ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); } еще { ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); } } } еще { handleMapLongClick (latLng); } } частная пустота handleMapLongClick (LatLng latLng) { mMap.clear(); addMarker(latLng); addCircle(latLng, GEOFENCE_RADIUS); addGeofence(latLng, GEOFENCE_RADIUS); } Private void addGeofence(LatLng latLng, float radius) { Геозона Geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, радиус, Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT); GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence); PendingIntent pendingIntent = geofenceHelper.getPendingIntent(); geofencingClient.addGeofences(geofencingRequest, pendingIntent) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess (Void aVoid) { Log.d(TAG, "onSuccess: Добавлена геозона..."); } }) .addOnFailureListener(новый OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Строка errorMessage = geofenceHelper.getErrorString(e); Log.d(TAG, "onFailure: " + сообщение об ошибке); } }); } частная пустота addMarker (LatLng latLng) { MarkerOptions markerOptions = новый MarkerOptions().position(latLng); mMap.addMarker(markerOptions); } Private void addCircle(LatLng latLng, float radius) { CircleOptions CircleOptions = новый CircleOptions (); CircleOptions.center(latLng); CircleOptions.radius(радиус); CircleOptions.strokeColor(Color.argb(255, 255, 0, 0)); CircleOptions.fillColor(Color.argb(64, 255, 0, 0)); CircleOptions.strokeWidth(4); mMap.addCircle(circleOptions); } } вот код GeofenceBroadcastReceiver.java
публичный класс GeofenceBroadcastReceiver расширяет BroadcastReceiver { Private static Final String TAG = "GeofenceBroadcastReceiv"; @Override public void onReceive (контекст контекста, намерение намерения) { NotificationHelper NotificationHelper = новый NotificationHelper (контекст); GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(намерение); если (geofencingEvent.hasError()) { Log.d(TAG, "onReceive: Ошибка получения события геозоны..."); возвращаться; } List geofenceList = geofencingEvent.getTriggeringGeofences(); for (Геозона геозона: geofenceList) { Log.d(TAG, "onReceive: " + geofence.getRequestId()); } // Местоположение местоположения = geofencingEvent.getTriggeringLocation(); inttransitionType = geofencingEvent.getGeofenceTransition(); переключатель (тип перехода) { случай Geofence.GEOFENCE_TRANSITION_ENTER: Toast.makeText(context, "GEOFENCE_TRANSITION_ENTER", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_ENTER", "", MapsActivity.class); перерыв; случай Geofence.GEOFENCE_TRANSITION_DWELL: Toast.makeText(context, "GEOFENCE_TRANSITION_DWELL", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_DWELL", "", MapsActivity.class); перерыв; случай Geofence.GEOFENCE_TRANSITION_EXIT: Toast.makeText(context, "GEOFENCE_TRANSITION_EXIT", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_EXIT", "", MapsActivity.class); перерыв; } } } вот код GeofenceHelper.java
публичный класс GeofenceHelper расширяет ContextWrapper { частная статическая окончательная строка TAG = "GeofenceHelper"; PendingIntent public GeofenceHelper (Контекстная база) { супер(база); } public GeofencingRequest getGeofencingRequest(Geofence geofence) { вернуть новый GeofencingRequest.Builder() .addGeofence(геозона) .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) .строить(); } public Geofence getGeofence(String ID, LatLng latLng, float radius, inttransitionTypes) { вернуть новый Geofence.Builder() .setCircularRegion(latLng.latitude, latLng.longitude, radius) .setRequestId(ID) .setTransitionTypes(типыпереходов) .setLoiteringDelay(5000) .setExpirationDuration(Geofence.NEVER_EXPIRE) .строить(); } общественный PendingIntent getPendingIntent () { если (pendingIntent!= ноль) { вернуть ожидающее намерение; } Намерение намерение = новое намерение (это, GeofenceBroadcastReceiver.class); pendingIntent = PendingIntent.getBroadcast (это, 2607, намерение, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); вернуть ожидающее намерение; } общественная строка getErrorString (Исключение е) { если (e экземпляр ApiException) { ApiException apiException = (ApiException) e; переключатель (apiException.getStatusCode()) { случай GeofenceStatusCodes .GEOFENCE_NOT_AVAILABLE: вернуть «GEOFENCE_NOT_AVAILABLE»; случай GeofenceStatusCodes .GEOFENCE_TOO_MANY_GEOFENCES: вернуть «GEOFENCE_TOO_MANY_GEOFENCES»; случай GeofenceStatusCodes .GEOFENCE_TOO_MANY_PENDING_INTENTS: вернуть «GEOFENCE_TOO_MANY_PENDING_INTENTS»; } } вернуть e.getLocalizedMessage(); } } Когда приложение работает в фоновом режиме или закрывается, я хочу получать уведомление о том, что пользователь входит в зону геозоны или выходит из нее. Как мне это сделать.
Я создал простое приложение для геозон, которое отлично работает, когда приложение находится на переднем плане, но когда приложение находится в фоновом режиме, я не получаю никаких уведомлений. Я запустил службу переднего плана и правильно зарегистрировал свои геозоны. Я также предоставил своему приложению разрешение ACCESS_BACKGROUND_LOCATION. Любая помощь будет оценена по достоинству.
вот код MapsActivity.java
Открытый класс MapsActivity расширяет FragmentActivity реализует OnMapReadyCallback, GoogleMap.OnMapLongClickListener { частная статическая окончательная строка TAG = «MapsActivity»; частная карта GoogleMap; частный GeofencingClient geofencingClient; частный GeofenceHelper geofenceHelper; частное окончательное плавающее значение GEOFENCE_RADIUS = 30; частная окончательная строка GEOFENCE_ID = "SOME_GEOFENCE_ID"; частный финал int FINE_LOCATION_ACCESS_REQUEST_CODE = 10001; частный финал int BACKGROUND_LOCATION_ACCESS_REQUEST_CODE = 10002; @Override protected void onCreate (Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.activity_maps); // Получите SupportMapFragment и получите уведомление, когда карта будет готова к использованию. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(это); geofencingClient = LocationServices.getGeofencingClient(this); geofenceHelper = новый GeofenceHelper (это); } /** * Управляет картой, когда она доступна. * Этот обратный вызов запускается, когда карта готова к использованию. * Здесь мы можем добавлять маркеры или линии, добавлять слушателей или перемещать камеру. В этом случае, * мы просто добавляем маркер возле Сиднея, Австралия. * Если на устройстве не установлены сервисы Google Play, пользователю будет предложено установить * это внутри SupportMapFragment. Этот метод будет запущен только после того, как пользователь * установил сервисы Google Play и вернулся в приложение. */ @Override public void onMapReady(GoogleMap googleMap) { mMap = GoogleMap; // Добавляем маркер в Сиднее и перемещаем камеру LatLng eiffel = новый LatLng(48.8589, 2.29365); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(eiffel, 16)); включитьUserLocation(); mMap.setOnMapLongClickListener(это); } частный недействительный EnableUserLocation () { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mMap.setMyLocationEnabled(истина); } еще { //Попросить разрешения if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { //Нам нужно показать пользователю диалоговое окно, объясняющее, почему необходимо разрешение, а затем запросить разрешение... ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); } еще { ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); } } } @Override public void onRequestPermissionsResult(int requestCode, разрешения @NonNull String[], @NonNull int[]grantResults) { если (requestCode == FINE_LOCATION_ACCESS_REQUEST_CODE) { if (grantResults.length > 0 && GrantResults[0] == PackageManager.PERMISSION_GRANTED) { //У нас есть разрешение mMap.setMyLocationEnabled(истина); } еще { //У нас нет разрешения.. } } если (requestCode == BACKGROUND_LOCATION_ACCESS_REQUEST_CODE) { if (grantResults.length > 0 && GrantResults[0] == PackageManager.PERMISSION_GRANTED) { //У нас есть разрешение Toast.makeText(this, «Вы можете добавить геозоны...», Toast.LENGTH_SHORT).show(); } еще { //У нас нет разрешения.. Toast.makeText(this, «Для срабатывания геозон необходим доступ к фоновому местоположению...», Toast.LENGTH_SHORT).show(); } } } @Override общественная недействительность onMapLongClick (LatLng latLng) { если (Build.VERSION.SDK_INT >= 29) { //Нам нужно разрешение на фоновый режим if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { handleMapLongClick (latLng); } еще { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { //Показываем диалог и спрашиваем разрешение ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); } еще { ActivityCompat.requestPermissions(это, новая строка[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); } } } еще { handleMapLongClick (latLng); } } частная пустота handleMapLongClick (LatLng latLng) { mMap.clear(); addMarker(latLng); addCircle(latLng, GEOFENCE_RADIUS); addGeofence(latLng, GEOFENCE_RADIUS); } Private void addGeofence(LatLng latLng, float radius) { Геозона Geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, радиус, Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT); GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence); PendingIntent pendingIntent = geofenceHelper.getPendingIntent(); geofencingClient.addGeofences(geofencingRequest, pendingIntent) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess (Void aVoid) { Log.d(TAG, "onSuccess: Добавлена геозона..."); } }) .addOnFailureListener(новый OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Строка errorMessage = geofenceHelper.getErrorString(e); Log.d(TAG, "onFailure: " + сообщение об ошибке); } }); } частная пустота addMarker (LatLng latLng) { MarkerOptions markerOptions = новый MarkerOptions().position(latLng); mMap.addMarker(markerOptions); } Private void addCircle(LatLng latLng, float radius) { CircleOptions CircleOptions = новый CircleOptions (); CircleOptions.center(latLng); CircleOptions.radius(радиус); CircleOptions.strokeColor(Color.argb(255, 255, 0, 0)); CircleOptions.fillColor(Color.argb(64, 255, 0, 0)); CircleOptions.strokeWidth(4); mMap.addCircle(circleOptions); } } вот код GeofenceBroadcastReceiver.java
публичный класс GeofenceBroadcastReceiver расширяет BroadcastReceiver { Private static Final String TAG = "GeofenceBroadcastReceiv"; @Override public void onReceive (контекст контекста, намерение намерения) { NotificationHelper NotificationHelper = новый NotificationHelper (контекст); GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(намерение); если (geofencingEvent.hasError()) { Log.d(TAG, "onReceive: Ошибка получения события геозоны..."); возвращаться; } List geofenceList = geofencingEvent.getTriggeringGeofences(); for (Геозона геозона: geofenceList) { Log.d(TAG, "onReceive: " + geofence.getRequestId()); } // Местоположение местоположения = geofencingEvent.getTriggeringLocation(); inttransitionType = geofencingEvent.getGeofenceTransition(); переключатель (тип перехода) { случай Geofence.GEOFENCE_TRANSITION_ENTER: Toast.makeText(context, "GEOFENCE_TRANSITION_ENTER", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_ENTER", "", MapsActivity.class); перерыв; случай Geofence.GEOFENCE_TRANSITION_DWELL: Toast.makeText(context, "GEOFENCE_TRANSITION_DWELL", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_DWELL", "", MapsActivity.class); перерыв; случай Geofence.GEOFENCE_TRANSITION_EXIT: Toast.makeText(context, "GEOFENCE_TRANSITION_EXIT", Toast.LENGTH_SHORT).show(); NotificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_EXIT", "", MapsActivity.class); перерыв; } } } вот код GeofenceHelper.java
публичный класс GeofenceHelper расширяет ContextWrapper { частная статическая окончательная строка TAG = "GeofenceHelper"; PendingIntent public GeofenceHelper (Контекстная база) { супер(база); } public GeofencingRequest getGeofencingRequest(Geofence geofence) { вернуть новый GeofencingRequest.Builder() .addGeofence(геозона) .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) .строить(); } public Geofence getGeofence(String ID, LatLng latLng, float radius, inttransitionTypes) { вернуть новый Geofence.Builder() .setCircularRegion(latLng.latitude, latLng.longitude, radius) .setRequestId(ID) .setTransitionTypes(типыпереходов) .setLoiteringDelay(5000) .setExpirationDuration(Geofence.NEVER_EXPIRE) .строить(); } общественный PendingIntent getPendingIntent () { если (pendingIntent!= ноль) { вернуть ожидающее намерение; } Намерение намерение = новое намерение (это, GeofenceBroadcastReceiver.class); pendingIntent = PendingIntent.getBroadcast (это, 2607, намерение, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); вернуть ожидающее намерение; } общественная строка getErrorString (Исключение е) { если (e экземпляр ApiException) { ApiException apiException = (ApiException) e; переключатель (apiException.getStatusCode()) { случай GeofenceStatusCodes .GEOFENCE_NOT_AVAILABLE: вернуть «GEOFENCE_NOT_AVAILABLE»; случай GeofenceStatusCodes .GEOFENCE_TOO_MANY_GEOFENCES: вернуть «GEOFENCE_TOO_MANY_GEOFENCES»; случай GeofenceStatusCodes .GEOFENCE_TOO_MANY_PENDING_INTENTS: вернуть «GEOFENCE_TOO_MANY_PENDING_INTENTS»; } } вернуть e.getLocalizedMessage(); } } Когда приложение работает в фоновом режиме или закрывается, я хочу получать уведомление о том, что пользователь входит в зону геозоны или выходит из нее. Как мне это сделать.
Мобильная версия