1

長年前、私はデバイスの位置を知る必要があるAndroidアプリケーションをプログラミングしました。デバイスの場所へのアクセスを抽象化する目的で、すべてのロケーション関連のものを管理するクラスをプログラミングし、現在のデバイスのロケーションを保存し、ユーザーに通知するためにGPSまたはインターネットのステータスが変化したときにメインアクティビティを呼び出します。GPSがロリポップを除くすべてのデバイスで動作しています

このアプリケーションは、Lollipopに付属のSamsung Galaxy A5 2016を購入するまで、すべてのデバイスで動作し続けています。それは私がそれをテストしたすべてのJellybeanデバイスで動作しますが、古いAndroidバージョンで動作しますが、A5 2016ではGPSステータスの変更が通知されますが、onLocationChanged()メソッドは動作してはいけません。 。場所を取得するためのこのクラスがすべての端末で動作していて、Lollipopで動作しなくなった理由を教えてください。本当にイライラしています。 Androidアプリケーションは、前方互換性があると考えられています。 場所を管理し、Lollipopでの作業を停止したクラスのコードは次のとおりです。 Lollipopの前には、タイプがLocationのクラスのインスタンス属性に格納されていましたが、Lollipopから始めると、その場所はもう保存されません。

package bembibre.personlocator.logic.locationservices; 

import android.content.Context; 
import android.location.GpsStatus; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.location.LocationProvider; 
import android.os.Bundle; 
import android.os.SystemClock; 
import bembibre.personlocator.activities.MainActivity; 
import bembibre.personlocator.logic.Action; 
import bembibre.personlocator.logic.internet.InternetManager; 

/** 
* Clase singleton que permite averiguar la localización del usuario en cada 
* momento. 
* 
* @author misines 
* 
*/ 
public class MyLocationManager { 

    /** 
    * Única instancia que puede existir de este objeto (es un singleton). 
    */ 
    private static MyLocationManager instance = new MyLocationManager(); 

    private static int GPS_INTERVAL = 3000; 

    /** 
    * Actividad que llama a este objeto y que necesita conocer la localización 
    * del usuario. 
    */ 
    private MainActivity activity; 

    /** 
    * Objeto de Android que permite acceder a la localización del usuario. 
    */ 
    private LocationManager locationManager; 

    /** 
    * Objeto que se encarga de escuchar cambios de localización basada en red. 
    */ 
    private LocationListener networkLocationListener; 

    /** 
    * Objeto que se encarga de escuchar cambios de localización basada en GPS. 
    */ 
    private LocationListener gpsLocationListener; 

    private int networkStatus = LocationProvider.OUT_OF_SERVICE; 

    private int gpsStatus = LocationProvider.OUT_OF_SERVICE; 

    private EnumGpsStatuses status = EnumGpsStatuses.BAD; 

    /** 
    * Este atributo contiene la última localización del usuario determinada 
    * por red (no muy exacta) o <code>null</code> si no se ha podido 
    * determinar (por ejemplo porque no hay Internet). 
    */ 
    private Location networkLocation; 

    /** 
    * Este atributo contiene la última localización del usuario determinada 
    * por GPS (es más exacta que por red) o <code>null</code> si no se ha 
    * podido determinar (por ejemplo porque no está activado el GPS). 
    */ 
    private Location gpsLocation; 
    private Long gpsLastLocationMillis; 

    private boolean networkProviderEnabled = false; 



    public static MyLocationManager getInstance() { 
     return MyLocationManager.instance; 
    } 

    private void setNetworkLocation(Location location) { 
     this.networkLocation = location; 
    } 

    private void setGpsLocation(Location location) { 
     this.gpsLocation = location; 
    } 

    /** 
    * Método que es llamado cuando el estado de alguno de los proveedores de 
    * localización de los que depende esta clase ha cambiado de estado. 
    */ 
    private void onStatusChanged() { 
     switch(this.gpsStatus) { 
     case LocationProvider.AVAILABLE: 
      this.status = EnumGpsStatuses.GOOD; 
      break; 
     case LocationProvider.OUT_OF_SERVICE: 
     case LocationProvider.TEMPORARILY_UNAVAILABLE: 
     default: 
      switch(this.networkStatus) { 
      case LocationProvider.AVAILABLE: 
       this.status = EnumGpsStatuses.SO_SO; 
       break; 
      case LocationProvider.OUT_OF_SERVICE: 
      case LocationProvider.TEMPORARILY_UNAVAILABLE: 
      default: 
       this.status = EnumGpsStatuses.BAD; 
      } 
     } 

     if (this.activity != null) { 
      this.activity.onGpsStatusChanged(this.status); 
     } 
    } 

    private void setNetworkStatus(int status) { 
     this.networkStatus = status; 
     this.onStatusChanged(); 
    } 

    private void setGpsStatus(int status) { 
     this.gpsStatus = status; 
     this.onStatusChanged(); 
    } 

