Run GPS listener in background on Android

2019-04-26 19:47发布

I would like to know how to receive GPS when the Android app is in the background. Is there a complete tutorial to explain it?

4条回答
迷人小祖宗
2楼-- · 2019-04-26 20:26
爷、活的狠高调
3楼-- · 2019-04-26 20:32

You need to use a AlarmManager to activate a pending intent (via a broadcast receiver) to launch a background service.

Some sample code for you

In your MainActivity

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent notifyintent = new Intent(this, OnAlarmReceiver.class);
notifyintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notifyintent.setAction("android.intent.action.NOTIFY");
PendingIntent notifysender = PendingIntent.getBroadcast(this, 0, notifyintent,
        PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 20 * 1000,
        notifysender);

AlarmReceiver class

public class OnAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    // PullPendingRequests.acquireStaticLock(context)
    try {
        lock = getLock(context);
        lock.acquire();
        context.startService(new Intent(context, UpdateCustomerRequests.class));
    } finally {
        if (lock.isHeld()) {
            lock.release();
        }
    }
}

The BroadcastReceiver

private static final String NAME = "com.commonsware.cwac.wakeful.WakefulIntentService";
private static volatile PowerManager.WakeLock lockStatic = null;
private static PowerManager.WakeLock lock;

// Needed since network will to work when device is sleeping.
synchronized private static PowerManager.WakeLock getLock(Context context) {
    if (lockStatic == null) {
        PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

        lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
        lockStatic.setReferenceCounted(true);
    }

    return (lockStatic);
  }
}

The background Service. Here you will notice 2 important points

  1. WakeLock, to ensure that your device wakes up and uses the network in the background
  2. A hack for LocationManager to work. I had to debug this for about 2 weeks, trust me, you need this. requestLocationUpdates and getLastKnownLocation will just not give your location when you want. Hence the AlarmManager (which runs much better than a java TimerTask thing).

All this works in a production app on the play store.

public class UpdateCustomerRequests extends IntentService implements LocationListener {
private static Context mainContext;

public UpdateCustomerRequests() {
    super("UpdateCustomerRequests");
    mHandler = new Handler();
    me = this;
}

public static UpdateCustomerRequests getService() {
    if (me == null)
        me = new UpdateCustomerRequests();
    return me;
}

@Override
final protected void onHandleIntent(Intent intent) {
    mainContext = getApplicationContext();
    Location myLocation;

    if (HomeScreen.getLocationManager() != null) {
        // this is needed to trigger a background location change. Since LocationManager does not work on Samsung phones. Its a hack needed.
        HomeScreen.getLocationManager().requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 0, 0, new LocationListener() {
                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
                }
                @Override
                public void onProviderEnabled(String provider) {
                }
                    @Override
                public void onProviderDisabled(String provider) {
                }
                @Override
                public void onLocationChanged(final Location location) {
            }
        });
        myLocation = HomeScreen.getLocationManager().getLastKnownLocation(
                LocationManager.NETWORK_PROVIDER);
        if (myLocation != null)
            onLocationChanged(myLocation);
        else {
            God.notifications.setSpeedNotification();
        }
    } else
        Log.e("Taxeeta:PullPendingRequets", "Not activated");

}

@Override
public void onLocationChanged(final Location location) {
    // Do your background stuff
}

}

Lastly, don't forget your manifest thing.

 <service
        android:name="com.taxeeta.UpdateCustomerRequests"
        android:enabled="true"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Light.NoTitleBar" />

    <receiver
        android:name="com.taxeeta.support.OnAlarmReceiver"
        android:exported="true" >
        <intent-filter>
            <action android:name="android.intent.action.NOTIFY" />
        </intent-filter>
    </receiver>
    <receiver
        android:name="com.taxeeta.HomeScreen$ResponseReceiver"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.taxeeta.intent.action.GET_SCREEN_UPDATES" />
        </intent-filter>
    </receiver>
查看更多
老娘就宠你
4楼-- · 2019-04-26 20:34

You can use a Service which always runs in the background..and in the background service you can get the current latitude and longitude and you can further convert these lats and longs into proper location using the Android geocoder class... check the follwing link:

http://www.codeproject.com/KB/android/GPSLocator.aspx

查看更多
再贱就再见
5楼-- · 2019-04-26 20:39

The thing which you will do in Activity can be done in service also..in the onStart() of Service....

查看更多
登录 后发表回答