#android #kotlin #location #android-permissions
#Android #котлин #Расположение #android-разрешения
Вопрос:
Я пытаюсь указать местоположение устройства в профиле пользователя, используя разрешения на местоположение как для грубого, так и для точного. Код запрашивает разрешения, и когда он предоставляется, он обновляет поля только иногда, я не могу понять, что не так, поскольку я процедурно проверяю разрешения, а затем заполняю поля, когда разрешение было предоставлено … мой код ниже (Kotlin)
EditProfile : AppCompatActivity() {
var usersReference: DatabaseReference? = null
var firebaseUser: FirebaseUser? = null
private val RequestCode = 438 //To enable redirect to phone gallery to select image
private var imageUri: Uri? = null //Uploaded Image URI
private var storageRef: StorageReference? = null //To enable storing on Firebase DB
private var profileImageChk: String? =
"" //to check if user is going to change the profile image
private var socialChk: String? = ""
//Location Manager
lateinit var fusedLocationProviderClient: FusedLocationProviderClient
lateinit var locationRequest: LocationRequest
val PERMISSION_ID = 1010
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_profile1)
setSupportActionBar(toolbar_editpro1)
val toolbar: Toolbar = findViewById(R.id.toolbar_editpro1)
setSupportActionBar(toolbar)
supportActionBar!!.title = "Edit Profile"
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
val cityname = findViewById<EditText>(R.id.editLocation)
val countryname = findViewById<EditText>(R.id.edit_user_country)
//Character Count for About
edit_user_desc.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
val length: Int = edit_user_desc.length()
val convert = "$length/300"
edit_desc_count.text = convert
if (length > 300) {
edit_desc_count.setTextColor(resources.getColor(R.color.colorPrimaryDark));
}
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {}
})
//Location Manager
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
location_btn.setOnClickListener {
RequestPermission()
/* fusedLocationProviderClient.lastLocation.addOnSuccessListener{location: Location? ->
textView.text = location?.latitude.toString() "," location?.longitude.toString()
}*/
getLastLocation()
}
//Creating firebase authorization for current user
firebaseUser = FirebaseAuth.getInstance().currentUser
usersReference =
FirebaseDatabase.getInstance().reference.child("Users").child(firebaseUser!!.uid)
storageRef = FirebaseStorage.getInstance().reference.child("App User Images")
usersReference!!.addValueEventListener(object : ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
if (p0.exists()) {
val user: Users? = p0.getValue(Users::class.java)
if (user != null) {
edit_profile_name?.setText(user.getFirstName())
edit_profile_surname?.setText(user.getSurName())
Picasso.get().load(user.getProfile())
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(edit_profile_image)
edit_comp_name?.setText(user.getCname())
edit_desig_name?.setText(user.getRole())
edit_user_desc?.setText(user.getAbout())
cityname.setText(user.getCity())
countryname.setText(user.getCountry())
}
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
//connecting to the display widget
edit_profile_image.setOnClickListener {
profileImageChk = "profile"
selectImage()
}
user_profile_save.setOnClickListener {
val name = edit_profile_name.text.toString()
val surname = edit_profile_surname.text.toString()
val role = edit_desig_name.text.toString()
val cname = edit_comp_name.text.toString()
val about = edit_user_desc.text.toString()
val cityn = editLocation.text.toString()
val countryn = edit_user_country.text.toString()
if (name == "") {
Toast.makeText(this, "Please enter your name", Toast.LENGTH_LONG).show()
} else if (surname == "") {
Toast.makeText(this, "Please enter your surname", Toast.LENGTH_LONG).show()
} else if (role == "") {
Toast.makeText(
this,
"Please enter your designation or a headline",
Toast.LENGTH_LONG
).show()
} else if (about == "") {
Toast.makeText(
this,
"Please enter a brief description about yourself",
Toast.LENGTH_LONG
).show()
} else if (cityn == "") {
Toast.makeText(this, "Please click on - Use Current Location", Toast.LENGTH_LONG)
.show()
} else {
//to save message on Firebase
val usersHashMap = HashMap<String, Any?>()
usersHashMap["firstname"] = name
usersHashMap["surname"] = surname
usersHashMap["role"] = role
usersHashMap["cname"] = cname
usersHashMap["about"] = about
usersHashMap["city"] = cityn
usersHashMap["country"] = countryn
usersReference!!.updateChildren(usersHashMap)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Toast.makeText(this, "Details Updated.", Toast.LENGTH_LONG).show()
}
}
}
}
}
private fun selectImage() {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(intent, RequestCode)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RequestCode amp;amp; resultCode == Activity.RESULT_OK amp;amp; data!!.data != null) {
imageUri = data.data
Toast.makeText(this@EditProfile, "uploading the image", Toast.LENGTH_LONG).show()
uploadImageToDatabase()
}
}
private fun uploadImageToDatabase() {
if (imageUri != null) {
//creating a unique storage reference so that there are no duplicates
val fileRef = storageRef!!.child(System.currentTimeMillis().toString() ".jpg")
val uploadTask: StorageTask<*>
uploadTask = fileRef.putFile(imageUri!!)
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot, Task<Uri>>
{ task ->
if (!task.isSuccessful) {
task.exception?.let {
throw it
}
}
return@Continuation fileRef.downloadUrl
}).addOnCompleteListener { task ->
if (task.isSuccessful) {
val downloadUrl = task.result
val url = downloadUrl.toString()
//to check if user is going to change the profile image
if (profileImageChk == "profile") {
val mapProfileImg = HashMap<String, Any>()
mapProfileImg["profile"] = url
usersReference!!.updateChildren(mapProfileImg)
}
} else {
Toast.makeText(this, "Please Upload an Image", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun CheckPermission(): Boolean {
//this function will return a boolean
//true: if we have permission
//false if not
if (
ActivityCompat.checkSelfPermission(
this,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(
this,
android.Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
return true
}
return false
}
private fun RequestPermission() {
//this function will allows us to tell the user to request the necessary permission if they are not granted
ActivityCompat.requestPermissions(
this,
arrayOf(
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION
),
PERMISSION_ID
)
}
private fun isLocationEnabled(): Boolean {
//this function will return to us the state of the location service
//if the gps or the network provider is enabled then it will return true otherwise it will return false
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun getLastLocation() {
val cityname = findViewById<EditText>(R.id.editLocation)
val countryname = findViewById<EditText>(R.id.edit_user_country)
if (CheckPermission()) {
if (isLocationEnabled()) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED amp;amp; ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
fusedLocationProviderClient.lastLocation.addOnCompleteListener { task ->
val location: Location? = task.result
if (location == null) {
NewLocationData()
} else {
val cityn = getCityName(location.latitude, location.longitude)
val countryn = getCountryName(location.latitude, location.longitude)
Toast.makeText(this, "$cityn amp; $countryn", Toast.LENGTH_SHORT)
.show()
cityname.setText(cityn)
countryname.setText(countryn)
}
}
} else {
Toast.makeText(this, "Please turn on your device location.", Toast.LENGTH_SHORT)
.show()
}
} else {
RequestPermission()
}
}
private fun NewLocationData() {
val locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.interval = 0
locationRequest.fastestInterval = 0
locationRequest.numUpdates = 1
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED amp;amp; ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
fusedLocationProviderClient.requestLocationUpdates(
locationRequest, locationCallback, Looper.myLooper()
)
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
val lastLocation: Location = locationResult.lastLocation
val cityname = findViewById<EditText>(R.id.editLocation)
val countryname = findViewById<EditText>(R.id.edit_user_country)
val cityn = getCityName(lastLocation.latitude, lastLocation.longitude)
val countryn = getCountryName(lastLocation.latitude, lastLocation.longitude)
cityname.setText(cityn)
countryname.setText(countryn)
}
}
private fun getCityName(lat: Double, long: Double): String {
var cityName: String = ""
val geoCoder = Geocoder(this, Locale.getDefault())
val Address = geoCoder.getFromLocation(lat, long, 3)
cityName = Address.get(0).locality
return cityName
}
private fun getCountryName(lat: Double, long: Double): String {
var countryName = ""
val geoCode = Geocoder(this, Locale.getDefault())
val Address = geoCode.getFromLocation(lat, long, 3)
countryName = Address.get(0).countryName
return countryName
}
}
Комментарии:
1. В вашем коде есть несколько проблем. вы запрашиваете разрешение на местоположение, но результат не обрабатывается.
2. Привет, Мэйбл, не могли бы вы указать на них ?…
Ответ №1:
Я надеюсь, что вы дали
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
разрешения в манифесте и не использовать эмулятор. вам также необходимо запросить разрешение времени выполнения для устройства с более высокой версией Android.
Ваш код хорош. Рассмотрите возможность создания для него другого класса, который расширяет класс обслуживания и реализует LocationListener
class LocationTrack extends Service implements LocationListener
Надеюсь, это поможет.
https://site-valley.com/2021/02/23/get-location-android-example-kotlin/