Я хотел бы разработать приложение для металлоискателя для Android, и для этого я использую магнитометр вместе с родным классом GeomagneticField. Это то, что я делаю:Получить местоположение пользователя на Android
- Извлеките значения x, y, z из магнитометра и вычислите магнитное поле при x^2 + y^2 + z^2.
- Рассчитайте геомагнитное поле, используя единственный конструктор, заданный классом GeomagneticField. Чтобы вычислить мои координаты, я использую менеджер местоположений и другие связанные с ним классы.
- Сравните эти магнитные поля, чтобы обнаружить металл.
Вот мой код:
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 (определяется пользователем) всегда возвращает нуль. Что я делаю неправильно?
Ваше решение работает. Однако каков правильный способ сравнить значения, полученные с помощью магнитометра с объектом GeomagneticField, для обнаружения металлов? – leqo
К сожалению, я плохо информирован в логике вашего процесса. В stackoverflow я нашел ответ на ваш вопрос: http://stackoverflow.com/questions/16371777/how-to-detect-a-metal-using-magnetic-sensor-in-android-phone. Насколько я понимаю, ошибка в методе getField(), чтобы определить magnitute. –