    private class MyGPSListener implements GpsStatus.Listener { 
     public void onGpsStatusChanged(int event) { 
      boolean isGPSFix; 
      switch (event) { 
       case GpsStatus.GPS_EVENT_SATELLITE_STATUS: 
        if (MyLocationManager.this.gpsLastLocationMillis != null) { 
         isGPSFix = (SystemClock.elapsedRealtime() - MyLocationManager.this.gpsLastLocationMillis) < 3 * MyLocationManager.GPS_INTERVAL; 
        } else { 
         isGPSFix = false; 
        } 

        if (isGPSFix) { // A fix has been acquired. 
         MyLocationManager.this.setGpsStatus(LocationProvider.AVAILABLE); 
        } else { // The fix has been lost. 
         MyLocationManager.this.setGpsStatus(LocationProvider.OUT_OF_SERVICE); 
        } 

        break; 
       case GpsStatus.GPS_EVENT_FIRST_FIX: 
        // Do something. 
        MyLocationManager.this.setGpsStatus(LocationProvider.AVAILABLE); 

        break; 
      } 
     } 
    } 

    /** 
    * Inicializa este objeto para que empiece a funcionar y trate de 
    * determinar la localización del dispositivo. Además inicializa al 
    * <code>InternetManager</code>, de modo que una vez que se haya llamado a 
    * este método, InternetManager estará disponible en todo momento para ver 
    * si la conexión a Internet funciona o hacer pruebas a dicha conexión. 
    * 
    * @param activity 
    */ 
    public void start(final MainActivity activity) { 
     this.activity = activity; 

     // Acquire a reference to the system Location Manager 
     this.locationManager = (LocationManager) this.activity.getSystemService(Context.LOCATION_SERVICE); 

     // Define a listener that responds to location updates 
     this.networkLocationListener = new LocationListener() { 
      public void onLocationChanged(Location location) { 
       // Called when a new location is found by the network location 
       // provider. 
       MyLocationManager.this.setNetworkLocation(location); 
       MyLocationManager.this.networkProviderEnabled = true; 
       InternetManager.getInstance().makeInternetTest(activity); 
      } 

      public void onStatusChanged(String provider, int status, Bundle extras) { 
       MyLocationManager.this.setNetworkStatus(status); 
      } 

      public void onProviderEnabled(String provider) { 
       MyLocationManager.this.networkProviderEnabled = true; 
       InternetManager.getInstance().makeInternetTest(activity); 
      } 

      public void onProviderDisabled(String provider) { 
       MyLocationManager.this.networkProviderEnabled = false; 
       MyLocationManager.this.setNetworkStatus(LocationProvider.OUT_OF_SERVICE); 
      } 
     }; 

     this.gpsLocationListener = new LocationListener() { 
      public void onLocationChanged(Location location) { 
       // Called when a new location is found by the network location 
       // provider. 
       MyLocationManager.this.setGpsLocation(location); 
       MyLocationManager.this.gpsLastLocationMillis = SystemClock.elapsedRealtime(); 
       //MyLocationManager.this.setGpsStatus(LocationProvider.AVAILABLE); 
      } 

      public void onStatusChanged(String provider, int status, Bundle extras) { 
       MyLocationManager.this.setGpsStatus(status); 
      } 

      public void onProviderEnabled(String provider) { 

      } 

      public void onProviderDisabled(String provider) { 
       MyLocationManager.this.setGpsStatus(LocationProvider.OUT_OF_SERVICE); 
      } 
     }; 

     // Register the listener with the Location Manager to receive location 
     // updates 
     try { 
      this.locationManager.requestLocationUpdates(
       LocationManager.NETWORK_PROVIDER, 3000, 0, this.networkLocationListener 
      ); 

      this.locationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER, GPS_INTERVAL, 0, this.gpsLocationListener 
      ); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     this.locationManager.addGpsStatusListener(new MyGPSListener()); 



     /* 
     * Hay que inicializar al InternetManager y decirle que avise a este 
     * objeto cada vez que el Internet vuelva o se pierda. Para ello usamos 
     * dos objetos Action. 
     */ 
     Action action1 = new Action() { 

      @Override 
      public void execute(String string) { 
       MyLocationManager.getInstance().internetHasBeenRecovered(); 
      } 

     }; 
     Action action2 = new Action() { 

      @Override 
      public void execute(String string) { 
       MyLocationManager.getInstance().internetHasBeenLost(); 
      } 

     }; 
     InternetManager.getInstance().initialize(activity, action1, action2); 
    } 

    public void stop() { 
     if (this.locationManager != null) { 
      if (this.networkLocationListener != null) { 
       this.locationManager.removeUpdates(this.networkLocationListener); 
      } 
      if (this.gpsLocationListener != null) { 
       this.locationManager.removeUpdates(this.gpsLocationListener); 
      } 
     } 

     this.activity = null; 
    } 

