欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

開箱即用的Google與百度定位坐標(biāo)系轉(zhuǎn)換實例

 更新時間:2022年08月19日 10:47:27   作者:newki  
這篇文章主要為大家介紹了開箱即用的Google與百度定位坐標(biāo)系轉(zhuǎn)換實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

集成谷歌定位與百度定位并在地圖上顯示

項目背景

東南亞某小國的App,需要用到定位與地圖顯示,我們都知道海外人士都是喜歡谷歌地圖與谷歌定位的,那么必然是要優(yōu)先使用谷歌定位的,但是中國手機賣的很好,部分中國手機的海外版是沒有谷歌服務(wù)的,那么我使用百度地圖進(jìn)行降級處理。

兩者使用的定位坐標(biāo)系不同,如果需要在谷歌地圖上展示百度定位,需要如何轉(zhuǎn)換呢?或者說谷歌的定位如何在百度地圖上展示呢?

一. 集成谷歌定位

跟項目下的build.gradle

別的先不說,先把谷歌服務(wù)插件給引入

    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.3'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.8'
    }

app模塊下的build.gradle最底部 應(yīng)用谷歌服務(wù)插件

apply plugin: 'com.google.gms.google-services'

然后去谷歌后臺申請App-Key相關(guān)的項目,需要填寫包名和一些簽名文件的SHA1值,注意這里relese包的SHA1值,和谷歌市場上架的SHA1值是不同的,上架之后需要去谷歌市場把谷歌市場上的SHA1值設(shè)置進(jìn)去,因為谷歌市場上架之后會把你的簽名文件包裝一次,完全不同的簽名文件了。

完成此步之后 下載對應(yīng)App的 google-services.json 文件。

此步驟完成,我們再遠(yuǎn)程依賴谷歌定位的庫。location

   //定位功能
    api 'com.google.android.gms:play-services-location:16.0.0'

定位Api使用流程:

權(quán)限定義

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

注意使用之前要動態(tài)申請權(quán)限,這里不做演示

     //初始化谷歌地圖API
     if (googleApiClient == null) {
        googleApiClient = new GoogleApiClient.Builder(mActivity)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    }
   //Google-Location-Api 服務(wù)連接成功回調(diào)
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接成功了");
        getAPILastLocation();
    }
    //Google-Location-Api 服務(wù)異常連接暫停
    @Override
    public void onConnectionSuspended(int i) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)被暫停了");
        if (googleApiClient != null && !googleApiClient.isConnected())
            googleApiClient.connect();
    }
    //Google-Location-Api 連接異常
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接錯誤");
        //如果連接錯誤直接用百度定位
    }
    public void stopLocation() {
        if (googleApiClient != null && googleApiClient.isConnected()){
            googleApiClient.disconnect();
        }
    }
    private void getAPILastLocation() {
    FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mActivity);
    fusedLocationProviderClient.getLastLocation().addOnSuccessListener(mActivity, location -> {
        if (location != null && location.getLatitude() > 0 && location.getLongitude() > 0) {
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            Log.e("MapLastLocationUtils", "Google-API-獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
        } else {
                //如果沒有值直接用百度定位
        }
    });
  }

二. 集成百度定位

我們也是需要在百度開發(fā)者平臺上申請應(yīng)用的App,不過這一塊就比較簡單,只需要驗證包名就行了,然后會給你一個AppId。

我們下載定位的jar包與so動態(tài)庫,導(dǎo)入到項目,然后再清單文件配置

              <meta-data
           android:name="com.baidu.lbsapi.API_KEY"
            android:value="123456789">
        </meta-data>
        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote">
            <intent-filter>
                <action android:name="com.baidu.location.service_v2.2"></action>
            </intent-filter>
        </service>

Application中初始化SDK

    SDKInitializer.initialize(context);

判斷開啟谷歌定位還是百度定位的邏輯封裝

