日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

android定位的實現(xiàn)

系統(tǒng) 2161 0
基于android的定位無非就兩種:network、gps。兩者各有優(yōu)劣。
Network:定位快,準(zhǔn)確度低,受環(huán)境影響小。
GPS:定位慢,準(zhǔn)確度高,受環(huán)境影響大。

本文要解決的問題:
1.????? locationManager.getLastKnownLocation方法返回null。
2.????? 如何實現(xiàn)快速而又精確的定位。

E文好的話,直接看官網(wǎng)就好了 http://developer.android.com/guide/topics/location/strategies.html

在你的程序里如果有這樣的代碼你就要注意了(現(xiàn)在看來這些倒是多余了)
    
Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);//高精度
        criteria.setAltitudeRequired(false);//無海拔要求
        criteria.setBearingRequired(false);//無方位要求
        criteria.setCostAllowed(true);//允許產(chǎn)生資費
        criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗
      
        // 獲取最佳服務(wù)對象
        String provider = locationManager.getBestProvider(criteria,true);
locationManager.getLastKnownLocation(provider);

  


locationManager.getBestProvider(criteria,true);方法看起來很完美,但其實返回值就network、gps二選一。而且如果你要求高精度,它會優(yōu)先檢查GPS,如果手機開啟了GPS就返回GPS,否則返回network。如果都沒開啟則返回null。
結(jié)合Network、GPS兩種定位方式的優(yōu)劣不難看出為什么getLastKnownLocation方法會返回null(這只針對第一次定位)。

當(dāng)你開啟GPS,provider的值為GPS。這時的定位方式為GPS,由于GPS定位慢(我測試的時間大約為50秒),所以它不可能立即返回你一個Location對象,所以就返回null了。還有人用下面的方法解決這個問題:
    
    while (location ==null) {
           location = locationManager.getLastKnownLocation(provider);
       }

  

這絕對是個愚蠢的做法!舉個例子:如果你在室內(nèi),gps無法定位到,你的程序?qū)⑾萑胨姥h(huán)。當(dāng)然使用requestLocationUpdates可以做到定位且不讓程序陷入死循環(huán),但是定位耗時長,甚至得不到定位。
如果使用網(wǎng)絡(luò)定位呢,不得說這也是一個不錯的選擇。locationManager.requestLocationUpdates(
????????????? LocationManager.NETWORK_PROVIDER, 0, 0,networkListener);
網(wǎng)絡(luò)定位耗時一般在2秒左右(網(wǎng)絡(luò)差,時間會更長),只要你接入網(wǎng)絡(luò),基本上都能獲得定位。唯一的缺點就是精度不高。

那能不能將兩者結(jié)合,這也是本文的重點。既然結(jié)合兩者,就要同時為兩者添加監(jiān)聽
    
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000 * 2,50,gpsListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,networkListener);

  


這樣,大概2秒我們就可以得到來自網(wǎng)絡(luò)的定位,一分鐘后得到來自GPS定位。這時用GPS定位替換網(wǎng)絡(luò)定位就好了。當(dāng)然這只是個理想的情況,現(xiàn)實要復(fù)雜的多。
比如:
你第一次定位成功返回location,由于網(wǎng)絡(luò)問題第二次返回null。這時會發(fā)現(xiàn),更新的location沒有上次的精確,甚至是null,無法使用,這時我們要判斷當(dāng)前的location和新獲得的location那個更好。可能你獲得GPS定位后,由于天氣、進(jìn)入隧道等原因GPS服務(wù)器丟失,無法更新location(這時一個好的做法是切換到network定位)。還有可能用戶沒有開啟GPS和network,根本就談不上定位(其實每次定位成功都會有個定位緩存的,可以使用getLastKnownLocation獲得)。

終上所述,我們要做的就是:
1.? 嘗試通過getLastKnownLocation獲取上次定位信息
2.? 開啟network和gps監(jiān)聽
3.? 獲得network定位信息location
4.? 比較當(dāng)前l(fā)ocation和新獲取的location哪個更好(來自network)
5.? 獲得gps定位信息location
6.? 停掉network監(jiān)聽
7.? 比較當(dāng)前l(fā)ocation和新獲取的location哪個更好(來自gps)
8.? 如果gps服務(wù)器丟失,重新開啟network監(jiān)聽

以GPS監(jiān)聽為例
    
   // GPS監(jiān)聽的回調(diào)函數(shù)
    private class GPSLocationListener implements LocationListener {
 
       private boolean isRemove = false;//判斷網(wǎng)絡(luò)監(jiān)聽是否移除
 
       @Override
       public void onLocationChanged(Location location) {
           // TODO Auto-generatedmethod stub
           boolean flag =betterLocation.isBetterLocation(location,
                  currentBestLocation);
 
           if (flag) {
              currentBestLocation = location;
              updateLocation(currentBestLocation);
           }
           // 獲得GPS服務(wù)后,移除network監(jiān)聽
           if (location !=null && !isRemove) {
              locationManager.removeUpdates(networkListener);
              isRemove = true;
           }
       }
 
       @Override
       public void onProviderDisabled(String provider) {
           // TODO Auto-generatedmethod stub
       }
 
       @Override
       public void onProviderEnabled(String provider) {
           // TODO Auto-generatedmethod stub
       }
 
       @Override
       public void onStatusChanged(String provider, int status, Bundleextras) {
           // TODO Auto-generatedmethod stub
           if (LocationProvider.OUT_OF_SERVICE == status) {
              Toast.makeText(MainActivity.this,"GPS服務(wù)丟失,切換至網(wǎng)絡(luò)定位",
                     Toast.LENGTH_SHORT).show();
              locationManager
                     .requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER, 0, 0,
                            networkListener);
           }
       }
    }

  


