2016-08-10 4 views
1

Я хотел бы разработать приложение для металлоискателя для Android, и для этого я использую магнитометр вместе с родным классом GeomagneticField. Это то, что я делаю:Получить местоположение пользователя на Android

  1. Извлеките значения x, y, z из магнитометра и вычислите магнитное поле при x^2 + y^2 + z^2.
  2. Рассчитайте геомагнитное поле, используя единственный конструктор, заданный классом GeomagneticField. Чтобы вычислить мои координаты, я использую менеджер местоположений и другие связанные с ним классы.
  3. Сравните эти магнитные поля, чтобы обнаружить металл.

Вот мой код:

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; 
    } 

Моя проблема заключается в том, что переменная earthField всегда имеет значение 0.0, и это заставляет меня думать, что метод getLocation (определяется пользователем) всегда возвращает нуль. Что я делаю неправильно?

ответ

0

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

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 - на этот раз через, как система получат место,

MIN_DISTANCE - такой же, только на расстоянии

mLocationListener - ваш слушатель, где вы находите место

+0

Ваше решение работает. Однако каков правильный способ сравнить значения, полученные с помощью магнитометра с объектом GeomagneticField, для обнаружения металлов? – leqo

+0

К сожалению, я плохо информирован в логике вашего процесса. В stackoverflow я нашел ответ на ваш вопрос: http://stackoverflow.com/questions/16371777/how-to-detect-a-metal-using-magnetic-sensor-in-android-phone. Насколько я понимаю, ошибка в методе getField(), чтобы определить magnitute. –

Смежные вопросы