1 Star 71 Fork 32

John-逍遥 / android_plugin_readme

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README_location.md 17.48 KB
一键复制 编辑 原始数据 按行查看 历史
johnson1 提交于 2021-01-07 15:15 . update the sensor plugin

android 位置信息获取 代码展示

以下只展示关键部分

fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.lujianfei.module_plugin_base.widget.PluginButton
        android:id="@+id/bt_click"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="点击获取位置信息"/>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <com.lujianfei.plugin10_4.widget.EmptyView
            android:id="@+id/emptyView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"/>
    </FrameLayout>
</LinearLayout>
MainFragment.kt
package com.lujianfei.plugin10_4

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Criteria
import android.location.Geocoder
import android.location.Location
import android.location.LocationManager
import android.net.Uri
import android.provider.Settings
import android.view.View
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lujianfei.module_plugin_base.utils.LogUtils
import com.lujianfei.module_plugin_base.utils.ResUtils
import com.lujianfei.plugin10_4.adapter.MainAdapter
import com.lujianfei.plugin10_4.base.BaseFragment
import com.lujianfei.plugin10_4.bean.MainBean
import com.lujianfei.plugin10_4.utils.LocationUtils
import com.lujianfei.plugin10_4.widget.EmptyView
import java.util.*

class MainFragment: BaseFragment() {

    companion object {
        const val REQUEST_PERMISSION = 100
        const val TAG = "MainFragment"
        const val PERMISSION1 = Manifest.permission.ACCESS_COARSE_LOCATION
        const val PERMISSION2 = Manifest.permission.ACCESS_FINE_LOCATION
    }

    private var bt_click: com.lujianfei.module_plugin_base.widget.PluginButton? = null
    private var locationManager:LocationManager ?= null
    private var mProvider:String ?= null
    private var emptyView:EmptyView ?= null
    private var recyclerview: RecyclerView ?= null
    private val mAdapter by lazy { MainAdapter() }

    override fun resourceId() = R.layout.fragment_main