其中isBetterLocation是用來判斷哪個location更好的。這個方法來自android官網(wǎng)的,通過location獲取的時間,精度等信息進(jìn)行判斷。
    
private static final int TWO_MINUTES = 1000 * 60 * 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  
        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);  
    }  

  

因為之前上傳的demo,大家覺得意義不大,所以就不再提供了。
下圖的‘微秒’單位錯了,應(yīng)該是毫秒

android定位的實現(xiàn)


andriod 自動切換網(wǎng)絡(luò)和gps定位
獲取到位置服務(wù)以后,同時請求網(wǎng)絡(luò)和gps定位更新,然后就會同時上報網(wǎng)絡(luò)和gps的Location 信息。在沒有g(shù)ps信號的時候,會自動獲取網(wǎng)絡(luò)定位的位置信息,如果有g(shù)ps信號,則優(yōu)先獲取gps提供的位置信息.isBetterLocation 根據(jù) 時間、準(zhǔn)確性、定位方式等判斷是否更新當(dāng)前位置信息,該方法來源于開發(fā)指南的Obtaining User Location 下。

    
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import cn.tangdada.tangbang.R;

public class SecondFragment extends BaseFragment
{

    private TextView tv;

    LocationManager lm = null;

    Location myLocation = null;

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss.SSSZ");

    public SecondFragment()
    {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_second, null);
        tv = (TextView) view.findViewById(R.id.tv);

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

        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onDestroy()
    {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public void onPause()
    {
        // TODO Auto-generated method stub
        super.onPause();
        lm.removeUpdates(listener);
    }

    @Override
    public void onResume()
    {
        // TODO Auto-generated method stub
        super.onResume();
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    LocationListener listener = new LocationListener()
    {

        @Override
        public void onLocationChanged(Location location)
        {
            // 實際上報時間
            // String time = sdf.format(new Date(location.getTime()));
            // timeText.setText("實際上報時間:" + time);

            if (isBetterLocation(location, myLocation))
            {
                // 獲取緯度
                double lat = location.getLatitude();
                // 獲取經(jīng)度
                double lon = location.getLongitude();
                // 位置提供者
                String provider = location.getProvider();
                // 位置的準(zhǔn)確性
                float accuracy = location.getAccuracy();
                // 高度信息
                double altitude = location.getAltitude();
                // 方向角
                float bearing = location.getBearing();
                // 速度 米/秒
                float speed = location.getSpeed();

                String locationTime = sdf.format(new Date(location.getTime()));
                String currentTime = null;

                if (myLocation != null)
                {
                    currentTime = sdf.format(new Date(myLocation.getTime()));
                    myLocation = location;

                }
                else
                {
                    myLocation = location;
                }

                // 獲取當(dāng)前詳細(xì)地址
                StringBuffer sb = new StringBuffer();
                if (myLocation != null)
                {
                    Geocoder gc = new Geocoder(context);
                    List<Address> addresses = null;
                    try
                    {
                        addresses = gc.getFromLocation(myLocation.getLatitude(), myLocation.getLongitude(), 1);
                    }
                    catch (IOException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    if (addresses != null && addresses.size() > 0)
                    {
                        Address address = addresses.get(0);
                        sb.append(address.getCountryName() + address.getLocality());
                        sb.append(address.getSubThoroughfare());

                    }
                }

                tv.setText("經(jīng)度:" + lon + "\n緯度:" + lat + "\n服務(wù)商:" + provider + "\n準(zhǔn)確性:" + accuracy + "\n高度:" + altitude + "\n方向角:" + bearing
                        + "\n速度:" + speed + "\n上次上報時間:" + currentTime + "\n最新上報時間:" + locationTime + "\n您所在的城市:" + sb.toString());

            }

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
            Log.i("tag", "onStatusChanged: " + provider);

        }

        @Override
        public void onProviderEnabled(String provider)
        {
            Log.i("tag", "onProviderEnabled: " + provider);
        }

        @Override
        public void onProviderDisabled(String provider)
        {
            Log.i("tag", "onProviderDisabled: " + provider);
        }

    };

    private static final int TWO_MINUTES = 1000 * 1 * 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
        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);
    }

}

  

android定位的實現(xiàn)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 孝感市| 江永县| 九台市| 奉新县| 瓦房店市| 贵德县| 凤城市| 枣庄市| 淄博市| 延寿县| 土默特右旗| 永寿县| 中方县| 贡山| 海盐县| 门源| 游戏| 新乡市| 大港区| 厦门市| 苏尼特右旗| 华坪县| 贺兰县| 华阴市| 崇仁县| 云安县| 信阳市| 富锦市| 东山县| 桂林市| 昭平县| 新宁县| 紫阳县| 乾安县| 钟山县| 虞城县| 娄烦县| 巫溪县| 灌阳县| 孙吴县| 安康市|