码迷,mamicode.com
首页 > 其他好文 > 详细

GPS

时间:2016-04-21 10:11:26      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:

1.申请用户权限

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

2.Java代码

import java.util.Iterator;

import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;

/**
 * 获取到位置服务以后,同时请求网络和gps定位更新,然后就会同时上报网络和gps的Location 信息。
 * 在没有gps信号的时候,会自动获取网络定位的位置信息,如果有gps信号,则优先获取gps提供的位置信息。
 * 使用 .isBetterLocation 根据时间、准确性、定位方式等判断是否更新当前位置信息,
 * 该方法来源于开发指南的Obtaining User Location。
 * 
 * 
 * @author THINK
 * 
 */
public class MainActivity extends Activity {
    private EditText editText;
    private LocationManager lm;
    private Location currentlocation;  // 当前位置
    private static final String TAG = "h_bl";
    private TextView tv_show_log;

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 不要用的时候,移出监听器,不然会一直在获取
        lm.removeUpdates(locationListener);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_show_log=(TextView) findViewById(R.id.tv_show_log);
        editText = (EditText) findViewById(R.id.editText);
        // 1.创建LocationManager
        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

/*         // 判断GPS是否正常启动
         if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
         Toast.makeText(this, "请开启GPS导航...", Toast.LENGTH_SHORT).show();
         // 返回开启GPS导航设置界面
         Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
         startActivityForResult(intent, 0);
         return;
         }*/

        // 为获取地理位置信息时设置查询条件
//        String bestProvider = lm.getBestProvider(getCriteria(), true);
        // 获取位置信息
        // 如果不设置查询要求,getLastKnownLocation方法传人的参数为LocationManager.GPS_PROVIDER
        // getLastKnownLocation返回一个给定Provider提供的最后一个已知位置,提前提供,防止用户等待,但数据不精确
        currentlocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        tv_show_log.append("原始缓存数据:\n");
        if (currentlocation!=null) {
            tv_show_log.append("时间:" + currentlocation.getTime()+"  经度:" + currentlocation.getLongitude()+"  纬度:" + currentlocation.getLatitude()+"  海拔:" + currentlocation.getAltitude()+"\n");
        }
        updateView(currentlocation);
        // 监听状态
        lm.addGpsStatusListener(listener);
        // 绑定监听,有4个参数
        // 参数1,设备:有GPS_PROVIDER和NETWORK_PROVIDER两种
        // 参数2,位置信息更新周期,单位毫秒
        // 参数3,位置变化最小距离:当位置距离变化超过此值时,将更新位置信息
        // 参数4,监听
        // 备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新