public class MapLastLocationUtils implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
        LifecycleObserver {
    private static MapLastLocationUtils ourInstance;
    private Activity mActivity;
    private GoogleApiClient googleApiClient;
    private LocationClient mBDLocationClient;
    private LocationRequest mLocationRequest;
    private boolean isNeedBackNotifyLocation = false;
    public static MapLastLocationUtils getInstance(Activity context) {
        if (ourInstance == null) {
            ourInstance = new MapLastLocationUtils(context);
        }
        return ourInstance;
    }
    private MapLastLocationUtils(Activity context) {
        mActivity = context;
        //初始化谷歌地圖API
        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }
    }
    /**
     * 只是獲取當(dāng)前的位置一次
     */
    public void getLastLocation() {
        int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(CommUtils.getContext());
        if (code == ConnectionResult.SUCCESS) {
            // 支持Google服務(wù)
            getAPILastLocation();
        } else {
            //開啟百度定位
            getBDLastLocation();
        }
    }
    //API連接成功嘗試獲取最后的位置
    @SuppressLint("MissingPermission")
    private void getAPILastLocation() {
        FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mActivity);
        fusedLocationProviderClient.getLastLocation().addOnSuccessListener(mActivity, location -> {
            if (location != null && location.getLatitude() > 0 && location.getLongitude() > 0) {
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                Log.e("MapLastLocationUtils", "Google-API-獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
                if (mListener != null) {
                    //這里轉(zhuǎn)換一下,如果國內(nèi)轉(zhuǎn)換為火星坐標(biāo),國外直接用
                    Gps gps = GPS84ToGCJ02(longitude, latitude);
                    mListener.onLastLocation(gps.getLatitude(), gps.getLongitude());
                }
            } else {
                getBDLastLocation();
            }
        });
    }
    //百度定位嘗試獲取最后的位置
    private void getBDLastLocation() {
        mBDLocationClient = new LocationClient(mActivity);
        //聲明LocationClient類
        mBDLocationClient.registerLocationListener(mBDLastLocationListener);
        //配置百度定位的選項
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy); // 可選,默認(rèn)高精度,設(shè)置定位模式,高精度,低功耗,僅設(shè)備
        option.setCoorType("gcj02"); // 可選,默認(rèn)gcj02,設(shè)置返回的定位結(jié)果坐標(biāo)系,如果配合百度地圖使用,建議設(shè)置為bd09ll; 國際WGS84
        option.setScanSpan(0); // 可選,默認(rèn)0,即僅定位一次,設(shè)置發(fā)起連續(xù)定位請求的間隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(false); // 可選,設(shè)置是否需要地址信息,默認(rèn)不需要
        option.setIsNeedLocationDescribe(false); // 可選,設(shè)置是否需要地址描述
        option.setNeedDeviceDirect(false); // 可選,設(shè)置是否需要設(shè)備方向結(jié)果
        option.setLocationNotify(false); // 可選,默認(rèn)false,設(shè)置是否當(dāng)gps有效時按照1S1次頻率輸出GPS結(jié)果
        option.setIgnoreKillProcess(true); // 可選,默認(rèn)true,定位SDK內(nèi)部是一個SERVICE,并放到了獨立進(jìn)程,設(shè)置是否在stop
        option.setIsNeedLocationDescribe(false); // 可選,默認(rèn)false,設(shè)置是否需要位置語義化結(jié)果,可以在BDLocation
        option.setIsNeedLocationPoiList(false); // 可選,默認(rèn)false,設(shè)置是否需要POI結(jié)果,可以在BDLocation
        option.SetIgnoreCacheException(false); // 可選,默認(rèn)false,設(shè)置是否收集CRASH信息,默認(rèn)收集
        option.setOpenGps(false); // 可選,默認(rèn)false,設(shè)置是否開啟Gps定位
        option.setIsNeedAltitude(false); // 可選,默認(rèn)false,設(shè)置定位時是否需要海拔信息,默認(rèn)不需要,除基礎(chǔ)定位版本都可用
        mBDLocationClient.setLocOption(option);
        //開啟定位
        if (mBDLocationClient != null && !mBDLocationClient.isStarted()) {
            mBDLocationClient.start();
        }
    }
    //Google-Location-Api 服務(wù)連接成功回調(diào)
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接成功了");
        getAPILastLocation();
    }
    //Google-Location-Api 服務(wù)異常連接暫停
    @Override
    public void onConnectionSuspended(int i) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)被暫停了");
        if (googleApiClient != null && !googleApiClient.isConnected())
            googleApiClient.connect();
    }
    //Google-Location-Api 連接異常
    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e("MapLastLocationUtils", "Google-Api服務(wù)連接錯誤");
        //如果連接錯誤直接用百度定位吧
        getBDLastLocation();
    }
    /**
     * 停止全部的定位
     */
    public void stopLocation() {
        if (googleApiClient != null && googleApiClient.isConnected()) {
            googleApiClient.disconnect();
        }
        if (mBDLocationClient != null) {
            if (mBDLastLocationListener != null) {
                mBDLocationClient.unRegisterLocationListener(mBDLastLocationListener);
            }
            YYLogUtils.w("定位stop了");
            mBDLocationClient.stop();
        }
    }
    private OnLocationCallbackListener mListener;
    public void setOnLocationCallbackListener(OnLocationCallbackListener listener) {
        mListener = listener;
    }
    public interface OnLocationCallbackListener {
        void onLastLocation(double lat, double lon);
    }
    /**
     * 百度的監(jiān)聽回調(diào)(最后的地址)
     */
    BDAbstractLocationListener mBDLastLocationListener = new BDAbstractLocationListener() {
        //百度定位成功的展示
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            if (bdLocation != null && bdLocation.getLocType() != BDLocation.TypeServerError &&
                    !(bdLocation.getLatitude() + "").equals("4.9E-324") &&
                    !(bdLocation.getLongitude() + "").equals("4.9E-324")) {
                double latitude = bdLocation.getLatitude();    //獲取緯度信息
                double longitude = bdLocation.getLongitude();    //獲取經(jīng)度信息
                Log.w("MapLastLocationUtils", "百度定位獲取到的最后的地址為:" + "Lat:" + latitude + " Lon:" + longitude);
                //獲取到了最后的位置-直接回調(diào)
                if (mListener != null) {
                    mListener.onLastLocation(latitude, longitude);
                }
            } else {
                Log.e("MapLastLocationUtils", "百度定位-獲取位置失敗");
                if (googleApiClient != null && !googleApiClient.isConnected()) {
                    googleApiClient.connect();
                } else {
                    getAPILastLocation();
                }
            }
        }
        @Override
        public void onConnectHotSpotMessage(String s, int i) {
            super.onConnectHotSpotMessage(s, i);
        }
        //百度定位的錯誤信息展示
        @Override
        public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) {
            super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage);
            int tag = 2;
            StringBuffer sb = new StringBuffer(256);
            sb.append("診斷結(jié)果: ");
            if (locType == BDLocation.TypeNetWorkLocation) {
                if (diagnosticType == 1) {
                    sb.append("網(wǎng)絡(luò)定位成功,沒有開啟GPS,建議打開GPS會更好");
                    sb.append("\n" + diagnosticMessage);
                } else if (diagnosticType == 2) {
                    sb.append("網(wǎng)絡(luò)定位成功,沒有開啟Wi-Fi,建議打開Wi-Fi會更好");
                    sb.append("\n" + diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeOffLineLocationFail) {
                if (diagnosticType == 3) {
                    sb.append("定位失敗,請您檢查您的網(wǎng)絡(luò)狀態(tài)");
                    sb.append("\n" + diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeCriteriaException) {
                if (diagnosticType == 4) {
                    sb.append("定位失敗,無法獲取任何有效定位依據(jù)");
                    sb.append("\n" + diagnosticMessage);
                } else if (diagnosticType == 5) {
                    sb.append("定位失敗,無法獲取有效定位依據(jù),請檢查運營商網(wǎng)絡(luò)或者Wi-Fi網(wǎng)絡(luò)是否正常開啟,嘗試重新請求定位");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 6) {
                    sb.append("定位失敗,無法獲取有效定位依據(jù),請嘗試插入一張sim卡或打開Wi-Fi重試");
                    sb.append("\n" + diagnosticMessage);
                } else if (diagnosticType == 7) {
                    sb.append("定位失敗,飛行模式下無法獲取有效定位依據(jù),請關(guān)閉飛行模式重試");
                    sb.append("\n" + diagnosticMessage);
                } else if (diagnosticType == 9) {
                    sb.append("定位失敗,無法獲取任何有效定位依據(jù)");
                    sb.append("\n" + diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeServerError) {
                if (diagnosticType == 8) {
                    sb.append("定位失敗,請確認(rèn)您定位的開關(guān)打開狀態(tài),是否賦予APP定位權(quán)限");
                    sb.append("\n" + diagnosticMessage);
                }
            }
            Log.e("MapLastLocationUtils", sb.toString());
        }
    };
    // =======================  update begin ↓ =========================
    /**
     * 開啟后臺的通知欄定位
     */
    public void startBackNotifyLocation() {
        isNeedBackNotifyLocation = true;
        if (mBDLocationClient == null) {
            mBDLocationClient = new LocationClient(mActivity);
        }
        LocationClientOption mOption = new LocationClientOption();
        mOption.setScanSpan(15000);
        mOption.setIsNeedAddress(false);
        mOption.setOpenGps(true);
        mBDLocationClient.setLocOption(mOption);
//                mClient.registerLocationListener(mBDUpdateLocationListener);
        Notification notification;
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationUtils mNotificationUtils = new NotificationUtils(mActivity);
            Notification.Builder builder2 = mNotificationUtils.getAndroidChannelNotification("YY Circle", "Locating in the background");
            builder2.setSmallIcon(R.drawable.ic_launcher_map);
            notification = builder2.build();
        } else {
            //獲取一個Notification構(gòu)造器
            Notification.Builder builder = new Notification.Builder(mActivity);
            builder.setContentTitle("YY Circle") // 設(shè)置下拉列表里的標(biāo)題
                    .setSmallIcon(R.drawable.ic_launcher_map) // 設(shè)置狀態(tài)欄內(nèi)的小圖標(biāo)
                    .setContentText("Locating in the background") // 設(shè)置上下文內(nèi)容
                    .setWhen(System.currentTimeMillis()); // 設(shè)置該通知發(fā)生的時間
            notification = builder.build(); // 獲取構(gòu)建好的Notification
        }
        notification.defaults = Notification.DEFAULT_SOUND; //設(shè)置為默認(rèn)的聲音
        //開啟前臺通知的后臺定位
        mBDLocationClient.enableLocInForeground(1, notification);
        mBDLocationClient.start();
    }
    // =======================  轉(zhuǎn)換 begin ↓ =========================
    private double pi = 3.1415926535897932384626;
    private double a = 6378245.0;
    private double ee = 0.00669342162296594323;
    /**
     * 國際 GPS84 坐標(biāo)系
     * 轉(zhuǎn)換成
     * [國測局坐標(biāo)系] 火星坐標(biāo)系 (GCJ-02)
     * <p>
     * World Geodetic System ==> Mars Geodetic System
     *
     * @param lon 經(jīng)度
     * @param lat 緯度
     * @return GPS實體類
     */
    public Gps GPS84ToGCJ02(double lon, double lat) {
        if (outOfChina(lat, lon)) {
            YYLogUtils.e("GPS84ToGCJ02:國外的坐標(biāo)不做處理");
        return new Gps(lon, lat);
        } else {
            YYLogUtils.e("GPS84ToGCJ02:處理國內(nèi)的坐標(biāo)");
            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = lat / 180.0 * pi;
            double magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
            double mgLat = lat + dLat;
            double mgLon = lon + dLon;
            return new Gps(mgLon, mgLat);
        }
    }
    /**
     * [國測局坐標(biāo)系] 火星坐標(biāo)系 (GCJ-02)
     * 轉(zhuǎn)換成
     * 國際 GPS84 坐標(biāo)系
     *
     * @param lon 火星經(jīng)度
     * @param lat 火星緯度
     */
    public Gps GCJ02ToGPS84(double lon, double lat) {
        Gps gps = transform(lon, lat);
        double lontitude = lon * 2 - gps.getLongitude();
        double latitude = lat * 2 - gps.getLatitude();
        return new Gps(lontitude, latitude);
    }
    private Gps transform(double lon, double lat) {
        if (outOfChina(lon, lat)) {
            return new Gps(lon, lat);
        }
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new Gps(mgLon, mgLat);
    }
    /**
     * 不在中國范圍內(nèi)
     *
     * @param lon 經(jīng)度
     * @param lat 緯度
     * @return boolean值
     */
    public static boolean outOfChina(double lat, double lon) {
        if (lon < 72.004 || lon > 137.8347)
            return true;
        if (lat < 0.8293 || lat > 55.8271)
            return true;
        return false;
    }
    /**
     * 緯度轉(zhuǎn)化算法
     *
     * @param x
     * @param y
     * @return
     */
    private double transformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
        return ret;
    }
    /**
     * 經(jīng)度轉(zhuǎn)化算法
     *
     * @param x
     * @param y
     * @return
     */
    private double transformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
                * pi)) * 2.0 / 3.0;
        return ret;
    }
}

