{"id":18565072,"url":"https://github.com/jenly1314/location","last_synced_at":"2025-08-18T07:31:30.207Z","repository":{"id":57720446,"uuid":"404673738","full_name":"jenly1314/Location","owner":"jenly1314","description":":round_pushpin: Location 是一个通过 Android 自带的 LocationManager 来实现的定位功能","archived":false,"fork":false,"pushed_at":"2025-07-05T01:53:38.000Z","size":2817,"stargazers_count":77,"open_issues_count":0,"forks_count":20,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-05T03:06:54.399Z","etag":null,"topics":["android","gps","gps-location","kotlin","latlng","location","location-manager"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenly1314.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-09-09T10:09:59.000Z","updated_at":"2025-07-05T01:53:41.000Z","dependencies_parsed_at":"2024-06-21T00:00:17.533Z","dependency_job_id":"dfac5366-2d10-4505-8da0-2b3fd2e05d6b","html_url":"https://github.com/jenly1314/Location","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jenly1314/Location","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLocation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLocation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLocation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLocation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenly1314","download_url":"https://codeload.github.com/jenly1314/Location/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenly1314%2FLocation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270961525,"owners_count":24675914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","gps","gps-location","kotlin","latlng","location","location-manager"],"created_at":"2024-11-06T22:17:35.764Z","updated_at":"2025-08-18T07:31:30.198Z","avatar_url":"https://github.com/jenly1314.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Location\n\n![Image](app/src/main/ic_launcher-playstore.png)\n\n[![MavenCentral](https://img.shields.io/maven-central/v/com.github.jenly1314/location?logo=sonatype)](https://repo1.maven.org/maven2/com/github/jenly1314/Location)\n[![JitPack](https://img.shields.io/jitpack/v/github/jenly1314/Location?logo=jitpack)](https://jitpack.io/#jenly1314/Location)\n[![CI](https://img.shields.io/github/actions/workflow/status/jenly1314/Location/gradle.yml?logo=github)](https://github.com/jenly1314/Location/actions/workflows/gradle.yml)\n[![Download](https://img.shields.io/badge/download-APK-brightgreen?logo=github)](https://raw.githubusercontent.com/jenly1314/Location/master/app/release/app-release.apk)\n[![API](https://img.shields.io/badge/API-21%2B-brightgreen?logo=android)](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)\n[![License](https://img.shields.io/github/license/jenly1314/Location?logo=open-source-initiative)](https://opensource.org/licenses/mit)\n\n\nLocation 是一个通过 Android 自带的 LocationManager 来实现的定位功能。\n\n\u003e 之所以写这个库的主要原因还需要从下面的场景说起：在开发某个App的过程当中，可能有个需求需要用到定位功能，但是又不那么重要；\n这个时候如果选择使用第三方的定位服务，需要先去申请相关的appKey和集成定位相关的SDK，显得太繁琐了。杀鸡焉用宰牛刀，我们只是需要一个简单的定位功能，使用自带的实现不香吗？因此就有了 **Location**。\n\n## 效果展示\n![Image](GIF.gif)\n\n\u003e 你也可以直接下载 [演示App](https://raw.githubusercontent.com/jenly1314/Location/master/app/release/app-release.apk) 体验效果\n\n## 引入\n\n### Gradle:\n\n1. 在Project的 **build.gradle** 或 **setting.gradle** 中添加远程仓库\n\n    ```gradle\n    repositories {\n        //...\n        mavenCentral()\n    }\n    ```\n\n2. 在Module的 **build.gradle** 中添加依赖项\n\n    ```gradle\n    implementation 'com.github.jenly1314:location:1.0.0'\n    ```\n\n## 使用\n\n### 示例\n\n主要方法调用示例\n```kotlin\n     \n    //初始化实例\n    val locationClient = LocationClient(this)\n\n    //可根据具体需求设置定位配置参数\n    val locationOption = locationClient.getLocationOption()\n        .setAccuracy(Criteria.ACCURACY_FINE)//设置位置精度：高精度\n        .setMinTime(10000)//设置位置更新最小时间间隔（单位：毫秒）； 默认间隔：10000毫秒，最小间隔：1000毫秒\n        .setOnceLocation(false)//设置是否只定位一次，默认为 false，当设置为 true 时，则只定位一次后，会自动停止定位\n\n    //设置定位配置参数\n    locationClient.setLocationOption(locationOption)\n\n    //----------------------------------\n\n    //设置定位监听\n    locationClient.setOnLocationListener(object: OnLocationListener(){\n        override fun onLocationChanged(location: Location) {\n            //TODO 位置信息\n        }\n\n    })\n\n    //----------------------------------\n\n    //开始定位（建议先校验是否有定位权限，然后开始定位）\n    locationClient.startLocation()\n\n    //----------------------------------\n    \n    //停止定位\n    locationClient.stopLocation()\n\n```\n\n完整示例\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n    private val binding by lazy {\n        ActivityMainBinding.inflate(layoutInflater)\n    }\n\n    private val locationClient by lazy {\n        LocationClient(this)\n    }\n\n    private val geocoder by lazy {\n        Geocoder(this)\n    }\n\n    private val simpleDateFormat by lazy {\n        SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\")\n    }\n\n    private var isPermissionGranted = false\n\n    companion object{\n        const val TAG = \"MainActivity\"\n        const val REQ_LOCATION_PERMISSION = 0x01\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(binding.root)\n\n        binding.btnStartLocation.setOnClickListener {\n            isPermissionGranted = checkLocationPermission()\n            if(isPermissionGranted){\n                startLocation()\n            }else{\n                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQ_LOCATION_PERMISSION)\n            }\n        }\n\n        binding.btnStopLocation.setOnClickListener {\n            locationClient.stopLocation()\n            binding.tvLocation.text = \"\"\n        }\n\n        binding.cbOnceLocation.setOnCheckedChangeListener { buttonView, isChecked -\u003e\n            locationClient.getLocationOption().setOnceLocation(isChecked)\n        }\n\n        binding.cbLastKnownLocation.setOnCheckedChangeListener { buttonView, isChecked -\u003e\n            locationClient.getLocationOption().setLastKnownLocation(isChecked)\n        }\n\n        //可根据具体需求设置定位配置参数（这里只列出一些主要的参数）\n        val locationOption = locationClient.getLocationOption()\n            .setAccuracy(Criteria.ACCURACY_FINE)//设置位置精度：高精度\n            .setPowerRequirement(Criteria.POWER_LOW) //设置电量消耗：低电耗\n            .setMinTime(10000)//设置位置更新最小时间间隔（单位：毫秒）； 默认间隔：10000毫秒，最小间隔：1000毫秒\n            .setMinDistance(0)//设置位置更新最小距离（单位：米）；默认距离：0米\n            .setOnceLocation(false)//设置是否只定位一次，默认为 false，当设置为 true 时，则只定位一次后，会自动停止定位\n            .setLastKnownLocation(true)//设置是否获取最后一次缓存的已知位置，默认为 true\n        //设置定位配置参数\n        locationClient.setLocationOption(locationOption)\n\n        //设置定位监听\n        locationClient.setOnLocationListener(object: OnLocationListener(){\n            override fun onLocationChanged(location: Location) {\n                //位置信息\n                Log.d(TAG,\"onLocationChanged(location = ${location})\")\n                val builder = StringBuilder()\n                builder.append(\"Longitude: \\t${location.longitude}\\n\")\n                    .append(\"Latitude: \\t${location.latitude}\\n\")\n\n                //根据坐标经纬度获取位置地址信息（WGS-84坐标系）\n                val list = geocoder.getFromLocation(location.latitude,location.longitude,1)\n                if(list.isNotEmpty()){\n                    builder.append(\"Address: \\t${list[0].getAddressLine(0)}\\n\")\n                }\n\n                builder.append(\"Time: \\t${simpleDateFormat.format(Date(location.time))}\\n\")\n                    .append(\"Provider: \\t${location.provider}\\n\")\n\n                binding.tvLocation.text = builder.toString()\n            }\n\n            override fun onProviderEnabled(provider: String) {\n                super.onProviderEnabled(provider)\n                Log.d(TAG,\"onProviderEnabled(provider = ${provider})\")\n            }\n\n            override fun onProviderDisabled(provider: String) {\n                super.onProviderDisabled(provider)\n                Log.d(TAG,\"onProviderDisabled(provider = ${provider})\")\n            }\n\n        })\n\n        //设置异常监听\n        locationClient.setOnExceptionListener(object : OnExceptionListener{\n            override fun onException(@LocationErrorCode errorCode: Int, e: Exception) {\n                //定位出现异常\n                Log.w(TAG,\"onException(errorCode = ${errorCode}, e = ${e})\")\n                binding.tvLocation.text = e.message\n            }\n        })\n    }\n\n    override fun onResume() {\n        super.onResume()\n        if(!isPermissionGranted){\n            if(checkLocationPermission()){\n                isPermissionGranted = true\n                binding.tvLocation.text = \"\"\n            }\n        }\n    }\n\n    /**\n     * 开始定位\n     */\n    private fun startLocation(){\n        if(locationClient.isStarted()){//如果已经开始定位，则先停止定位\n            locationClient.stopLocation()\n        }\n        binding.tvLocation.text = \"Start location...\"\n        locationClient.startLocation()\n\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array\u003cout String\u003e,\n        grantResults: IntArray\n    ) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        if(requestCode == REQ_LOCATION_PERMISSION){\n            isPermissionGranted = verifyPermissions(grantResults)\n            if(isPermissionGranted){//已授权\n                startLocation()\n            }else{//未授权\n                binding.tvLocation.text = \"Location permission has not been granted.\"\n                showMissingPermissionDialog()\n            }\n        }\n    }\n\n    /**\n     * 检测位置权限\n     */\n    private fun checkLocationPermission(): Boolean{\n        return ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED\n    }\n\n    /**\n     * 校验授权结果\n     */\n    private fun verifyPermissions(grantResults: IntArray): Boolean{\n        for(result in grantResults){\n            if(result != PackageManager.PERMISSION_GRANTED){\n                return false\n            }\n        }\n        return true\n    }\n\n    /**\n     * 显示未授权提示对话框\n     */\n    private fun showMissingPermissionDialog(){\n        val builder = AlertDialog.Builder(this)\n        builder.setMessage(\"Location permission has not been granted.\")\n            .setNegativeButton(\"Cancel\"\n            ) { dialog, which -\u003e\n\n            }\n            .setPositiveButton(\"Setting\"\n            ) { dialog, which -\u003e\n                startAppSettings()\n            }\n        builder.show()\n    }\n\n\n    /**\n     * 跳转到 App 的设置详情界面\n     */\n    private fun startAppSettings(){\n        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)\n        intent.data = Uri.parse(\"package:${packageName}\")\n        startActivity(intent)\n    }\n\n}\n\n```\n\n在你项目的 **AndroidManifest.xml** 清单文件中添加定位相关权限\n```xml\n    \u003c!-- 允许程序访问CellID或WiFi热点来获取粗略的位置 --\u003e\n    \u003cuses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" /\u003e\n    \u003c!-- 用于访问GPS定位 --\u003e\n    \u003cuses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" /\u003e\n\n```\n\n更多使用详情，请查看[app](app)中的源码使用示例或直接查看[API帮助文档](https://jitpack.io/com/github/jenly1314/Location/latest/javadoc/)\n\n## 相关推荐\n- [MapHelper](https://github.com/jenly1314/MapHelper) 一个整合了高德地图、百度地图、腾讯地图、谷歌地图等相关路线规划和导航的地图帮助类库。\n\n## 版本日志\n\n#### v1.0.0：2021-9-9\n*  Location初始版本\n\n---\n\n![footer](https://jenly1314.github.io/page/footer.svg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenly1314%2Flocation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenly1314%2Flocation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenly1314%2Flocation/lists"}