在Android上获取用户位置

时间:2016-08-10 12:49:23

标签: android geolocation magnetometer

我想开发一款适用于Android的金属探测器应用程序,并且我会使用磁力计和GeomagneticField本机类一起使用。这就是我正在做的事情:

  1. 从磁力计中检索x,y,z值并将磁场计算为x ^ 2 + y ^ 2 + z ^ 2.
  2. 使用GeomagneticField类给出的唯一构造函数计算地磁场。要使用位置管理器和与之相关的其他类来计算我的坐标。
  3. 比较这些磁场以检测金属。
  4. 这是我的代码:

    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(用户定义)总是返回null。 我做错了什么?

1 个答案:

答案 0 :(得分: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 - 您获取位置的侦听器