        // 1秒更新一次,或最小位移变化超过1米更新一次;
        // 注意:此处更新准确度非常低,推荐在service里面启动一个Thread,在run中sleep(10000);然后执行handler.sendMessage(),更新位置
        // 同时启用net和gps
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, locationListener);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 1, locationListener);
    }

    // 2.LocationListener位置监听
    private LocationListener locationListener = new LocationListener() {

        /**
         * 位置信息变化时触发
         */
        public void onLocationChanged(Location location) {
//            tv_show_log.append("数据提供者:"+location.getProvider()+"\n");
            // 判断位置是否更好
            if (isBetterLocation(location, currentlocation))
            {
                tv_show_log.append("数据提供者:"+location.getProvider()+"\n");
                Log.d(TAG, "刷新位置");
                tv_show_log.append("刷新位置\n");
                updateView(location);  // 更新ui数据
                currentlocation=location; // 当前位置 替换为 更新获得的位置
            }else {
//                updateView(currentlocation);  // 更新ui数据
                Log.d(TAG, "未刷新位置");
                tv_show_log.append("未刷新位置\n");
            }
            Log.i(TAG, "时间:" + location.getTime());
            Log.i(TAG, "经度:" + location.getLongitude());
            Log.i(TAG, "纬度:" + location.getLatitude());
            Log.i(TAG, "海拔:" + location.getAltitude());
            tv_show_log.append("时间:" + location.getTime()+"  经度:" + location.getLongitude()+"  纬度:" + location.getLatitude()+"  海拔:" + location.getAltitude()+"\n");
        }

        /**
         * GPS状态变化时触发
         */
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
            // GPS状态为可见时
            case LocationProvider.AVAILABLE:
                Log.i(TAG, "当前GPS状态为可见状态");
                tv_show_log.append("当前GPS状态为可见状态\n");
                break;
            // GPS状态为服务区外时
            case LocationProvider.OUT_OF_SERVICE:
                Log.i(TAG, "当前GPS状态为服务区外状态");
                tv_show_log.append("当前GPS状态为服务区外状态\n");
                break;
            // GPS状态为暂停服务时
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                Log.i(TAG, "当前GPS状态为暂停服务状态");
                tv_show_log.append("当前GPS状态为暂停服务状态\n");
                break;
            }
        }

        /**
         * GPS开启时触发
         */
        public void onProviderEnabled(String provider) {
            Location location = lm.getLastKnownLocation(provider);
            updateView(location);
        }

        /**
         * GPS禁用时触发
         */
        public void onProviderDisabled(String provider) {
            updateView(null);
        }

    };

    // 状态监听
    GpsStatus.Listener listener = new GpsStatus.Listener() {
        public void onGpsStatusChanged(int event) {
            switch (event) {
            // 第一次定位
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Log.i(TAG, "第一次定位");
                tv_show_log.append("第一次定位\n");
                break;
            // 卫星状态改变
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                Log.i(TAG, "卫星状态改变");
                tv_show_log.append("卫星状态改变\n");
                // 获取当前状态
                GpsStatus gpsStatus = lm.getGpsStatus(null);
                // 获取卫星颗数的默认最大值
                int maxSatellites = gpsStatus.getMaxSatellites();
                // 创建一个迭代器保存所有卫星
                Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator();
                int count = 0;
                while (iters.hasNext() && count <= maxSatellites) {
                    GpsSatellite s = iters.next();
                    count++;
                }
                System.out.println("搜索到:" + count + "颗卫星");
                tv_show_log.append("搜索到:" + count + "颗卫星\n");
                break;
            // 定位启动
            case GpsStatus.GPS_EVENT_STARTED:
                Log.i(TAG, "定位启动");
                tv_show_log.append("定位启动\n");
                break;
            // 定位结束
            case GpsStatus.GPS_EVENT_STOPPED:
                Log.i(TAG, "定位结束");
            //    tv_show_log.append("定位结束\n");
                break;
            }
        };
    };

    /**
     * 实时更新文本内容
     * 
     * @param location
     */
    private void updateView(Location location) {
        if (location != null) {
            editText.setText("设备位置信息\n\n经度:");
            editText.append(String.valueOf(location.getLongitude()));
            editText.append("\n纬度:");
            editText.append(String.valueOf(location.getLatitude()));
        } else {
            // 清空EditText对象
            editText.getEditableText().clear();
        }
    }

    /**
     * 返回查询条件,暂时不用这个
     * 
     * @return
     */
    private Criteria getCriteria() {
        Criteria criteria = new Criteria();
        // 设置定位精确度 Criteria.ACCURACY_COARSE比较粗略,Criteria.ACCURACY_FINE则比较精细
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        // 设置是否要求速度
        criteria.setSpeedRequired(false);
        // 设置是否允许运营商收费
        criteria.setCostAllowed(false);
        // 设置是否需要方位信息
        criteria.setBearingRequired(false);
        // 设置是否需要海拔信息
        criteria.setAltitudeRequired(false);
        // 设置对电源的需求
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        return criteria;
    }
    
    /**
     * 精度判断,来自Dev Guide
     */
    private static final int TWO_MINUTES = 1000 * 60 * 2; // 2分钟

    /** Determines whether one Location reading is better than the current Location fix
     *  确定获取的位置和当前位置,哪个比较好
      * @param location  The new Location that you want to evaluate 你想要评估的新位置
      * @param currentBestLocation  The current Location fix, to which you want to compare the new one 当前位置,你想比较的
      */
    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location  有一个新位置总比没有位置要好
            return true;
        }

        // Check whether the new location fix is newer or older
        // 检查新地址是更新的还是更旧的
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it‘s been more than two minutes since the current location, use the new location
        // because the user has likely moved
        // 如果从当前位置开始超过两分钟,使用新的位置,因为用户可能移动了
        if (isSignificantlyNewer) {
            return true;
        // If the new location is more than two minutes older, it must be worse
        // 如果从当前位置开始少于两分钟,使用新的位置,一定是因为出错了
        } else if (isSignificantlyOlder) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        // 检查当前地址的精度高了,还是低了。
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        // 检查当前地址和旧地址,是否来自同一个provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        // 确认位置的质量,通过"及时性和精度的结合"来判断
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }

    /** Checks whether two providers are the same */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
          return provider2 == null;
        }
        return provider1.equals(provider2);
    }
}

3.布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/editText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:cursorVisible="false"
        android:editable="false" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/tv_show_log"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" 
            android:text="显示log:\n"
            android:textSize="15sp"/>
    </ScrollView>

</LinearLayout>

 

GPS

标签:

原文地址:http://www.cnblogs.com/H-BolinBlog/p/5415521.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!