Get the boundary setting activity working.
This commit is contained in:
parent
7cd3706b7d
commit
48a6d1fff1
|
@ -1,9 +1,14 @@
|
|||
package com.danilafe.fencelessgrazing.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
/**
|
||||
* GPS coordinate returned by many of the project's API endpoints.
|
||||
*
|
||||
* @param longitude the longitude of the GPS point.
|
||||
* @param latitude the latitude of the GPS point.
|
||||
*/
|
||||
data class CollarPos(val longitude: String, val latitude: String)
|
||||
@Parcelize
|
||||
data class CollarPos(val longitude: String, val latitude: String) : Parcelable
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.danilafe.fencelessgrazing.requests.authenticated
|
||||
|
||||
import com.android.volley.Response
|
||||
import com.android.volley.toolbox.JsonObjectRequest
|
||||
import com.android.volley.toolbox.StringRequest
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import org.json.JSONObject
|
||||
|
||||
open class AuthenticatedPostRequest<T>(
|
||||
private val value: T,
|
||||
baseUrl: String,
|
||||
apiEndpoint: String,
|
||||
private val token: String,
|
||||
listener: Response.Listener<String>,
|
||||
error: Response.ErrorListener
|
||||
) : StringRequest(Method.POST, "${baseUrl}${apiEndpoint}",
|
||||
listener, error
|
||||
) {
|
||||
|
||||
override fun getBody(): ByteArray = Gson().toJson(value).toByteArray()
|
||||
|
||||
override fun getBodyContentType(): String = "application/json"
|
||||
|
||||
override fun getHeaders(): MutableMap<String, String> {
|
||||
val newMap = HashMap(super.getHeaders())
|
||||
newMap["Authorization"] = "Bearer $token"
|
||||
return newMap
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.danilafe.fencelessgrazing.requests.authenticated
|
||||
|
||||
import com.android.volley.Response
|
||||
import com.danilafe.fencelessgrazing.model.CollarPos
|
||||
|
||||
class SetBoundaryRequest(
|
||||
baseUrl: String,
|
||||
token: String,
|
||||
identifier: Int,
|
||||
coordinates: List<CollarPos>,
|
||||
listener: Response.Listener<String>,
|
||||
error: Response.ErrorListener
|
||||
) : AuthenticatedPostRequest<List<CollarPos>>(
|
||||
coordinates, baseUrl, "/collars/${identifier}/boundary/set",
|
||||
token, listener, error
|
||||
)
|
|
@ -0,0 +1,127 @@
|
|||
package com.danilafe.fencelessgrazing.ui.activities
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.os.PersistableBundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.android.volley.RequestQueue
|
||||
import com.android.volley.Response
|
||||
import com.android.volley.toolbox.Volley
|
||||
import com.danilafe.fencelessgrazing.R
|
||||
import com.danilafe.fencelessgrazing.model.CollarPos
|
||||
import com.danilafe.fencelessgrazing.requests.authenticated.SetBoundaryRequest
|
||||
import com.danilafe.fencelessgrazing.ui.components.GrazingPolygon
|
||||
import org.osmdroid.util.GeoPoint
|
||||
import org.osmdroid.views.MapView
|
||||
import org.osmdroid.views.overlay.Marker
|
||||
import org.osmdroid.views.overlay.Polygon
|
||||
|
||||
class BoundaryEditorActivity : AppCompatActivity(),
|
||||
Marker.OnMarkerDragListener,
|
||||
Marker.OnMarkerClickListener {
|
||||
|
||||
private lateinit var map: MapView
|
||||
private val markers: MutableList<Marker> = mutableListOf()
|
||||
private lateinit var polygon: GrazingPolygon
|
||||
private lateinit var center: GeoPoint
|
||||
private var identifier: Int = -1
|
||||
private lateinit var queue: RequestQueue
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_boundary_editor)
|
||||
|
||||
val requestedCenter = intent.getParcelableExtra<CollarPos>("center")!!
|
||||
center = GeoPoint(
|
||||
requestedCenter.longitude.toDouble(),
|
||||
requestedCenter.latitude.toDouble())
|
||||
identifier = intent.getIntExtra("identifier", -1)
|
||||
queue = Volley.newRequestQueue(applicationContext)
|
||||
|
||||
map = findViewById(R.id.editorMap)
|
||||
polygon = GrazingPolygon(map)
|
||||
map.overlays.add(polygon)
|
||||
map.controller.setZoom(9.5)
|
||||
map.controller.setCenter(center)
|
||||
}
|
||||
|
||||
private fun removeMarker(m: Marker) {
|
||||
markers.remove(m)
|
||||
map.overlays.remove(m)
|
||||
updatePolygon()
|
||||
map.invalidate()
|
||||
}
|
||||
|
||||
fun sendBoundary(v: View) {
|
||||
val request = SetBoundaryRequest(
|
||||
getString(R.string.apiUrl),
|
||||
getSharedPreferences("FencelessGrazing",0).getString("token",null)!!,
|
||||
identifier, markers.map {
|
||||
CollarPos(it.position.longitude.toString(), it.position.latitude.toString())
|
||||
},
|
||||
Response.Listener<String> {
|
||||
finish()
|
||||
},
|
||||
Response.ErrorListener {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Failed to update grazing boundaries",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
)
|
||||
queue.add(request)
|
||||
}
|
||||
|
||||
fun addMarker(v : View) {
|
||||
if(markers.size >= 10) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Cannot add more than ten vertices to grazing boundary",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
val newMarker = Marker(map)
|
||||
newMarker.isDraggable = true
|
||||
newMarker.setOnMarkerClickListener(this)
|
||||
newMarker.setOnMarkerDragListener(this)
|
||||
newMarker.position = center
|
||||
markers.add(newMarker)
|
||||
map.overlays.add(newMarker)
|
||||
updatePolygon()
|
||||
map.invalidate()
|
||||
}
|
||||
|
||||
private fun updatePolygon() {
|
||||
polygon.points.clear()
|
||||
if(markers.isEmpty()) return
|
||||
val newPoints = markers.map { it.position }
|
||||
polygon.points = newPoints
|
||||
polygon.points.add(newPoints.first())
|
||||
}
|
||||
|
||||
override fun onMarkerDragEnd(marker: Marker?) {
|
||||
updatePolygon()
|
||||
map.invalidate()
|
||||
}
|
||||
|
||||
override fun onMarkerDragStart(marker: Marker?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onMarkerDrag(marker: Marker?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onMarkerClick(m: Marker, mv: MapView): Boolean {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle("Delete Marker")
|
||||
.setMessage("Do you want to delete this marker?")
|
||||
.setPositiveButton("Delete") { _, _ -> removeMarker(m) }
|
||||
.setNegativeButton("Cancel") { d, _ -> d.dismiss() }
|
||||
.show()
|
||||
return true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user