我在Kotlin工作,我的片段位于一个活动中。因此,当我运行我的应用程序并打开位置片段时,它会询问我许可,但立即崩溃,因此我无法允许或拒绝该许可。
这是我的位置片段代码:
package com.example.atry.MakeComplaint
import android.app.Activity
import android.app.Activity.RESULT_OK
import com.example.atry.Retrofit.INodeJS
import com.example.atry.Retrofit.Observables
import com.example.atry.Retrofit.RetrofitClient
import android.content.Context
import android.content.IntentSender
import android.content.pm.PackageManager
import android.location.*
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Switch
import android.widget.Toast
import com.google.android.gms.maps.MapView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.atry.R
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.*
import com.google.android.gms.maps.*
import com.google.android.gms.maps.model.*
import kotlinx.android.synthetic.main.fragment_location.view.*
import retrofit2.Call
import retrofit2.Response
class LocationFragment : Fragment(), OnMapReadyCallback, GoogleMap.OnMarkerClickListener {
override fun onMarkerClick(p0: Marker?)= false
private lateinit var map: GoogleMap
private lateinit var mapView : MapView
private lateinit var restrict:LatLngBounds
lateinit var myAPI: INodeJS
var MyCategory: Observables.Complainttype?=null
private var listener: OnLocationFragmentInteractionListener? = null
var makeComplaintobject1:Observables.final?=null
lateinit var typename:String
var objectComplaint =
Observables.Complaint(
1 , "dummy problem" ,
"url" ,
Observables.Location("78.4","17.4"),
Observables.ComplaintTypes("Smell" ),
Observables.Status( "Unresolved")
)
//for updating user's location/ for current location
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback
// private lateinit var lastLocation: Location
var lastLocation:Location?=null
private var locationUpdateState = false
companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1
private const val REQUEST_CHECK_SETTINGS = 2 //For updating user's location as they move
}
fun sendCategoryItem(category: Observables.Complainttype) {
//receiving the category selected from Category Fragment
this.MyCategory = category
Log.d("here", "i am here 1")
Log.d("here", MyCategory.toString())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
if (locationResult.locations.isNotEmpty()) {
// get latest location and sets it on the map
lastLocation = locationResult.lastLocation
Log.d("lastlocation", lastLocation.toString())
placeMarkerOnMap(LatLng(lastLocation!!.latitude, lastLocation!!.longitude))
} } }
getLocationUpdates()
//INIT API
val retrofit = RetrofitClient.instanc
myAPI = retrofit.create(INodeJS::class.java)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(R.layout.fragment_location, container, false)
mapView = v.findViewById(R.id.maps)
mapView.onCreate(savedInstanceState)
mapView.onResume()
try {
MapsInitializer.initialize(getActivity()!!.getApplicationContext())
} catch (sendEx: IntentSender.SendIntentException) {
sendEx.printStackTrace()
}
mapView.getMapAsync(this)
v.backToList.setOnClickListener {
backFragment()
}
v.forwardToDescription.setOnClickListener{
//will proceed to the Category Description fragment only if the lastLocation isn't null
getAllData()
}
return v
}
private fun setUpMap() {
if (activity!!.checkSelfPermission(
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
return
}
}
private fun checkForPermissions(){
if(activity!!.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
requestPermissions( arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
}
startLocationUpdates()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(grantResults.size >0){
if(requestCode== LOCATION_PERMISSION_REQUEST_CODE && grantResults[0] == PackageManager.PERMISSION_GRANTED){
locationUpdateState=true
checkForPermissions()
}
}
}
/**
* call this method in onCreate
* onLocationResult call when location is changed
*/
private fun getLocationUpdates() {
//with fusedLocationClient
// fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)
locationRequest = LocationRequest()
locationRequest.interval = 1000
locationRequest.fastestInterval = 5000
locationRequest.smallestDisplacement = 170f // 170 m = 0.1 mile
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY //set according to your app function
val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val client = LocationServices.getSettingsClient(context!!)
val task = client.checkLocationSettings(builder.build())
//can update the map if location services on
task.addOnSuccessListener {
locationUpdateState=true
checkForPermissions()
}
task.addOnFailureListener { e ->
//check if the location settings is on yet
if(e is ResolvableApiException){
try{
e.startResolutionForResult(activity, REQUEST_CHECK_SETTINGS)
}catch (sendEx : IntentSender.SendIntentException){
}
}
}
}
//Places the marker on the map and changes its style.
private fun placeMarkerOnMap(location: LatLng) {
// 1
val markerOptions = MarkerOptions().position(location)
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))
// 2
map.addMarker(markerOptions)
}
//start location updates
private fun startLocationUpdates() {
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
null /* Looper */
)
}
// stop location updates
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
// start receiving location update when activity visible/foreground
override fun onResume() {
super.onResume()
mapView.onResume()
checkForPermissions()
// startLocationUpdates()
}
// stop receiving location update when activity not visible/foreground
override fun onPause() {
super.onPause()
mapView.onPause()
stopLocationUpdates()
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
override public fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
override fun onMapReady(googleMap: GoogleMap?) {
map = googleMap!!
map.uiSettings?.isZoomControlsEnabled = true
setUpMap()
map.isMyLocationEnabled = true
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
//updating the map with user's current location
if (location !=null){
lastLocation = location
val currentLatLng = LatLng(location.latitude,location.longitude)
placeMarkerOnMap(currentLatLng)
map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng,12f))
}
}
}
private fun backFragment() {
val manager = (context as AppCompatActivity).supportFragmentManager
manager.popBackStackImmediate()
}
fun getAllData(){
//
// val latitude = 17.4
// val longitude = 78.4
// LocationUtils().getInstance(appContext)
// LocationUtils().getLocation().observe(this, Observer {loc: Location? ->
// location = loc!!
// // Yay! location recived. Do location related work here
// Log.i(TAG,"Location: ${location.latitude} ${location.longitude}")
//
// })
if(lastLocation!=null){
makeComplaintobject1 = Observables.final(
Observables.ComplaintTypes(MyCategory!!.typeName),
// Observables.Location(lastLocation.longitude.toString(),lastLocation.latitude.toString()) //lateinit wala
Observables.Location(lastLocation!!.longitude.toString(),lastLocation!!.latitude.toString())
)
}
else{
makeComplaintobject1 = Observables.final(
Observables.ComplaintTypes(MyCategory!!.typeName),
// Observables.Location(lastLocation.longitude.toString(),lastLocation.latitude.toString()) //lateinit wala
Observables.Location("","")
)
}
typename = MyCategory!!.typeName
val call = myAPI.checkExistingComplain(typename,makeComplaintobject1!!.finalLocation.longitude, makeComplaintobject1!!.finalLocation.latitude ) //new
Log.d("T", typename)
Log.d("Lo", makeComplaintobject1!!.finalLocation.longitude)
Log.d("La", makeComplaintobject1!!.finalLocation.latitude)
call.enqueue(object : retrofit2.Callback<Observables.checkExistingResult> {
override fun onFailure(call: Call<Observables.checkExistingResult>?, t: Throwable?) {
Log.d("NO", t!!.message)
}
override fun onResponse(call: Call<Observables.checkExistingResult>?, response: Response<Observables.checkExistingResult>?) {
Log.d("response popup", response!!.code().toString())
//
if(response.code() == 200){
Log.d("YES", response.code().toString())
Log.d("response", response.body().toString())
if(response.body()!!.Complain === null){
//if type and location are in db but does not match
Log.d("null",response.body()!!.Complain.toString())
var item1 = makeComplaintobject1
Log.d("wohoooooo",makeComplaintobject1.toString())
listener!!.onLocationFragmentInteraction1(item1!!) // typeName and location going to category description
}
else{
//if location or type matched
objectComplaint = response.body()!!.Complain!!
Log.d("got the complaint",objectComplaint.toString())
setExistingData(objectComplaint)
val item = objectComplaint
listener!!.onLocationFragmentInteraction(item) // all complaint going to popup
}
}
else if(response.code() == 500){
//if location or type is not in db
Log.d("response error", response.body().toString())
var item1 = makeComplaintobject1
Log.d("NOT IN DB",makeComplaintobject1.toString())
listener!!.onLocationFragmentInteraction1(item1!!) // typeName and location going to category description
}
else{
var item1 = makeComplaintobject1
Log.d("wohoooooo!1111",makeComplaintobject1.toString())
listener!!.onLocationFragmentInteraction1(item1!!) // typeName and location going to category description
//descriptionFragment()
}
}
})
}
interface OnLocationFragmentInteractionListener {
fun onLocationFragmentInteraction(item: Observables.Complaint?) // all complaint going to popup
fun onLocationFragmentInteraction1(item1: Observables.final) // typeName and location going to category description
}
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is OnLocationFragmentInteractionListener) {
listener = context
}
else {
throw RuntimeException("$context must implement OnLocationFragmentInteractionListener")
}
}
fun setExistingData(test: Observables.Complaint) {
objectComplaint = test
}
}
我已经在清单中请求了ACCESS_FINE_LOCATION权限,我的最小sdk版本是23,而targetdk是26。
经过多次尝试,我仍然遇到以下错误。
java.lang.SecurityException: my location requires permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION
请有人帮助我,我将非常感激!
答案 0 :(得分:0)
如果您在Marshmallow
或更高版本上运行,那么您需要检查ACCESS_FINE_LOCATION
的权限(如果用户未授予权限),那么当您尝试访问时将获得SecurityException
未经用户同意的位置。因此在访问位置之前,您需要像这样检查-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// you can access LOCATION
}
else
{
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 411);
}
}
else
{
// you can access LOCATION
}
获取“权限”对话框的结果,
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 411) {
if (grantResults.length == 0 || grantResults == null) {
// show dialog that you need access to go ahead
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Your code here permission granted
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// show dialog that you need access to go ahead
}
}
}
现在进入您的代码
private fun checkForPermissions(){
if(activity!!.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
requestPermissions( arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
}
startLocationUpdates()
}
紧接着
if(activity!!.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
您正在拨打的if condition
端
startLocationUpdates()
所以这就是为什么权限对话框系统调用此方法并尝试在未经用户同意的情况下获取位置更新,并且应用SecurityException
崩溃的原因。
您的更新方法可能如下-
private fun checkForPermissions(){
if(activity!!.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
requestPermissions( arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE)
}else{
startLocationUpdates()
}
}
希望这会对您有所帮助。