Android GPS定位(获取经纬度)

来源:互联网 发布:新加坡旅游消费知乎 编辑:程序博客网 时间:2024/05/17 04:48

简述:

    android 定位一般有四种方法,这四种方式分别是:GPS定位,WIFI定位,基站定位,AGPS定位。

本篇博文主要记录一下GPS定位:这种方式需要手机支持GPS模块硬件支持。通过GPS方式准确度是最高的,但是它的缺点也非常明显:

                    1、比较耗电;

                    2、绝大部分用户默认不开启GPS模块;

                    3、从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;

                    4、室内几乎无法使用。

这其中,缺点2,3都是比较致命的。

GPS定位优点:GPS走的是卫星通信的通道,在没有网络连接的情况下也能使用。

GPS定位:

    相关类

        (1)、LocationManager:位置服务管理器类
是获取位置信息的入口级类,要获取位置信息,首先需要获取一个LocationManger对象:
                  

 LocationManager  pLocationManager = (LocationManager) Context.getSystemService(Context.LOCATION_SERVICE);
        (2)、LocationProvider:位置源提供者
用于描述位置提供者信息,可以先使用方法获取最佳提供者的名称:

String providerName = LocationManger.getBestProvider(Criteria criteria, boolean enabledOnly);

                         LocationManger.getProvider(String name)获取LocationProvider对象。

        (3)、Location:位置对象
                        描述地理位置信息的类,记录了经纬度、海拔高度、获取坐标时间、速度、方位等。可以通过LocationManager.getLastKnowLocation(provider)获取位置坐标,provider就是上文中提到的GPS_PROVIDER、NETWORK_PROVIDER、PASSIVE_PROVIDER、FUSED_PROVIDER;不过很多时候得到的Location对象为null;实时动态坐标可以在监听器locationListener的onLocationChanged(Location location)方法中来获取。

        (4)、LocationListener:位置监听接口
用于监听位置(包括GPS、网络、基站等所有提供位置的)变化,监听设备开关与状态。实时动态获取位置信息,首先要实现该接口,在相关方法中添加实现功能的代码,实现该接口可以使用内部类或者匿名实现。然后注册监听:LocationManger.requestLocationUpdates(Stringprovider, long minTime, float minDistance, LocationListener listener)。使用完之后需要在适当的位置移除监听:LocationManager .removeUpdates(LocationListener listener)。LocationListener需要实现的方法:
onLocationChanged(Locationlocation):当位置发生变化的时候会自动调用该方法,参数location记录了最新的位置信息。
onStatusChanged(String provider, int status, Bundle extras):当位置提供者的状态发生改变(可用到不可用、不可用到可用)时自动调用该方法;参数provider为位置提供者的名称,status为状态信息:OUT_OF_SERVICE 、AVAILABLE 、TEMPORARILY_UNAVAILABLE ,extras为附加数据:key/value,如satellites;
onProviderEnabled(String provider):位置信息提供者可用时自动调用,比如用户关闭了GPS时,provider则为“gps”;
onProviderDisabled(String provider):位置信息不可用时自动调用。

        (5)、Criteria:用于选择位置信息提供者的辅助类