    override fun initView() {
        emptyView = findViewById(R.id.emptyView)
        bt_click = findViewById(R.id.bt_click)
        recyclerview = findViewById(R.id.recyclerview)
        recyclerview?.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = mAdapter
        }
    }

    override fun initData() {
        locationManager = context?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        val mCriteria = Criteria()
        mCriteria.apply {
            accuracy = Criteria.ACCURACY_COARSE
            // 设置不需要获取海拔方向数据
            isAltitudeRequired = false
            isBearingRequired = false
            // 设置允许产生资费
            isCostAllowed = true
            // 要求低耗电
            powerRequirement = Criteria.POWER_LOW
        }
        mProvider = locationManager?.getBestProvider(mCriteria, true)
        LogUtils.d(TAG, "mProvider: $mProvider")
    }

    override fun initEvent() {
        bt_click?.setOnClickListener {
            checkGPSPermission {
                getLocation()
            }
        }
    }

    private fun checkGPSPermission(hasPermission:(()->Unit)) {
        context?.let {
            if (ActivityCompat.checkSelfPermission(it, PERMISSION1) != PackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(it, PERMISSION2) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
                        arrayOf(PERMISSION1,PERMISSION2),
                        REQUEST_PERMISSION)
            } else {
                hasPermission.invoke()
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun getLocation() {
        var longitude = 0.0
        var latitude = 0.0

        emptyView?.visibility = View.GONE

        val data = arrayListOf<MainBean>()
        // WGS84
        val lastKnownLocation = locationManager?.getLastKnownLocation(mProvider ?: LocationManager.NETWORK_PROVIDER)
        data.add(MainBean(title = "WGS84", location = "${lastKnownLocation?.longitude},${lastKnownLocation?.latitude}",summary = "真实 GPS 坐标"))

        longitude = lastKnownLocation?.longitude ?: 0.0
        latitude = lastKnownLocation?.latitude ?: 0.0

        // BD09
        val bd09 = Location(lastKnownLocation)
        LocationUtils.wgs84_to_bd09(lastKnownLocation, bd09)
        data.add(MainBean(title = "BD09", location = "${bd09.longitude},${bd09.latitude}",summary = "百度地图坐标系"))
        // GCJ02
        val gcj02 = Location(lastKnownLocation)
        LocationUtils.wgs84_to_gcj02(lastKnownLocation, gcj02)
        data.add(MainBean(title = "GCJ02", location = "${gcj02.longitude},${gcj02.latitude}",summary = "火星坐标系 (腾讯地图使用坐标)"))

        getGeoInfo(data, longitude, latitude)
        mAdapter.setData(data)
    }

    private fun getGeoInfo(data: ArrayList<MainBean>, longitude:Double, latitude:Double) {
        val mGeocoder = Geocoder(context, Locale.CHINESE)
        kotlin.runCatching {
            val fromLocation = mGeocoder.getFromLocation(latitude, longitude, 1)
            if (fromLocation?.isNotEmpty() == true) {
                val location = fromLocation[0]
                LogUtils.d(TAG, "getGeoInfo location:$location")
                val country = location.countryName
                val province = location.adminArea
                val city = location.locality
                val district = location.subLocality
                val building = location.featureName
                val detail = "${country},${province},${city},$district,$building"
                data.add(MainBean(title = "坐标反查地理信息", location = "反地理查询" ,summary = "具体地址:$detail", type = MainBean.TYPE_CUSTOM))
            }
        }.onFailure {
            LogUtils.e(TAG,"getGeoInfo $it")
        }
    }

    override fun updateTitle(title: String?) {
    }

    override fun onTitleRightClick(that: Activity?, view: View?) {
    }

    override fun release() {
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        LogUtils.d(TAG, "onRequestPermissionsResult ${grantResults.size}")
        when(requestCode) {
            REQUEST_PERMISSION -> {
                var granted = true
                for (grant in grantResults) {
                    LogUtils.d(TAG, "grant = $grant")
                    if (grant == PackageManager.PERMISSION_DENIED) {
                        granted = false
                    }
                }
                LogUtils.d(TAG, "granted = $granted")
                if (granted) {
                    getLocation()
                } else {
                    emptyView?.apply {
                        visibility = View.VISIBLE
                        onButtonClickListener = {
                            startAppDetailsInfo()
                        }
                        setText("定位权限未开启,前往开启")
                        setButtonText("GO")
                        showButton()
                    }
                }
            }
        }
    }

    private fun startAppDetailsInfo() {
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.data = Uri.parse("package:" + ResUtils.context?.packageName)
        startActivity(intent)
    }
}
adapter_location_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:padding="10dp">

    <TextView
        android:id="@+id/txt_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="23sp"
        tools:text="GPS"
        android:textStyle="bold"
        />

    <TextView
        android:id="@+id/txt_location_lbl"
        android:layout_below="@id/txt_title"
        android:layout_marginTop="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:text="经纬度:"/>
    <TextView
        android:id="@+id/txt_location"
        android:layout_toEndOf="@id/txt_location_lbl"
        android:layout_alignTop="@id/txt_location_lbl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textIsSelectable="true"
        android:textSize="18sp"
        android:text="123.34534,345345345.6565"
        />
    <TextView
        android:id="@+id/txt_summary_lbl"
        android:layout_below="@id/txt_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:textSize="18sp"
        android:text="备注:"/>

    <TextView
        android:id="@+id/txt_summary"
        android:layout_toEndOf="@id/txt_summary_lbl"
        android:layout_alignTop="@id/txt_summary_lbl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        tools:text="腾讯地图"/>
</RelativeLayout>
MainAdapter.kt
package com.lujianfei.plugin10_4.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.lujianfei.plugin10_4.R
import com.lujianfei.plugin10_4.bean.MainBean

class MainAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    var mData = arrayListOf<MainBean>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.adapter_location_item, parent, false))
    }

    override fun getItemCount(): Int = mData.size

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is MyViewHolder) {
            holder.setData(mData[position])
        }
    }

    fun setData(mData: List<MainBean>) {
        this.mData.clear()
        this.mData.addAll(mData)
        notifyDataSetChanged()
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        private var txt_title: TextView? = null
        private var txt_location_lbl: TextView? = null
        private var txt_location: TextView? = null
        private var txt_summary_lbl: TextView? = null
        private var txt_summary: TextView? = null

        init {
            txt_title = itemView.findViewById(R.id.txt_title)
            txt_location_lbl = itemView.findViewById(R.id.txt_location_lbl)
            txt_location = itemView.findViewById(R.id.txt_location)
            txt_summary_lbl = itemView.findViewById(R.id.txt_summary_lbl)
            txt_summary = itemView.findViewById(R.id.txt_summary)
        }

        fun setData(bean: MainBean) {
            when(bean.type) {
                MainBean.TYPE_CUSTOM -> {
                    txt_location_lbl?.text = ""
                    txt_summary_lbl?.text = ""
                }
                MainBean.TYPE_DEFAULT-> {
                    txt_location_lbl?.text = "经纬度:"
                    txt_summary_lbl?.text = "备注:"
                }
            }
            txt_title?.text = bean.title
            txt_location?.text = bean.location
            txt_summary?.text = bean.summary
        }
    }
}

实体类

MainBean.kt
package com.lujianfei.plugin10_4.bean

data class MainBean (
        val type:Int = TYPE_DEFAULT, // 0:默认样式,1:自定义
        val title:String,
        val location:String,
        val summary:String
) {
    companion object {
        const val TYPE_DEFAULT = 0
        const val TYPE_CUSTOM = 1
    }
}

下面是坐标转换核心类

LocationUtils.kt
package com.lujianfei.plugin10_4.utils

import android.location.Location
import android.location.LocationManager
import android.util.Log
import com.lujianfei.module_plugin_base.utils.LogUtils
import kotlin.math.*

