Я хотел бы знать, как получать GPS, когда приложение Android работает в фоновом режиме. Есть ли полный учебник, чтобы объяснить это?
Запуск прослушивателя GPS в фоновом режиме на Android
Ответы (4)
Вам нужно использовать AlarmManager для активации ожидающего намерения (через широковещательный приемник) для запуска фоновой службы.
Пример кода для вас
В вашей основной активности
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
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();
}
}
}
Радиовещательный приемник
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);
}
}
Фоновая служба. Здесь вы заметите 2 важных момента
- WakeLock, чтобы ваше устройство просыпалось и использовало сеть в фоновом режиме.
- Хак для работы LocationManager. Мне пришлось отлаживать это около 2 недель, поверьте мне, вам это нужно. requestLocationUpdates и getLastKnownLocation просто не дадут ваше местоположение, когда вы этого захотите. Следовательно, AlarmManager (который работает намного лучше, чем java TimerTask).
Все это работает в рабочем приложении в магазине игр.
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
}
}
Наконец, не забывайте о своем манифесте.
<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>
Вам нужно использовать концепцию службы вместо активности. http://developer.android.com/guide/components/services.html
Вот хороший пример: Фоновой службе необходимо отправить местоположение GPS на сервер
То, что вы будете делать в Activity, можно сделать и в сервисе... в onStart() сервиса....
Вы можете использовать службу, которая всегда работает в фоновом режиме... и в фоновой службе вы можете получить текущую широту и долготу, и вы можете дополнительно преобразовать эти широты и долготы в правильное местоположение, используя класс геокодера Android... проверьте следующую ссылку :
http://www.codeproject.com/KB/android/GPSLocator.aspx