创建LocationProvider对象时会使用到该类,参考上文中内容。定位信息提供者会根据精度、电量、是否提供高度、速度、方位、服务商付费等信息进行排序选择定位提供者。 可以参考一个示例:

  /** this criteria needs high accuracy, high power and cost */   public static Criteria createFineCriteria() {       Criteriac = new Criteria();      c.setAccuracy(Criteria.ACCURACY_FINE);//高精度      c.setAltitudeRequired(true);//包含高度信息      c.setBearingRequired(true);//包含方位信息      c.setSpeedRequired(true);//包含速度信息      c.setCostAllowed(true);//允许付费      c.setPowerRequirement(Criteria.POWER_HIGH);//高耗电      return c;   }
         (6)、GpsStatus.Listener:GPS状态监听的一个接口

                       使用方法与locationListener接口类似,先实现接口并创建对象,实现接口中的方法:onGpsStatusChanged(int event);在方法中实现对卫星状态信息变化的监听,根据event的类型编写逻辑代码。创建对象后再注册监听:LocationManager .addGpsStatusListener(GpsStatus.Listener listener);使用后在合适的位置释放监听:LocationManager .removeGpsStatusListener(GpsStatus.Listener listener)。

    GPS定位流程

          (1)配置权限:

                添加如下权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission..ACCESS_FINE_LOCATION" />
  (2)获取LocationManager类型对象:     

LocationManager mLocationManager =(LocationManager) mContext.getSystemService (Context.LOCATION_SERVICE); 
             (3) 获取最佳位置定位方式pProvider:(这步可有可无,根据情况而定)

       mLocationManager.getBestProvider(mCriteria,true); mCriteria为Criteria类型的对象,包含精度、是否返回高度、方位、速度等信息。创建Criteria对象示例:

/** this criteria needs highaccuracy, high power, and cost */   public static CriteriacreateFineCriteria() {       Criteriac = new Criteria();      c.setAccuracy(Criteria.ACCURACY_FINE);//高精度      c.setAltitudeRequired(true);//包含高度信息      c.setBearingRequired(true);//包含方位信息      c.setSpeedRequired(true);//包含速度信息      c.setCostAllowed(true);//允许付费      c.setPowerRequirement(Criteria.POWER_HIGH);//高耗电      return c;   }
     (4) 实现LocationListener接口:可以采用内部类(MyLocationListener)或匿名类方式实现,重写接口方法.

             (5) 创建MyLocationListener对象mLocationListener,并添加监听:

mLocationListener =new MyLocationListener();mLocationManager.requestLocationUpdates(pProvider, MIN_TIME_UPDATE,MIN_DISTANCE_UPDATE, mLocationListener);
             (6) 使用完释放监听:

mLocationManager.removeUpdates(mLocationListener);
该方法执行的位置需要特别注意,如果是在Activity对象中,则需要考虑Activity的生命周期,onPause方法中比较合适,因为onStop、onDestroy两个方法在异常情况下不会被执行。
              (7) 如果需要监听GPS卫星状态,则需要实现GpsStatus.Listener接口,并创建对象、添加监听、使用完后释放监听:

                   实现接口:

private class MyGpsStatusListener implements GpsStatus.Listener;
                   创建对象:

MyGpsStatusListener mGpsStatusListener = new MyGpsStatusListener();

                   添加监听:

mLocationManager.addGpsStatusListener (mGpsStatusListener;

                   释放监听:      

mLocationManager.removeGpsStatusListener(mGpsStatusListener);

    案例实现:

全部代码贴出来:

package com.lzy.gpslocation;import android.Manifest;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.location.Criteria;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.location.LocationProvider;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.fastaccess.permission.base.PermissionHelper;import com.fastaccess.permission.base.callback.OnPermissionCallback;import java.util.Arrays;public class MainActivity extends AppCompatActivity implements OnPermissionCallback {    private static final String TAG = MainActivity.class.getSimpleName();    private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER;    private static final int REQUEST_PRESSMION_CODE = 10000;    private final static String[] MULTI_PERMISSIONS = new String[]{            Manifest.permission.ACCESS_COARSE_LOCATION,            Manifest.permission.ACCESS_FINE_LOCATION};    private LocationManager locationManager;    private boolean isGpsEnabled;    private String locateType;    private TextView textLocationShow;    private Button btnLocation;    //权限检测类    private PermissionHelper mPermissionHelper;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();        initViews();    }    /**     * 方法描述:初始化定位相关数据     */    private void initData() {        //获取定位服务        locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);        //判断是否开启GPS定位功能        isGpsEnabled = locationManager.isProviderEnabled(GPS_LOCATION_NAME);        //定位类型:GPS        locateType = locationManager.GPS_PROVIDER;        //初始化PermissionHelper        mPermissionHelper = PermissionHelper.getInstance(MainActivity.this);    }    /**     * 方法描述:初始化View组件信息及相关点击事件     */    private void initViews() {        textLocationShow = (TextView) findViewById(R.id.text_location_show);        btnLocation = (Button) findViewById(R.id.btn_location);        btnLocation.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                getLocation();            }        });        ((Button)findViewById(R.id.btn_skip)).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this,ThirdActivity.class);                startActivity(intent);            }        });    }    private void getLocation() {        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)                != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission                (MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)                != PackageManager.PERMISSION_GRANTED) {            mPermissionHelper.request(MULTI_PERMISSIONS);            return;        }        Location location = locationManager.getLastKnownLocation(locateType); // 通过GPS获取位置        if (location != null) {            updateUI(location);        }        // 设置监听*器,自动更新的最小时间为间隔N秒(1秒为1*1000,这样写主要为了方便)或最小位移变化超过N米        locationManager.requestLocationUpdates(locateType, 100,0,                locationListener);    }    private LocationListener locationListener = new LocationListener() {        /**         * 位置信息变化时触发:当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发         * @param location         */        @Override        public void onLocationChanged(Location location) {            Toast.makeText(MainActivity.this, "onLocationChanged函数被触发!", Toast.LENGTH_SHORT).show();            updateUI(location);            Log.i(TAG, "时间:" + location.getTime());            Log.i(TAG, "经度:" + location.getLongitude());            Log.i(TAG, "纬度:" + location.getLatitude());            Log.i(TAG, "海拔:" + location.getAltitude());        }        /**         * GPS状态变化时触发:Provider被disable时触发此函数,比如GPS被关闭         * @param provider         * @param status         * @param extras         */        @Override        public void onStatusChanged(String provider, int status, Bundle extras) {            switch (status) {                //GPS状态为可见时                case LocationProvider.AVAILABLE:                    Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为可见状态", Toast.LENGTH_SHORT).show();                    break;                //GPS状态为服务区外时                case LocationProvider.OUT_OF_SERVICE:                    Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为服务区外状态", Toast.LENGTH_SHORT).show();                    break;                //GPS状态为暂停服务时                case LocationProvider.TEMPORARILY_UNAVAILABLE:                    Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为暂停服务状态", Toast.LENGTH_SHORT).show();                    break;            }        }        /**         * 方法描述:GPS开启时触发         * @param provider         */        @Override        public void onProviderEnabled(String provider) {            Toast.makeText(MainActivity.this, "onProviderEnabled:方法被触发", Toast.LENGTH_SHORT).show();            getLocation();        }        /**         * 方法描述: GPS禁用时触发         * @param provider         */        @Override        public void onProviderDisabled(String provider) {        }    };    /**     * 方法描述:在View上更新位置信息的显示     *     * @param location     */    private void updateUI(Location location) {        double longitude = location.getLongitude();        double latitude = location.getLatitude();        textLocationShow.setText("当前经度:" + longitude + "\n当前纬度:" + latitude);    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        mPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        mPermissionHelper.onActivityForResult(requestCode);    }    @Override    public void onPermissionGranted(@NonNull String[] permissionName) {        getLocation();        Log.i("onPermissionGranted", "Permission(s) " + Arrays.toString(permissionName) + " Granted");    }    @Override    public void onPermissionDeclined(@NonNull String[] permissionName) {    }    @Override    public void onPermissionPreGranted(@NonNull String permissionsName) {    }    @Override    public void onPermissionNeedExplanation(@NonNull String permissionName) {    }    @Override    public void onPermissionReallyDeclined(@NonNull String permissionName) {    }    @Override    public void onNoPermissionNeeded() {    }}

代码封装:

     高效的开发者绝对不会做重复的代码的事情。那么可以编写一个GPS定位管理类,将公共的功能逻辑封装好实现模块化,在activity中实现差异化的内容。   

    1、GPSLocationListener:利用Java面向接口编程的方式定义该接口用于实时监听数据回调

import android.location.Location;import android.os.Bundle;/** * 类描述:供外部实现的接口 * Created by lizhenya on 2016/9/12. */public interface GPSLocationListener {    /**     * 方法描述:位置信息发生改变时被调用     *     * @param location 更新位置后的新的Location对象     */    void UpdateLocation(Location location);    /**     * 方法描述:provider定位源类型变化时被调用     *     * @param provider provider的类型     * @param status   provider状态     * @param extras   provider的一些设置参数(如高精度、低功耗等)     */    void UpdateStatus(String provider, int status, Bundle extras);    /**     * 方法描述:GPS状态发生改变时被调用(GPS手动启动、手动关闭、GPS不在服务区、GPS占时不可用、GPS可用)     *     * @param gpsStatus 详见{@link GPSProviderStatus}     */    void UpdateGPSProviderStatus(int gpsStatus);}

    2、GPSLocation:实现动态地实时更新位置坐标信息、状态信息

import android.location.Location;import android.location.LocationListener;import android.location.LocationProvider;import android.os.Bundle;/** * 类描述:实现LocationListener的子类,同时实现自己的接口调用 * Created by lizhenya on 2016/9/12. */public class GPSLocation implements LocationListener {    private GPSLocationListener mGpsLocationListener;    public GPSLocation(GPSLocationListener gpsLocationListener) {        this.mGpsLocationListener = gpsLocationListener;    }    @Override    public void onLocationChanged(Location location) {        if (location != null) {            mGpsLocationListener.UpdateLocation(location);        }    }    @Override    public void onStatusChanged(String provider, int status, Bundle extras) {        mGpsLocationListener.UpdateStatus(provider, status, extras);        switch (status) {            case LocationProvider.AVAILABLE:                mGpsLocationListener.UpdateGPSProviderStatus(GPSProviderStatus.GPS_AVAILABLE);                break;            case LocationProvider.OUT_OF_SERVICE:                mGpsLocationListener.UpdateGPSProviderStatus(GPSProviderStatus.GPS_OUT_OF_SERVICE);                break;            case LocationProvider.TEMPORARILY_UNAVAILABLE:                mGpsLocationListener.UpdateGPSProviderStatus(GPSProviderStatus.GPS_TEMPORARILY_UNAVAILABLE);                break;        }    }    @Override    public void onProviderEnabled(String provider) {        mGpsLocationListener.UpdateGPSProviderStatus(GPSProviderStatus.GPS_ENABLED);    }    @Override    public void onProviderDisabled(String provider) {        mGpsLocationListener.UpdateGPSProviderStatus(GPSProviderStatus.GPS_DISABLED);    }}

    3、GPS状态信息类

/** * 类描述:GPS状态类 * Created by lizhenya on 2016/9/12. */public class GPSProviderStatus {    //用户手动开启GPS    public static final int GPS_ENABLED = 0;    //用户手动关闭GPS    public static final int GPS_DISABLED = 1;    //服务已停止,并且在短时间内不会改变    public static final int GPS_OUT_OF_SERVICE = 2;    //服务暂时停止,并且在短时间内会恢复    public static final int GPS_TEMPORARILY_UNAVAILABLE = 3;    //服务正常有效    public static final int GPS_AVAILABLE = 4;}

    4、GPSLocationManager:实现GPS定位的初始化、GPS定位的启动和终止

import android.Manifest;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.location.Location;import android.location.LocationManager;import android.os.Build;import android.provider.Settings;import android.support.v4.app.ActivityCompat;import android.widget.Toast;import java.lang.ref.WeakReference;/** * 类描述:GPS定位的管理类 * Created by lizhenya on 2016/9/12. */public class GPSLocationManager {    private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER;    private static GPSLocationManager gpsLocationManager;    private static Object objLock = new Object();    private boolean isGpsEnabled;    private static String mLocateType;    private WeakReference<Activity> mContext;    private LocationManager locationManager;    private GPSLocation mGPSLocation;    private boolean isOPenGps;    private long mMinTime;    private float mMinDistance;    private GPSLocationManager(Activity context) {        initData(context);    }    private void initData(Activity context) {        this.mContext = new WeakReference<>(context);        if (mContext.get() != null) {            locationManager = (LocationManager) (mContext.get().getSystemService(Context.LOCATION_SERVICE));        }        //定位类型:GPS        mLocateType = locationManager.GPS_PROVIDER;        //默认不强制打开GPS设置面板        isOPenGps = false;        //默认定位时间间隔为1000ms        mMinTime = 1000;        //默认位置可更新的最短距离为0m        mMinDistance = 0;    }    public static GPSLocationManager getInstances(Activity context) {        if (gpsLocationManager == null) {            synchronized (objLock) {                if (gpsLocationManager == null) {                    gpsLocationManager = new GPSLocationManager(context);                }            }        }        return gpsLocationManager;    }    /**     * 方法描述:设置发起定位请求的间隔时长     *     * @param minTime 定位间隔时长(单位ms)     */    public void setScanSpan(long minTime) {        this.mMinTime = minTime;    }    /**     * 方法描述:设置位置更新的最短距离     *     * @param minDistance 最短距离(单位m)     */    public void setMinDistance(float minDistance) {        this.mMinDistance = minDistance;    }    /**     * 方法描述:开启定位(默认情况下不会强制要求用户打开GPS设置面板)     *     * @param gpsLocationListener     */    public void start(GPSLocationListener gpsLocationListener) {        this.start(gpsLocationListener, isOPenGps);    }    /**     * 方法描述:开启定位     *     * @param gpsLocationListener     * @param isOpenGps           当用户GPS未开启时是否强制用户开启GPS     */    public void start(GPSLocationListener gpsLocationListener, boolean isOpenGps) {        this.isOPenGps = isOpenGps;        if (mContext.get() == null) {            return;        }        mGPSLocation = new GPSLocation(gpsLocationListener);        isGpsEnabled = locationManager.isProviderEnabled(GPS_LOCATION_NAME);        if (!isGpsEnabled && isOPenGps) {            openGPS();            return;        }        if (ActivityCompat.checkSelfPermission(mContext.get(), Manifest.permission.ACCESS_FINE_LOCATION)                != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission                (mContext.get(), Manifest.permission.ACCESS_COARSE_LOCATION)                != PackageManager.PERMISSION_GRANTED) {            return;        }        Location lastKnownLocation = locationManager.getLastKnownLocation(mLocateType);        mGPSLocation.onLocationChanged(lastKnownLocation);        //备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新        locationManager.requestLocationUpdates(mLocateType, mMinTime, mMinDistance, mGPSLocation);    }    /**     * 方法描述:转到手机设置界面,用户设置GPS     */    public void openGPS() {        Toast.makeText(mContext.get(), "请打开GPS设置", Toast.LENGTH_SHORT).show();        if (Build.VERSION.SDK_INT > 15) {            Intent intent = new Intent(                    Settings.ACTION_LOCATION_SOURCE_SETTINGS);            mContext.get().startActivityForResult(intent, 0);        }    }    /**     * 方法描述:终止GPS定位,该方法最好在onPause()中调用     */    public void stop() {        if (mContext.get() != null) {            if (ActivityCompat.checkSelfPermission(mContext.get(), Manifest.permission.ACCESS_FINE_LOCATION) !=                    PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext.get(),                    Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {                return;            }            locationManager.removeUpdates(mGPSLocation);        }    }}

GPS管理类的使用:在Activity中Oncreate()方法中进行初始化和开启定位,在onPause()方法中终止定位

import android.app.Activity;import android.location.Location;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.lzy.gpslocation.location.GPSLocationListener;import com.lzy.gpslocation.location.GPSLocationManager;import com.lzy.gpslocation.location.GPSProviderStatus;/** * Created by lizhenya on 2016/9/12. */public class ThirdActivity extends Activity {    private TextView text_gps_3;    private Button btn_gps_3;    private GPSLocationManager gpsLocationManager;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_third);        initData();    }    private void initData() {        gpsLocationManager = GPSLocationManager.getInstances(ThirdActivity.this);        text_gps_3 = (TextView) findViewById(R.id.text_gps_3);        btn_gps_3 = (Button) findViewById(R.id.btn_gps_3);        btn_gps_3.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //开启定位                gpsLocationManager.start(new MyListener());            }        });    }    class MyListener implements GPSLocationListener {        @Override        public void UpdateLocation(Location location) {            if (location != null) {                text_gps_3.setText("经度:" + location.getLongitude() + "\n纬度:" + location.getLatitude());            }        }        @Override        public void UpdateStatus(String provider, int status, Bundle extras) {            if ("gps" == provider) {                Toast.makeText(ThirdActivity.this, "定位类型:" + provider, Toast.LENGTH_SHORT).show();            }        }        @Override        public void UpdateGPSProviderStatus(int gpsStatus) {            switch (gpsStatus) {                case GPSProviderStatus.GPS_ENABLED:                    Toast.makeText(ThirdActivity.this, "GPS开启", Toast.LENGTH_SHORT).show();                    break;                case GPSProviderStatus.GPS_DISABLED:                    Toast.makeText(ThirdActivity.this, "GPS关闭", Toast.LENGTH_SHORT).show();                    break;                case GPSProviderStatus.GPS_OUT_OF_SERVICE:                    Toast.makeText(ThirdActivity.this, "GPS不可用", Toast.LENGTH_SHORT).show();                    break;                case GPSProviderStatus.GPS_TEMPORARILY_UNAVAILABLE:                    Toast.makeText(ThirdActivity.this, "GPS暂时不可用", Toast.LENGTH_SHORT).show();                    break;                case GPSProviderStatus.GPS_AVAILABLE:                    Toast.makeText(ThirdActivity.this, "GPS可用啦", Toast.LENGTH_SHORT).show();                    break;            }        }    }    @Override    protected void onPause() {        super.onPause();        //在onPause()方法终止定位        gpsLocationManager.stop();    }}

OK,关于GPS定位获取经纬度的总结先这么多。

源码下载:Android GPS定位(获取经纬度)

3 0