开发者社区> 问答> 正文

Android中的地理标记

我正在开发一个需要用户能够对通过相机拍摄的照片进行地理标记的应用程序。该应用程序旨在鼓励用户对树进行地理标记,以鼓励造林并减少全球变暖。

是否可以实现此功能,我该如何实现?

注意:这是我的第一个主要项目。

展开
收起
垚tutu 2019-11-28 19:28:36 945 0
1 条回答
写回答
取消 提交回答
  • #include

    创建具有位置感的舒适用户体验是一项艰巨的任务。这些是您必须解决的一些问题:

    该应用可能没有使用位置的权限。 您想请求用户许可。 您不想一遍又一遍地打扰用户。 寻求许可意味着暂停您的活动,而转向需要许可的系统活动。 当用户响应时,您的活动将恢复,您需要重写一个特殊的回调方法来接收结果。 仅在需要时询问位置是不好的。可能需要一些时间。相反,您必须请求Android向您推送位置更新。 用户在使用应用程序时可能会撤销位置权限,您必须不断地重新检查权限,以应对突发异常,并在位置权限恢复时重复请求以接收位置更新。 以下是我项目中的一些片段,可以帮助您入门:

    private val Context.fusedLocationProviderClient get() = getFusedLocationProviderClient(this)
    
    private suspend fun FusedLocationProviderClient.tryFetchLastLocation(): Location? =
        lastLocation.await()
            ?.also { info { "Got response from getLastLocation()" } }
            ?: run { warn { "getLastLocation() returned null" }; null }
    
    suspend fun Context.canUseLocationFg() =
            appHasLocationPermission() && 
            locationSettingsException(locationRequestFg, locationRequestBg) == null
    
    
    import android.Manifest.permission.ACCESS_FINE_LOCATION
    import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
    
    fun Context.appHasLocationPermission() =
            checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED
    
    suspend fun Context.locationSettingsException(
            vararg locationRequests: LocationRequest
    ): ApiException? = try {
        getSettingsClient(this)
                .checkLocationSettings(LocationSettingsRequest.Builder()
                        .addAllLocationRequests(locationRequests.asList()).build())
                .await()
        null
    } catch (e: ApiException) { e }
    
    
    const val CODE_REQUEST_FINE_LOCATION = 13
    const val CODE_RESOLVE_API_EXCEPTION = 14
    
    suspend fun Fragment.checkAndCorrectPermissionsAndSettings() {
        with(context!!) {
            if (!appHasLocationPermission()) {
                warn { "FG: our app has no permission to access fine location" }
                delay(WAIT_MILLISECONDS_BEFORE_ASKING)
                if (!appHasLocationPermission()) {
                    startIntentRequestLocationPermission()
                    return
                }
            }
            if (locationSettingsException(locationRequestFg, locationRequestBg) == null) return
            warn { "FG: ResolvableApiException for location request (probably location disabled)" }
            if (!mainPrefs.shouldAskToEnableLocation) return
            delay(WAIT_MILLISECONDS_BEFORE_ASKING)
            locationSettingsException(locationRequestFg, locationRequestBg)
                    ?.let { it as? ResolvableApiException }
                    ?.also { startIntentResolveException(it) }
        }
    }
    
    fun Fragment.startIntentRequestLocationPermission() =
            requestPermissions(arrayOf(ACCESS_FINE_LOCATION), CODE_REQUEST_FINE_LOCATION)
    
    fun Fragment.startIntentResolveException(e: ResolvableApiException) =
            startIntentSenderForResult(e.resolution.intentSender, CODE_RESOLVE_API_EXCEPTION, null, 0, 0, 0, null)
    
    
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if (requestCode != CODE_REQUEST_FINE_LOCATION) return
        permissions.zip(grantResults.asList())
            .find { (perm, _) -> perm == ACCESS_FINE_LOCATION }
            ?.also { (_, result) ->
                if (result == PermissionChecker.PERMISSION_GRANTED) {
                    info { "User has granted us the fine location permission" }
                } else {
                    warn { "User hasn't granted us the fine location permission (grant result: ${grantResults[0]})" }
                }
            }
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode != CODE_RESOLVE_API_EXCEPTION) return
        if (resultCode == Activity.RESULT_OK) {
            info { "ResolvableApiException is now resolved" }
        } else {
            warn { "ResolvableApiException resolution failed with code $resultCode" }
            activity!!.mainPrefs.applyUpdate { setShouldAskToEnableLocation(false) }
        }
    }
    
    
    val locationRequestFg = LocationRequest().apply {
        interval = 1000
        fastestInterval = 10
        priority = PRIORITY_BALANCED_POWER_ACCURACY
    }
    
    suspend fun Context.receiveLocationUpdatesFg(locationState: LocationState) {
        fusedLocationProviderClient.apply {
            tryFetchLastLocation()?.also {
                info { "lastLocation: ${it.description}" }
                locationState.location = it
            }
            LocationCallbackFg.locationState = locationState
            requestLocationUpdates(locationRequestFg, LocationCallbackFg, null).await()
            info(CC_PRIVATE) { "FG: started receiving location updates" }
        }
    }
    
    object LocationCallbackFg : LocationCallback() {
        var locationState: LocationState? = null
    
        override fun onLocationResult(result: LocationResult) {
            val lastLocation = result.lastLocation
            info { "FG: received location ${lastLocation.description}" }
            locationState?.apply { location = lastLocation }
                    ?: warn { "LocationCallbackFg received an event while not in use" }
        }
    }
    
    

    代码依赖Task.await(),这在Kotlin的库中kotlinx-coroutines-play-services。

    2019-11-28 19:29:58
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
58同城Android客户端Walle框架演进与实践之路 立即下载
Android组件化实现 立即下载
蚂蚁聚宝Android秒级编译——Freeline 立即下载