/**
 *@date     创建时间:2020/9/2
 *@name     作者:陆键霏
 *@describe 描述:
 */
object LocationUtils {

    private const val TAG = "LocationUtils"
    private const val EARTH_RADIUS = 6378137.0
    private const val a = 6378245.0
    private const val ee = 0.00669342162296594323
    private const val x_PI = 3.14159265358979324 * 3000.0 / 180.0

    fun getDistance(loc1: Location?, loc2: Location?): Double {
        if (loc1 == null || loc2 == null) return 0.0
        return getDistance(loc1.longitude, loc1.latitude, loc2.longitude, loc2.latitude)
    }

    fun getDistance(
        longitude: Double,
        latitue: Double,
        longitude2: Double,
        latitue2: Double
    ): Double {
        val lat1 = rad(latitue)
        val lat2 = rad(latitue2)
        val a = lat1 - lat2
        val b = rad(longitude) - rad(longitude2)
        var s = 2 * asin(
            sqrt(
                sin(a / 2).pow(2.0) + cos(lat1) * cos(lat2) * sin(
                    b / 2
                ).pow(2.0)
            )
        )
        s *= EARTH_RADIUS
        s = (s * 10000).roundToInt() / 10000.toDouble()
        return s
    }

    private fun rad(d: Double): Double {
        return d * Math.PI / 180.0
    }

    /**
     * WGS84 转 GCJ02(火星坐标系)
     */
    fun wgs84_to_gcj02(origin: Location?, out: Location?) {
        origin?.let {
            LogUtils.d(TAG, "wgs84_to_gcj02 in (${origin.longitude},${origin.latitude})")
            val lng = origin.longitude
            val lat = origin.latitude
            var dlat = transformlat(lng - 105.0, lat - 35.0)
            var dlng = transformlng(lng - 105.0, lat - 35.0)
            val radlat = lat / 180.0 * PI
            var magic = sin(radlat)
            magic = 1 - ee * magic * magic
            val sqrtmagic = sqrt(magic)
            dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
            dlng = (dlng * 180.0) / (a / sqrtmagic * cos(radlat) * PI)
            val mglat = lat + dlat
            val mglng = lng + dlng
            out?.latitude = mglat
            out?.longitude = mglng
            LogUtils.d(TAG, "wgs84_to_gcj02 out (${out?.longitude},${out?.latitude})")
        }
    }
    /**
     * WGS84 坐标转换为 百度坐标系
     */
    fun wgs84_to_bd09(origin: Location?,out: Location?) {
        origin?.let {
            LogUtils.d(TAG, "wgs84_to_bd09 in (${origin.longitude},${origin.latitude})")
            val lng = origin.longitude
            val lat = origin.latitude
            //第一次转换
            var dlat = transformlat(lng - 105.0, lat - 35.0)
            var dlng = transformlng(lng - 105.0, lat - 35.0)
            val radlat = lat / 180.0 * PI
            var magic = sin(radlat)
            magic = 1 - ee * magic * magic
            val sqrtmagic = sqrt(magic)
            dlat = dlat * 180.0 / (a * (1 - ee) / (magic * sqrtmagic) * PI)
            dlng = dlng * 180.0 / (a / sqrtmagic * Math.cos(radlat) * PI)
            val mglat = lat + dlat
            val mglng = lng + dlng
            //第二次转换
            val z = sqrt(mglng * mglng + mglat * mglat) + 0.00002 * sin(mglat * x_PI)
            val theta = atan2(mglat, mglng) + 0.000003 * cos(mglng * x_PI)
            val bd_lng = z * cos(theta) + 0.0065
            val bd_lat = z * sin(theta) + 0.006
            out?.longitude = bd_lng
            out?.latitude = bd_lat
            LogUtils.d(TAG, "wgs84_to_bd09 out (${out?.longitude},${out?.latitude})")
        }
    }

    private fun transformlat(lng: Double, lat: Double): Double {
        var ret =
            -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * sqrt(
                abs(lng)
            )
        ret += (20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0 / 3.0
        ret += (20.0 * sin(lat * PI) + 40.0 * sin(lat / 3.0 * PI)) * 2.0 / 3.0
        ret += (160.0 * sin(lat / 12.0 * PI) + 320 * sin(lat * PI / 30.0)) * 2.0 / 3.0
        return ret
    }

    private fun transformlng(lng: Double, lat: Double): Double {
        var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * sqrt(
            abs(lng)
        )
        ret += (20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0 / 3.0
        ret += (20.0 * sin(lng * PI) + 40.0 * sin(lng / 3.0 * PI)) * 2.0 / 3.0
        ret += (150.0 * sin(lng / 12.0 * PI) + 300.0 * sin(lng / 30.0 * PI)) * 2.0 / 3.0
        return ret
    }

}
Android
1
https://gitee.com/lujianfei/android_plugin_readme.git
git@gitee.com:lujianfei/android_plugin_readme.git
lujianfei
android_plugin_readme
android_plugin_readme
master

搜索帮助