三. 坐標(biāo)系轉(zhuǎn)換與地圖上的顯示

網(wǎng)上一搜坐標(biāo)系那可太多了,我們不整那么復(fù)雜,我們Android就知道2個 gcj02(中國國測局) 和 wgs84(通過坐標(biāo)系) 。由于我們不是國內(nèi)的應(yīng)用,并且集成了非單一的定位軟件,所以我們就不知道私有的坐標(biāo)系如bd09之類的。

可以看到我們上面的工具類都是使用的gcj02坐標(biāo)系定位的,在中國就需要gcj02定位,這樣比較準(zhǔn)確,如果要在對應(yīng)的地圖上展示,則需要對應(yīng)的坐標(biāo)系經(jīng)緯度,在對應(yīng)的坐標(biāo)系地圖上展示。

如我們的定位是gcj02的坐標(biāo)系,在谷歌地圖上展示則需要轉(zhuǎn)換為wgs之后才對,不然會有大概800米的誤差。百度地圖則可以設(shè)置坐標(biāo)系,設(shè)置為gcj02之后就可以在百度地圖上展示。

坐標(biāo)系的轉(zhuǎn)換工具類在上面就有了。

以上就是開箱即用的Google與百度定位坐標(biāo)系轉(zhuǎn)換實例的詳細(xì)內(nèi)容,更多關(guān)于Google 百度定位坐標(biāo)系轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論