Reputation: 67
I created one foreground service to fetch the location for every 1 min somehow this service is not fetching location after sometime like one min.
I am creating one service before oreo background after oreo foreground service with in service I am trying to register for location updates but the problem is after killing app only up to one min I am getting location updates after that there is nothing I can get other than foreground service notification.
MainActivity.java
package com.practice.satya.foreground;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService();
}
public void startService() {
if(Build.VERSION.SDK_INT >25){
startForegroundService(new Intent(this, LocationFetchInForeground.class));
}else{
startService(new Intent(this, LocationFetchInForeground.class));
}
}
}
LocationUpdatesReceiver.java
package com.practice.satya.foreground;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
public class LocationUpdatesReceiver extends BroadcastReceiver {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onReceive(Context context, Intent intent) {
showNotification(context,"Location Changed","Updated location",intent);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void showNotification(Context context, String title, String body, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 93;
String channelId = "testing";
String channelName = "testing chanel";
int importance = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
}
LocationFetchInForeground.java
package com.practice.satya.foreground;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class LocationFetchInForeground extends Service {
private SensorManager sensorManager;
private Sensor sensor;
private TriggerEventListener triggerEventListener;
/** indicates how to behave if the service is killed */
int mStartMode;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
private static final String TAG = "MyLocationService";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 0f;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
Log.e(TAG, "LocationListener " + provider);
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
Toast.makeText(getApplicationContext(),"onLocationUpdated", Toast.LENGTH_LONG).show();
Intent intent=new Intent();
showNotification(getApplicationContext(),"Location Changed","Updated location",intent);
mLastLocation.set(location);
}
@Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + provider);
}
}
/*
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
*/
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER)
};
/** Called when the service is being created. */
@Override
public void onCreate() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//For creating the Foreground Service
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? getNotificationChannel(notificationManager) : "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("Location service")
.setContentText("This service is used to fetch location in background")
.setSmallIcon(R.mipmap.ic_launcher)
// .setPriority(PRIORITY_MIN)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.build();
startForeground(1, notification);
}
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
triggerEventListener = new TriggerEventListener() {
@Override
public void onTrigger(TriggerEvent event) {
// Do work
Toast.makeText(getApplicationContext(), "Location Updated", Toast.LENGTH_LONG).show();
Intent intent = new Intent();
showNotification(getApplicationContext(), "Motion Changed", "Updated location", intent);
}
};
if (sensor != null) {
sensorManager.requestTriggerSensor(triggerEventListener, sensor);
}
Log.e(TAG, "onCreate");
initializeLocationManager();
}
/** The service is starting, due to a call to startService() */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
try {
// Intent intenter = new Intent(this,LocationUpdatesReceiver.class);
// PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intenter, PendingIntent.FLAG_UPDATE_CURRENT);
// mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
// LOCATION_INTERVAL,
// LOCATION_DISTANCE,
// proximityIntent);
Intent intenter2 = new Intent(this,LocationUpdatesReceiver.class);
PendingIntent proximityIntent2 = PendingIntent.getBroadcast(this, 0, intenter2, PendingIntent.FLAG_UPDATE_CURRENT);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
LOCATION_INTERVAL,
LOCATION_DISTANCE,
proximityIntent2);
//
// mLocationManager.requestLocationUpdates(
// LocationManager.GPS_PROVIDER,
// LOCATION_INTERVAL,
// LOCATION_DISTANCE,
// mLocationListeners[0]
// );
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
return START_STICKY;
}
/** A client is binding to the service with bindService() */
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** Called when all clients have unbound with unbindService() */
@Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
/** Called when a client is binding to the service with bindService()*/
@Override
public void onRebind(Intent intent) {
}
/** Called when The service is no longer used and is being destroyed */
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listener, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: "+ LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
@RequiresApi(Build.VERSION_CODES.O)
private String getNotificationChannel(NotificationManager notificationManager){
String channelId = "ForegroundLocationFetch";
String channelName = getResources().getString(R.string.app_name);
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
channel.setImportance(NotificationManager.IMPORTANCE_NONE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
return channelId;
}
public void showNotification(Context context, String title, String body, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 234;
String channelId = "testing";
String channelName = "testing chanel";
int importance = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
notificationManager.notify(notificationId, mBuilder.build());
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.practice.satya.foreground">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-feature android:name="android.hardware.location.network"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationFetchInForeground" />
<receiver android:name=".LocationUpdatesReceiver"/>
</application>
</manifest>
Upvotes: 0
Views: 1587
Reputation: 31
In my experience with a React Native project using Expo Go, I've noticed a similar issue. When using an Android phone, whether I build the app or launch it with Expo Go, I only receive location updates when I'm actively moving. This behavior doesn't occur on iOS.
It seems that on Android, the background task for updating location doesn't trigger unless you're in motion. It waits for movement before updating the location.
Hope this helps!
Upvotes: 0
Reputation: 56
if your code is working right, some times android limit location updates due to power saving so make sure that your phone is charged more than 30% and your location is on ' high accuracy ':
package de.conlance.kotlinclean.stackoverflow
import android.annotation.SuppressLint
import android.app.Notification.EXTRA_NOTIFICATION_ID
import android.content.Intent
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import android.app.*
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Build
import android.os.Bundle
import de.conlance.kotlinclean.R
class ForGroundService : Service() {
companion object {
val CHANNEL_ID = "1956"
val notificationId = 252
val ACTION_SNOOZE = "de.conlance.kotlinclean.stopservice"
var cnt = 0
}
var locationListener: LocationListener? = null
var locationManager: LocationManager? = null
override fun onBind(intent: Intent?): IBinder? = null
override fun onCreate() {
// Start up the thread running the service
createCh()
startForeground(notificationId, NotificationCompat.Builder(this, CHANNEL_ID).build())
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
// If we get killed, after returning from here, restart
//Main Thread
showNotification("Service is Running")
doWork()
return START_NOT_STICKY
}
fun doWork() {
getLocation() {
showNotification(it)
}
}
override fun onDestroy() {
Log.v("ForService", "Service Is Dead")
RemoveUpdates()
showNotification("Service is Destroyed restart app .")
stopForeground(true)
}
//Create Notification Channel ID .
@SuppressLint("InlinedApi")
private fun showNotification(msg: String) {
val stopintent = Intent(this, MyBroadcastReceiver::class.java).apply {
ACTION_SNOOZE
putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val stoppendingintent: PendingIntent =
PendingIntent.getBroadcast(this, 0, stopintent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My notification")
.setContentText(msg)
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(msg)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.addAction(
R.mipmap.ic_launcher_round, "StopService",
stoppendingintent
)
with(NotificationManagerCompat.from(this)) {
// notificationId is a unique int for each notification that you must define
notify(notificationId, builder.build())
}
}
fun Context.getLocation(onResult: (String) -> Unit = {}) {
val context = this
locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
locationListener = object : LocationListener {
override fun onLocationChanged(location: Location?) {
location?.let {
onResult("cntrefresh {${++cnt}} lat-> ${it.latitude} , lng ${it.longitude} ")
//send Location To Activity and then send it to Parse Location Function......
}
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
// Timber.tag(MyTag).v("on Status Changed $provider $status")
}
override fun onProviderEnabled(provider: String?) {
// Timber.tag(MyTag).v("on Provider Enabled $provider")
}
override fun onProviderDisabled(provider: String?) {
// Timber.tag(MyTag).v("on Provider Disabled $provider")
}
}// location Listner
try {
locationManager?.let {
if (it.isProviderEnabled(LocationManager.GPS_PROVIDER) && it.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
it.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0f, locationListener)
else {
//fail.value = Failure.GPSError
onResult("Gps Error")
}
}
} catch (ex: SecurityException) {
// fail.value = Failure.SecurityError
onResult("Permission")
}
}
private fun RemoveUpdates() {
locationListener?.let {
locationManager?.removeUpdates(it)
}
}
fun createCh() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel
val name = "randname"
val descriptionText = "dumdum"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
mChannel.description = descriptionText
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
}
}
}
Upvotes: 1