Отправлять обновления местоположения в IntentService

Как можно отправлять обновления местоположения непосредственно в Intent Service? Следующий подход не работает. Вызывается функция OnConnected, но тогда это намерение никогда не принимается в службе:

...
    private PendingIntent getLocationPendingIntent(boolean shouldCreate) {
        Intent broadcast = new Intent(m_context,LocationUpdateService.class);
        int flags = shouldCreate ? 0 : PendingIntent.FLAG_NO_CREATE;
        return PendingIntent.getService(m_context, 0, broadcast, flags);
    }



    @Override
    public void onConnected(Bundle arg0) {
        PendingIntent locationPendingIntent = getLocationPendingIntent(true);        
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
        locationRequest.setFastestInterval(LOCATION_FASTEST_UPDATE_INTERVAL);
        LocationServices.FusedLocationApi.requestLocationUpdates(m_googleApiClient, locationRequest,locationPendingIntent);
}
...

Сервис Intent:

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class LocationUpdateService extends IntentService {

    public LocationUpdateService() {
        super(LocationUpdateService.class.getName());
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startID) {
        super.onStartCommand(intent, flags, startID);
        Log.d("LocationUpdateService","Location received");
        return START_REDELIVER_INTENT;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("LocationUpdateService","Intent received");

    }   
}

Файл манифеста:

...
<service  android:name=".LocationUpdateService" />
...

Ответ 1

Вот рабочий и проверенный код, который успешно устанавливает IntentService в качестве получателя для Intent, включенного в PendingIntent, используемого для обновлений местоположения, на основе найденного кода здесь.

Сначала IntentService:

import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.util.Log;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationResult;

public class LocationUpdateService extends IntentService {

    private final String TAG = "LocationUpdateService";
    Location location;

    public LocationUpdateService() {

        super("LocationUpdateService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (LocationResult.hasResult(intent)) {
            LocationResult locationResult = LocationResult.extractResult(intent);
            Location location = locationResult.getLastLocation();
            if (location != null) {
                 Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());
            }
        }
    }
}

И вот код операции, который регистрирует обновления местоположения с помощью PendingIntent, который отправляется в IntentService:

import android.app.PendingIntent;
import android.os.Bundle;
import android.content.Intent;
import android.app.Activity;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends Activity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    PendingIntent mRequestLocationUpdatesPendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buildGoogleApiClient();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause(){
        super.onPause();
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mRequestLocationUpdatesPendingIntent);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10);
        mLocationRequest.setFastestInterval(10);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        //mLocationRequest.setSmallestDisplacement(0.1F);

        // create the Intent to use WebViewActivity to handle results
        Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);

        // create a PendingIntent
        mRequestLocationUpdatesPendingIntent = PendingIntent.getService(getApplicationContext(), 0,
                mRequestLocationUpdatesIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        // request location updates
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest,
                mRequestLocationUpdatesPendingIntent);
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
    }
}

Результирующие журналы:

 D/locationtesting﹕ accuracy: 10.0 lat: 37.779702 lon: -122.3931595
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797023 lon: -122.3931594
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797022 lon: -122.3931596
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797021 lon: -122.3931597
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797021 lon: -122.3931596
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797019 lon: -122.3931597
 D/locationtesting﹕ accuracy: 10.0 lat: 37.7797019 lon: -122.3931597

Ответ 2

Интеллектуальные службы по своему характеру предназначены для терминальных задач, таких как получение намерения от вызова активности или фрагмента, запуск какой-либо задачи в отдельном потоке и завершение молча, без уведомления какой-либо организации о ее прекращении. Существует также документация с примечаниями о том, что onStartCommand не следует переопределять для Intent Services ([IntentService] [1]). Я предполагаю, что ваше обслуживание завершается, когда вы ожидаете, что оно будет живым, и поэтому намерение не доставлено должным образом.

Связанные службы будут более подходящим вариантом, поскольку они позволят различным компонентам подключаться к себе и выполнять требуемую связь.

Ответ 3

Вы не можете сделать это напрямую - я имею в виду requestLocationUpdates и получаю эти обновления в IntentService.

Что вы можете сделать, так это иметь Service в фоновом режиме, который запрашивает эти обновления через requestLocationUpdates и работает все время (помните о случае, когда устройство засыпает). Затем из этого Service, когда обновление местоположения было получено огнем в направлении IntentService и обрабатывать там.

Ответ 4

Вы можете использовать метод getService() для pendingIntent и в сервисе onStartCommand() вы можете получить соответствующее намерение. getBroadcast() отправляет широковещательную рассылку, для которой вам необходимо зарегистрировать широковещательный приемник для прослушивания. Надеюсь, это поможет.