Обновления местоположения Android в службе

Я хочу сделать что-то вроде этого:

  • Когда мое приложение запускается, я хочу запустить службу, которая должна проверять мое местоположение

  • Когда приложение переходит в фоновый режим, я хочу остановить службу

У меня две основные проблемы:

  • Как я могу обнаружить, что мое приложение переходит в фоновый режим? Я выполняю несколько действий, и я попробовал это в моей MainActivity переопределить onPause, но onPause также вызывается, когда я запускаю другое действие.

  • Эта проблема важнее: как должна выглядеть моя Служба, которая проверяет мое местоположение? Я пробовал несколько подходов, но не добился успеха.

Моя служба выглядит так, и она не работает. Что я должен изменить, чтобы заставить его работать?

package com.pivoscore.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

public class LocationService extends Service {

    private LocationListener locationListener;

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        super.onStartCommand(intent, flags, startId);
        return Service.START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        this.locationListener = new MyLocationListener();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, this.locationListener);
    }

    private static class MyLocationListener implements LocationListener {

        @Override
        public void onLocationChanged(final Location location) {
        }

        @Override
        public void onProviderDisabled(final String provider) {
        }

        @Override
        public void onProviderEnabled(final String provider) {
        }

        @Override
        public void onStatusChanged(final String provider, final int status, final Bundle extras) {
        }

    }

}

Ответ 1

Это поможет исправить то, что ваше требование но не забудьте добавить разрешение, которое я добавил в комментарии а также не забудьте добавить тег службы в файл манифеста Код Snipet после

public class LocationService extends Service {
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;

Intent intent;
int counter = 0;

@Override
public void onCreate() {
    super.onCreate();
    intent = new Intent(BROADCAST_ACTION);      
}

@Override
public void onStart(Intent intent, int startId) {      
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    listener = new MyLocationListener();        
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it been more than two minutes since the current location, use the new location
    // because the user has likely moved
    if (isSignificantlyNewer) {
        return true;
    // If the new location is more than two minutes older, it must be worse
    } else if (isSignificantlyOlder) {
        return false;
    }

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
            currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
      return provider2 == null;
    }
    return provider1.equals(provider2);
}

@Override
public void onDestroy() {       
   // handler.removeCallbacks(sendUpdatesToUI);     
    super.onDestroy();
    Log.v("STOP_SERVICE", "DONE");
    locationManager.removeUpdates(listener);        
}   

public static Thread performOnBackgroundThread(final Runnable runnable) {
    final Thread t = new Thread() {
        @Override
        public void run() {
            try {
                runnable.run();
            } finally {

            }
        }
    };
    t.start();
    return t;
}


public class MyLocationListener implements LocationListener
{

    public void onLocationChanged(final Location loc)
    {
        Log.i("**************************************", "Location changed");
        if(isBetterLocation(loc, previousBestLocation)) {
            loc.getLatitude();
            loc.getLongitude();             
            intent.putExtra("Latitude", loc.getLatitude());
            intent.putExtra("Longitude", loc.getLongitude());     
            intent.putExtra("Provider", loc.getProvider());                 
            sendBroadcast(intent);          
            /*final Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());         
            String Text = "";
            try {
                List<Address> addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);                
                Text = "My current location is: "+addresses.get(0).getAddressLine(0); 

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Text = "My current location is: " +"Latitude = " + loc.getLatitude() + ", Longitude = " + loc.getLongitude();  
            }
            */
            //Toast.makeText( getApplicationContext(), "Location polled to server", Toast.LENGTH_SHORT).show();
        }                               
    }

    public void onProviderDisabled(String provider)
    {
        Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
    }


    public void onProviderEnabled(String provider)
    {
        Toast.makeText( getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
    }


    public void onStatusChanged(String provider, int status, Bundle extras)
    {

    }

}

Ответ 2

  • Приложение не является визуальным компонентом в Android. Он разделен на "Действия", каждый из которых запускается, когда видимый, приостановленный и уничтоженный в противном случае. Таким образом, нет концепции полного применения, которая будет использоваться в фоновом режиме, действия приостанавливаются и возобновляются на основе их индивидуальной видимости и полностью независимы от других действий в этом вопросе.

  • Ваша Служба зарегистрируется в Менеджере местоположений в своем onCreate(), отмените регистрацию с тем же в onDestroy(). В своем onBind() он должен вернуть объект Messenger. И в onLocationChanged() он должен отправить сообщение через свой общий Messenger. Не нужно использовать START_STICKY, так как вы не хотите, чтобы служба работала все время.

  • Активность (может быть любой деятельностью в приложении) просто нужно вызвать bindService() в своем onStart(), служба запустится, если она еще не была, и Activity получит Messenger из службы. Кроме того, Activity должен вызывать unbindService() из своего onStop(). Служба автоматически остановится, когда с ней ничего не связано.

  • Если вам нужно сделать материал в пункте 3 на уровне App (Task), внесите класс Application и используйте его onCreate() и onTerminate(). Класс приложения не приостанавливается и не останавливается, как Activity.

Ответ 3

Я предлагаю вам использовать новейшее местоположение api, предоставленное google (также совместимое с версией 2.2).

вот пример показывает, как это использовать: https://github.com/chenjishi/android_location_demo

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

Ответ 4

Попробуйте этот код.. Используя это, вы можете узнать, находится ли ваше приложение на переднем плане или на заднем плане. Надеюсь, что это поможет вам.

try {
    foreground = new ForegroundCheckTask().execute(ctx).get();
}

======================================


class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {

@Override
protected Boolean doInBackground(Context... params) {
    final Context context = params[0].getApplicationContext();
    return isAppOnForeground(context);
}

private boolean isAppOnForeground(Context context) {
    ActivityManager activityManager = (ActivityManager) context
            .getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> appProcesses = activityManager
            .getRunningAppProcesses();
    if (appProcesses == null) {
        return false;
    }
    final String packageName = context.getPackageName();


    String activePackageName = activityManager.getRunningTasks(1).get(0).topActivity.getPackageName();
    if (activePackageName.equals(packageName)) {
        return true;
    }
    else{
        return false;
    }


}

}

Ответ 5

Okey, моя первая проблема решена с использованием кода выше:

@Override
protected void onResume() {
    super.onResume();

    final Intent locationServiceIntent = new Intent(this, LocationService.class);
    this.startService(locationServiceIntent);
}

@Override
protected void onPause() {
    super.onPause();

    if (!Utils.isAppInForeground(this)) {
        final Intent locationServiceIntent = new Intent(this, LocationService.class);
        this.stopService(locationServiceIntent);
    }
}

Теперь, как я могу сделать свою работу LocationService?