zoukankan      html  css  js  c++  java
  • Android GPS应用开发

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5715879.html 

    GPS定位系统由三部分组成,即由GPS卫星组成的空间部分,若干地面组成的控制部分和普通用户手中的接收机这三部分。对于手机用户来说,手机就是GPS定位系统的接收机,也就是说GPS定位需要手机的硬件支持GPS功能。

    一、核心API

      Android为GPS功能支持专门提供了一个LocationManager类,

    LocationManager lm=(LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);

    其常用方法如下:

    >  boolean addGpsStatusListener(GpsStatus.Listener listener): 添加一个监听GPS状态的监听器

    > void addProximityAlert(double latitude,double  longitude,float radius, long expiration, PendingIntent intent): 添加一个临近警告

    > List<String> getAllProviders(): 获取所有的LocationProvider列表

    > String getBestProvider(Criteria criteria,boolean enabledOnly): 根据指定条件返回最优的LocationProvider对象

    > GpsStatus getGpsStatus(GpsStatus status): 获取GPS状态

    > Location getLastKnownLocation(String provider): 根据LocationProvider获取最近一次已知的Location

    > LocationProvider getProvider(String name): 根据名称来获取LocationProvider

    > List<String>  getProviders(Criteria criteria,boolean enabledOnly): 根据指定条件获取满足该条件的全部LocationProvider的名称

    > List<String> getProviders(boolean enabledOnly): 获取所有可用的LocationProvider

    > boolean isProviderEnabled(provider): 判断指定名称的LocationProvider是否可用

    > void removeGpsStatusListener(GpsStatus.Listener listener): 删除Gps状态监听器

    > void removeProximityAlert(PendingIntent intent): 删除一个临近警告

    > void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent): 通过指定的LoactionProvider周期性地获取定位信息,并通过intent启动相应的组件。

    > void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener): 通过指定的LocationProvider周期性地获取定位信息,并触发listener所对应的触发器。

    LocationProvider(定位提供者),LocationProvider对象就是定位组件的抽象表示,通过LocationProvider可以获取该定位组件的相关信息。常用方法如下:

    > int getAccuracy(): 返回该LocationProvider的精度

    > String getName(): 返回该LocationProvider的名称

    > int getPowerRequirement(): 获取该LocationProvider的电源需求

    > boolean hasMonetaryCost(): 获取该LocationProvider是收费的还是免费的

    > boolean meetsCriteria(Criteria criteria) : 判断该LocationProvider是否满足Criteria条件

    > boolean requiresCell(): 判断该LocationProvider是否需要访问网络基站

    > boolean requiresNetwork(): 判断该LocationProvider是否需要网络数据

    > boolean requiresSatellite(): 判断该LocationProvider是否需要访问基于卫星的定位系统

    > boolean supportsAltitude(): 判断该LocationProvider是否支持高度信息

    > boolean supportsBearing(): 判断该LocationProvider是否支持方向信息

    > boolean supportsSpeed(): 判断该LocationProvider是否支持速度信息

    Location,一个代表位置信息的抽象类,提供如下方法来获取定位信息

    > float getAccuracy(): 获取定位信息的精度

    > double getAltitude(): 获取定位信息的高度

    > float getBearing(): 获取定位信息的方向

    > getLatitude(): 获取定位信息的纬度

    > getLongitude(): 获取定位信息的经度

    > getProvider(): 获取提供该定位信息的LocationProvider

    > getSpeed(): 获取定位信息的速度

    > hasAccuracy(): 判断该定位信息是否有精度信息

    > hasAltitude(): 判断该定位信息是否有高度信息

    > hasBearing(): 判断该定位信息是否有方向信息

    > hasSpeed(): 判断该定位信息是否有速度信息

      这三个API是Android GPS支持的三个核心API,用它们来获取GPS定位信息的通过步骤为:

    (1) 获取系统的LocationManager对象

    (2) 使用LocationManager,通过指定LocationProvider来获取定位信息,定位信息由Location对象来表示

    (3) 从Location中获取定位信息

    二、获取LocationProvider

      Android的定位信息由LocationProvider对象来提供,该对象代表一个抽象的定位组件。在编程之前需要先获取LocationProvider对象。

    1. 示例:获取所有可用的LocationProvider

    public class AllProvidersActivity extends Activity {
        ListView providers;
        LocationManager lm;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_all_providers);
        
            providers=(ListView) findViewById(R.id.providers);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            List<String> providerNames=lm.getAllProviders();
            ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);
            providers.setAdapter(adapter);
            
        }
    }

    如图可看出当前模拟器所有可用的LocationProvider有三个:

    > passive: 由LocationManager.PASSIVE_PROVIDER常量表示

    > gps: 由LocationManager.GPS_PROVIDER常量表示,代表通过GPS获取定位信息的LocationProvider对象

    > network: 由LocationManager.NETWORK_PROVIDER常量表示,代表通过移动通信网络获取定位信息的LocationProvider对象

    2. 通过名称获得指定LocationProvider

    //获得基于GPS的LocationProvider
    LocationProvider gpsProvider=lm.getProvider(LocationManager.GPS_PROVIDER);

    3. 根据Criteria获取LocationProvider

    LocationManager的getBestProvider(Criteria criteria,boolean enabledOnly)用来得到符合指定条件的LocationProvider。Criteria代表了一个过滤条件,提供如下常用方法来设置:

    > setAccuracy(int accuracy): 设置对LocationProvider的精度要求

    > setAltitudeRequired(boolean altitudeRequired): 设置要求LocationProvider能提供高度信息

    > setBearingRequired(boolean bearingRequired): 设置要求LocationProvider能提供方向信息

    > setCostAllowed(boolean  costAllowed): 设置要求LocationProvider是否免费

    > setPowerRequirement(int level): 设置要求LocationProvider的耗电量

    > setSpeedRequired(boolean speedRequired): 设置要求LocationProvider能提供速度信息

    示例:获取系统中免费的、能提供高度信息、速度信息的LocationProvider

    public class AllProvidersActivity extends Activity {
        ListView providers;
        LocationManager lm;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_all_providers);
            providers=(ListView) findViewById(R.id.providers);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Criteria cri=new Criteria();
            cri.setCostAllowed(false);
            cri.setAltitudeRequired(true);
            cri.setBearingRequired(true);
            List<String> providerNames=lm.getAllProviders();
            ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);
            providers.setAdapter(adapter);
        }
    }
    复制代码
    public class AllProvidersActivity extends Activity {
        ListView providers;
        LocationManager lm;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_all_providers);
            providers=(ListView) findViewById(R.id.providers);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Criteria cri=new Criteria();
            cri.setCostAllowed(false);
            cri.setAltitudeRequired(true);
            cri.setBearingRequired(true);
            List<String> providerNames=lm.getAllProviders();
            ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, providerNames);
            providers.setAdapter(adapter);
        }
    }
    复制代码

    三、获取定位信息

    示例:通过手机实时获取定位信息,包括用户所在的经度、纬度、高度、方向、移动速度等

    public class LocationActivity extends Activity {
        LocationManager lm;
        EditText show;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_location);
            show=(EditText) findViewById(R.id.show);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //从GPS获取最近的定位信息
            Location location=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            Log.i("LocationActivity", "location="+location);
            updateView(location);
            //每3秒获取一次GPS的定位信息
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8, new LocationListener() {
                
                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
                
                }
                
                @Override
                public void onProviderEnabled(String provider) {
                    // 当GPS LocationProvider可用时,更新位置
                    updateView(lm.getLastKnownLocation(provider));
                }
                
                @Override
                public void onProviderDisabled(String provider) {
                    updateView(lm.getLastKnownLocation(null));
                }
                
                @Override
                public void onLocationChanged(Location location) {
                    //GPS定位信息发生改变时,更新位置
                    updateView(location);
                }
            });
        }

        public void updateView(Location newLocation){
            if(newLocation!=null){
                StringBuilder sb=new StringBuilder();
                sb.append("实时的位置信息: ");
                sb.append("经度:");
                sb.append(newLocation.getLongitude());
                sb.append(" 纬度:");
                sb.append(newLocation.getLatitude());
                sb.append(" 高度:");
                sb.append(newLocation.getAltitude());
                sb.append(" 速度:");
                sb.append(newLocation.getSpeed());
                sb.append(" 方向:");
                sb.append(newLocation.getBearing());
                show.setText(sb.toString());
            }else{
                show.setText("");
            }
        }
    }
    复制代码
    public class LocationActivity extends Activity {
        LocationManager lm;
        EditText show;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_location);
            show=(EditText) findViewById(R.id.show);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //从GPS获取最近的定位信息
            Location location=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            Log.i("LocationActivity", "location="+location);
            updateView(location);
            //每3秒获取一次GPS的定位信息
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8, new LocationListener() {
                
                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
                
                }
                
                @Override
                public void onProviderEnabled(String provider) {
                    // 当GPS LocationProvider可用时,更新位置
                    updateView(lm.getLastKnownLocation(provider));
                }
                
                @Override
                public void onProviderDisabled(String provider) {
                    updateView(lm.getLastKnownLocation(null));
                }
                
                @Override
                public void onLocationChanged(Location location) {
                    //GPS定位信息发生改变时,更新位置
                    updateView(location);
                }
            });
        }
    
        public void updateView(Location newLocation){
            if(newLocation!=null){
                StringBuilder sb=new StringBuilder();
                sb.append("实时的位置信息:
    ");
                sb.append("经度:");
                sb.append(newLocation.getLongitude());
                sb.append("
    纬度:");
                sb.append(newLocation.getLatitude());
                sb.append("
    高度:");
                sb.append(newLocation.getAltitude());
                sb.append("
    速度:");
                sb.append(newLocation.getSpeed());
                sb.append("
    方向:");
                sb.append(newLocation.getBearing());
                show.setText(sb.toString());
            }else{
                show.setText("");
            }
        }
    }
    复制代码

    个人总结:

    1. 因为GPS信号偶尔会不好,所以仅使用gps的时候,绝大多数情况下会出现getLastKnowLocation为null,需要在系统的定位模式中,要允许使用wifi和network定位;这样即使gps定位返回null,network也能得到粗略的位置信息。

    2. getLastKnownLocation经常取不到东西的,使用百度定位SDK吧,比较靠谱。

    3. getLastKnowLocation不是一次就能定位成功,必须要多次定位。

    4. 要在空旷无遮挡物的地方。

    四、临近警告

      LocationManager提供一个方法addProximityAlert(double latitude,double  longitude,float radius, long expiration, PendingIntent intent)用于添加一个临近警告。当用户手机不断临近指定固定点时,当与该固定点的距离小于指定范围时,系统可以触发相应的处理。

    示例:

    public class ProximityTestActivity extends Activity {
        LocationManager lm;
        double longitude=113.39;
        double latitude=23.13;
        float radius=5000;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_proximity_test);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Intent intent=new Intent(this,ProximityAlertReceiver.class);
            PendingIntent pi=PendingIntent.getBroadcast(this, -1, intent, 0);
            //第四个参数指定经过多少毫秒后该临近警告就会过期失效,-1指定永不过期
            lm.addProximityAlert(latitude, longitude, radius, -1, pi);
        }

        public class ProximityAlertReceiver extends BroadcastReceiver{

            @Override
            public void onReceive(Context context, Intent intent) {
                boolean isEnter=intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
                if(isEnter){
                    Toast.makeText(context, "你已进入禁止区域", 0).show();
                }else{
                    Toast.makeText(context, "你离开禁止区域", 0).show();
                }
            }
        }
    }
    复制代码
    public class ProximityTestActivity extends Activity {
        LocationManager lm;
        double longitude=113.39;
        double latitude=23.13;
        float radius=5000;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_proximity_test);
            lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
            Intent intent=new Intent(this,ProximityAlertReceiver.class);
            PendingIntent pi=PendingIntent.getBroadcast(this, -1, intent, 0);
            //第四个参数指定经过多少毫秒后该临近警告就会过期失效,-1指定永不过期
            lm.addProximityAlert(latitude, longitude, radius, -1, pi);
        }
    
        public class ProximityAlertReceiver extends BroadcastReceiver{
    
            @Override
            public void onReceive(Context context, Intent intent) {
                boolean isEnter=intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
                if(isEnter){
                    Toast.makeText(context, "你已进入禁止区域", 0).show();
                }else{
                    Toast.makeText(context, "你离开禁止区域", 0).show();
                }
            }
        }
    
    复制代码
     
  • 相关阅读:
    EPANET头文件解读系列4——EPANET2.H
    EPANET头文件解读系列3——TOOLKIT.H
    EPANET头文件解读系列2——ENUMSTXT.H
    EPANET头文件解读系列1——TEXT.H
    ENUMSTXT.H中的指针数组
    main函数的参数
    函数指针与指针函数
    FMDB源码阅读
    17个提升iOS开发效率的必用工具
    UIKit性能调优实战讲解
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5718479.html
Copyright © 2011-2022 走看看