    /** 
    * Devuelve la última localización conocida basada en red o 
    * <code>null</code> si no hay. 
    * 
    * @return la última localización conocida basada en red o 
    * <code>null</code> si no hay. 
    */ 
    public Location getNetworkLocation() { 
     Location result; 

     if (this.networkLocation == null) { 
      result = this.gpsLocation; 
     } else { 
      result = this.networkLocation; 
     } 

     return result; 
    } 

    /** 
    * Si el gps está disponible y tenemos una posición guaradada basada en GPS 
    * entonces la devuelve. En caso contrario intenta devolver la última 
    * localización basada en red, y si tampoco está disponible, devuelve 
    * <code>null</code>. 
    * 
    * @return la localización más precisa que esté disponible en este momento. 
    */ 
    public Location getFinestLocationAvailable() { 
     Location result; 

     switch(this.gpsStatus) { 
     case LocationProvider.AVAILABLE: 
      if (this.gpsLocation == null) { 
       result = this.networkLocation; 
      } else { 
       result = this.gpsLocation; 
      } 
     case LocationProvider.TEMPORARILY_UNAVAILABLE: 
     case LocationProvider.OUT_OF_SERVICE: 
     default: 
      result = this.networkLocation; 
     } 

     return result; 
    } 

    /** 
    * Devuelve el estado actual del GPS. 
    * 
    * @return el estado actual del GPS. 
    */ 
    public EnumGpsStatuses getStatus() { 
     return this.status; 
    } 

    /** 
    * Método al que tenemos que llamar siempre que nos enteremos de que 
    * tenemos Internet, para que se sepa que la localización por red funciona. 
    */ 
    public void internetHasBeenRecovered() { 
     if (this.networkProviderEnabled) { 
      this.setNetworkStatus(LocationProvider.AVAILABLE); 
     } else { 
      this.setNetworkStatus(LocationProvider.OUT_OF_SERVICE); 
     } 
     this.onStatusChanged(); 
    } 

    /** 
    * Método al que tenemos que llamar siempre que nos enteremos de que la 
    * conexión a Internet se ha perdido, para que este objeto se dé cuenta de 
    * que el servicio de localización por red ya no funciona. 
    */ 
    public void internetHasBeenLost() { 
     this.setNetworkStatus(LocationProvider.OUT_OF_SERVICE); 
     this.onStatusChanged(); 
    } 
} 

答えて

0

次のコードで試してみてください:あなたが既に知っている

public class MyLocationService extends Service{ 

    Location mLastLocation; 
    android.location.LocationListener mLocationListener; 
    LocationManager locationManager; 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     super.onStartCommand(intent, flags, startId); 

     // Acquire a reference to the system Location Manager 
     locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 

     // Define a listener that responds to location updates 
     mLocationListener = new android.location.LocationListener() { 
      @Override 
      public void onLocationChanged(Location location) { 
       // Called when a new location is found by the gps location provider. 

       mLastLocation = location; // this is the object you need to play with Location changes 

       // do stuffs here you want after location changes 
      } 

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

      @Override 
      public void onProviderEnabled(String provider) {} 

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

     String locationProvider = LocationManager.GPS_PROVIDER; // here, you can also set Network provider as per your need 

     // Register the listener with the Location Manager to receive location updates 
     try{ 
      locationManager.requestLocationUpdates(locationProvider, 5000, 0, mLocationListener); 
      mLastLocation = locationManager.getLastKnownLocation(locationProvider); 
     } catch (SecurityException e){ 
      e.printStackTrace(); 
     } 

     return START_STICKY; 
    } 
} 

し、必要なマニフェスト許可:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

そして、次のように最終的にあなたのサービスはマニフェストで宣言されるはずです:

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

ActivityまたはApplicationクラスからサービスを開始する必要があります。

+0

ありがとうございます。私は知っておく必要があります。コードと鉱山の違いは何ですか?また、なぜ私のLollipopだけが動作しないのですか?私のコードはあなたのものと似ていて、私のonLocationChanged()メソッドは呼び出されていないと思います。ユーザーはアプリケーションを使用しているときにのみ場所を知りたいので、サービスを作成する必要はありません。 – user3289695

+0

私はgpsプロバイダーとネットワークプロバイダーを同時に使用していると思います.GPSプロバイダーはモバイルにインターネット接続がある場合にのみ使用し、そうでない場合はネットワークプロバイダーを使用してください。あなたの 'try {}'ブロックで 'if {} {} else {}'を使ってみてください。ハッピーコーディング:) – zeeali

+0

私のアプリケーションが再び動作するようになり、コードを変更しませんでした。私は何が起こっているのか分からない。おそらく私のデバイスが誤って構成されていたでしょうか?私は位置の設定を入力し、そこにいくつかのオプションがあった:GPSとネットワークを使用し、GPSだけを使用し、ネットワークのみを使用...それは非常に奇妙です。選択したオプションを変更して位置をオフにしてからオンにすると、選択したものがデバイスに記憶されず、前に選択したオプションに戻ります。 – user3289695

関連する問題