Je construis une application qui doit envoyer l'emplacement de l'utilisateur à un serveur distant (Pusher dans ce cas). L'objectif est de mettre à jour leur emplacement sur une carte en temps quasi réel, mais seulement quand ils sont sur un travail, sinon l'application n'aura pas besoin de suivre leur emplacement.android - Obtenir l'emplacement et envoyer des données au serveur distant seulement lorsque la condition est vraie
J'ai besoin des mises à jour de localisation pour rester actives si elles quittent l'activité où elles ont accepté le travail (et ont donc été placées sur la carte) et si elles quittent complètement l'application. Une fois qu'ils ont atteint leur destination, je souhaite arrêter ce suivi en arrière-plan.
J'ai regardé le composant Service
d'Android mais je ne suis pas sûr si c'est ce dont j'ai besoin pour cela. Les mises à jour doivent se produire en arrière-plan indéfiniment, mais uniquement lorsque l'utilisateur est affecté à un Job (les mises à jour démarrent lorsqu'elles acceptent un travail, et se terminent lorsqu'elles atteignent leur destination).
Un service lié serait-il le meilleur pour cela? Si oui, un certain code en ce qui concerne ce problème serait GRANDEMENT apprécié, autant de ce que je peux trouver est générique et fait des choses comme retourner des nombres entiers aléatoires.
Voici le code que je veux exécuter en arrière-plan:
package com.example.locationtester;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.pusher.client.Pusher;
import com.pusher.client.PusherOptions;
import com.pusher.client.channel.PrivateChannel;
import com.pusher.client.channel.PrivateChannelEventListener;
import com.pusher.client.connection.ConnectionEventListener;
import com.pusher.client.connection.ConnectionState;
import com.pusher.client.connection.ConnectionStateChange;
import com.pusher.client.util.HttpAuthorizer;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
private TextView mLatLabel;
private TextView mLongLabel;
private TextView mAccuracy;
private Double mLat;
private Double mLong;
private boolean isSubscribed = false;
private Pusher mPusher;
private PrivateChannel mChannel;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60;
private static final String TAG = "GPSTest";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLatLabel = (TextView) findViewById(R.id.latLabel);
mLongLabel = (TextView) findViewById(R.id.longLabel);
mAccuracy = (TextView) findViewById(R.id.accuracyLabel);
HttpAuthorizer authorizer = new HttpAuthorizer("http://example.com");
PusherOptions options = new PusherOptions().setAuthorizer(authorizer).setEncrypted(true);
mPusher = new Pusher("PUSHER_API_KEY", options);
mPusher.connect(new ConnectionEventListener() {
@Override
public void onConnectionStateChange(ConnectionStateChange change) {
Log.d(TAG, "State changed to " + change.getCurrentState() +
" from " + change.getPreviousState());
}
@Override
public void onError(String message, String code, Exception e) {
Log.d(TAG, "There was a problem connecting! " + e.toString());
}
}, ConnectionState.ALL);
mChannel = mPusher.subscribePrivate("private-location", new PrivateChannelEventListener() {
@Override
public void onAuthenticationFailure(String message, Exception e) {
Log.e(TAG, "Error " + message);
}
@Override
public void onSubscriptionSucceeded(String channelName) {
Log.d(TAG, "Subscribed to " + channelName);
isSubscribed = true;
}
@Override
public void onEvent(String channelName, String eventName, String data) {
}
});
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
handleLocationUpdate(location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Toast.makeText(getApplicationContext(), "GPS Status Changed " + provider, Toast.LENGTH_LONG).show();
}
@Override
public void onProviderEnabled(String provider) {
Toast.makeText(getApplicationContext(), "GPS Provider Enabled " + provider, Toast.LENGTH_LONG).show();
}
@Override
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, 0, locationListener);
}
private void handleLocationUpdate(Location location) {
mLat = location.getLatitude();
mLong = location.getLongitude();
mLatLabel.setText("Long: " + location.getLongitude());
mLongLabel.setText("Lat: " + location.getLatitude());
mAccuracy.setText("Accuracy: " + location.getAccuracy() + " at " + location.getTime());
Log.d(TAG, mLat + "");
if (isSubscribed)
{
JSONObject json = new JSONObject();
try {
json.put("lat", mLat);
json.put("long", mLong);
json.put("time", location.getTime());
json.put("accuracy", location.getAccuracy());
mChannel.trigger("client-location-changed", json.toString());
} catch (JSONException e) {
Log.e(TAG, "Problem adding JSON");
}
}
}
}
MISE À JOUR
C'est ce que je suis venu avec après le passage à Google Play API de localisation de service. J'ai testé en laissant cette activité (et l'application en général) et tout continue à fonctionner correctement, prouvant les mises à jour de localisation jusqu'à ce que je clique sur le bouton pour les faire arrêter.
commentaires seraient appréciés sur ce code:
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
public static final String TAG = MainActivity.class.getSimpleName();
public static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private boolean isSubscribed = false;
private Pusher mPusher;
private PrivateChannel mChannel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startTracking = (Button) findViewById(R.id.btnStartTracking);
Button stopTracking = (Button) findViewById(R.id.btnStopTracking);
final Button startActivity = (Button) findViewById(R.id.btnStartActivity);
HttpAuthorizer authorizer = new HttpAuthorizer("http://example.com");
PusherOptions options = new PusherOptions().setAuthorizer(authorizer).setEncrypted(true);
mPusher = new Pusher("API_KEY", options);
mPusher.connect(new ConnectionEventListener() {
@Override
public void onConnectionStateChange(ConnectionStateChange change) {
Log.d(TAG, "State changed to " + change.getCurrentState() +
" from " + change.getPreviousState());
}
@Override
public void onError(String message, String code, Exception e) {
Log.d(TAG, "There was a problem connecting! " + e.toString());
}
}, ConnectionState.ALL);
mChannel = mPusher.subscribePrivate("private-location", new PrivateChannelEventListener() {
@Override
public void onAuthenticationFailure(String message, Exception e) {
Log.e(TAG, "Error " + message);
}
@Override
public void onSubscriptionSucceeded(String channelName) {
Log.d(TAG, "Subscribed to " + channelName);
isSubscribed = true;
}
@Override
public void onEvent(String channelName, String eventName, String data) {
}
});
// Build the Google Api Client and set the API for LocationServices
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(20 * 1000) // 3 seconds, in MS
.setFastestInterval(1000); // 1 second, in MS
startTracking.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mGoogleApiClient.isConnected())
{
mGoogleApiClient.connect();
}
}
});
stopTracking.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mGoogleApiClient.isConnected())
{
mGoogleApiClient.disconnect();
}
}
});
startActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), Activity2.class);
startActivity(intent);
}
});
}
@Override
protected void onResume()
{
super.onResume();
if (!mGoogleApiClient.isConnected())
{
mGoogleApiClient.connect();
}
}
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Location services connected");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
int speed = (int) (location.getSpeed() * 2.2369);
if (isSubscribed) {
JSONObject json = new JSONObject();
try {
json.put("lat", currentLatitude);
json.put("long", currentLongitude);
json.put("time", location.getTime());
json.put("accuracy", location.getAccuracy());
json.put("speed", speed);
json.put("latLng", latLng);
mChannel.trigger("client-location-changed", json.toString());
} catch (JSONException e) {
Log.e(TAG, "Problem adding JSON");
}
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect");
}
@Override
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
}
commencer une nouvelle activité qui peut fonctionner dans le sol en arrière quand un nouvel emploi est attribué et mis ce Coode dans cette activité –
"Une nouvelle activité qui peut fonctionner en arrière-plan" - ne serait-ce pas un "Service"? – NightMICU
ouais mais les services qui durent longtemps peuvent être tués vous devez faire attention à de tels résultats –