2016-08-10 2 views
1

Je voudrais développer une application de détecteur de métaux pour Android et pour ce faire, j'utilise le magnétomètre à côté de la classe native GeomagneticField. Voici ce que je suis en train de faire:Obtenir l'emplacement de l'utilisateur sur Android

  1. Récupérer les valeurs x, y, z du magnétomètre et calculer le champ magnétique comme x^2 + y^2 + z^2.
  2. Calculez le champ géomagnétique en utilisant le seul constructeur donné par la classe GeomagneticField. Pour calculer mes coordonnées, j'utilise le gestionnaire de localisation et les autres classes qui s'y rapportent.
  3. Comparer les champs magnétiques pour détecter un métal.

Voici mon code:

public class MainActivity extends AppCompatActivity implements SensorEventListener, LocationListener { 

    SensorManager man; 
    Sensor sensor; 
    SensorEventListener thisActivity = this; 
    double earthField; 
    Location l; 
    LocationManager locationManager; 

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

     man = (SensorManager) getSystemService(SENSOR_SERVICE); 
     sensor = man.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 

     l = getLocation(); 
     if(l != null) 
     { 
      GeomagneticField gmf = new GeomagneticField((float) l.getLatitude(), 
        (float) l.getLongitude(), 
        (float) l.getAltitude(), 
        l.getTime()); 
      earthField = getEarthField(gmf); 
     } 
     else 
     { 
      ((TextView)findViewById(R.id.debug)).setText("l è nullo"); 
     } 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     man.unregisterListener(this); 
    } 

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

     man.registerListener(thisActivity, 
       sensor, 
       Sensor.TYPE_MAGNETIC_FIELD, 
       SensorManager.SENSOR_DELAY_NORMAL); 
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     float x = event.values[0]; 
     float y = event.values[1]; 
     float z = event.values[2]; 
     float magneticField = (float) getField(x, y, z); 

     ((TextView) findViewById(R.id.xreading)).setText("X: " + x + ""); 
     ((TextView) findViewById(R.id.yreading)).setText("Y: " + y + ""); 
     ((TextView) findViewById(R.id.zreading)).setText("Z: " + z + ""); 

     ((TextView) findViewById(R.id.earthTxt)).setText("Earth: " + earthField); 
     ((TextView) findViewById(R.id.fieldTxt)).setText("Calculated: " + magneticField); 

     // I'm not sure i have to repeat this step inside OnSensorChanged. 
     // Instructions inside the if statement are executed by onCreate, too. 
     if(l != null) 
     { 
      GeomagneticField gmf = new GeomagneticField((float) l.getLatitude(), 
        (float) l.getLongitude(), 
        (float) l.getAltitude(), 
        l.getTime()); 
      earthField = getEarthField(gmf); 
     } 


     TextView metalNearby = (TextView) findViewById(R.id.metalNearby); 

     if (magneticField > 1.4*earthField || magneticField < 0.6*earthField) { 
      //there is a high probability that some metal is close to the sensor 
      metalNearby.setText("Ho rilevato un metallo"); 
     } 
     else { 
      metalNearby.setText("Sto cercando..."); 
     } 
    } 

    private double getEarthField(GeomagneticField gmf) { 
     return getField(gmf.getX(), gmf.getY(), gmf.getZ()); 
    } 

    private double getField(float x, float y, float z) { 
     return Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2); 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { } 

    public Location getLocation() 
    { 
     Location location = null; 
     try 
     { 
      locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); 

      // Creating an empty criteria object 
      Criteria criteria = new Criteria(); 

      // Getting the name of the provider that meets the criteria 
      String provider = locationManager.getBestProvider(criteria, false); 

      try 
      { 
       location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
      } 
      catch (SecurityException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
     catch (Exception ex) 
     { 
      ex.printStackTrace(); 
     } 

     finally 
     { 
      return location; 
     } 
    } 

    @Override 
    public void onLocationChanged(Location location) 
    { 
     l = location; 
    } 

Mon problème est que la variable earthField évalue toujours à 0.0 et cela me fait penser la méthode getLocation (définie par l'utilisateur) renvoie toujours null. Qu'est-ce que je fais de mal?

Répondre

0

Si vous avez besoin nouvel emplacement chaque peu de temps ou tous les quelques voyagé mètres, essayez d'utiliser le code comme ça:

public void getLocation() { 
     try { 
      mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); 
      boolean isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 
      boolean isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 

      if (isNetworkEnabled) { 
       mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE, mLocationListener); 
      } 

      if (isGPSEnabled) { 
       mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, mLocationListener); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

MIN_TIME - cette fois-ci par le système recevra emplacement

MIN_DISTANCE - la même, seulement avec une distance

mLocationListener - votre écouteur où vous obtenez l'emplacement

+0

Votre solution fonctionne. Cependant, quelle est la bonne façon de comparer les valeurs obtenues à partir du magnétomètre avec l'objet GeomagneticField afin de détecter les métaux? – leqo

+0

Malheureusement, j'ai été mal informé dans la logique de votre processus. Sur stackoverflow j'ai trouvé la réponse à votre question: http://stackoverflow.com/questions/16371777/how-to-detect-a-metal-using-magnetic-sensor-in-android-phone. Si je comprends bien, une erreur dans votre méthode getField() pour déterminer magnat. –