From dad0594854a5ff469077a3cffea8f340c7eec65b Mon Sep 17 00:00:00 2001 From: wiecktobi Date: Thu, 28 May 2020 11:33:11 +0200 Subject: [PATCH 1/3] Set geofenc according to users location values --- .../hft/geotracker/activities/MainActivity.kt | 66 ++++++++++++++----- .../geotracker/retrofit/GeofenceService.kt | 3 + .../hft/geotracker/retrofit/ValuesLocation.kt | 19 ++++++ .../retrofit/ValuesTimetrackAccounts.kt | 19 ++++++ .../de/hft/geotracker/retrofit/ValuesUser.kt | 2 +- 5 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 android/app/src/main/java/de/hft/geotracker/retrofit/ValuesLocation.kt create mode 100644 android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt diff --git a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt index 836d029..2fe38d0 100644 --- a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt +++ b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt @@ -10,6 +10,7 @@ import android.os.Looper import android.widget.ArrayAdapter import android.widget.Spinner import android.widget.TextView +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat.requestPermissions @@ -18,6 +19,7 @@ import de.hft.geotracker.GeofenceBroadcastReceiver import de.hft.geotracker.R import de.hft.geotracker.retrofit.AuthenticationInterceptor import de.hft.geotracker.retrofit.GeofenceService +import de.hft.geotracker.retrofit.ValuesTimetrackAccounts import de.hft.geotracker.retrofit.ValuesUser import kotlinx.android.synthetic.main.activity_home.* import okhttp3.OkHttpClient @@ -80,22 +82,6 @@ class MainActivity : AppCompatActivity() { button_start_stop.isEnabled = btnState } - //Setup geofence - geofencingClient = LocationServices.getGeofencingClient(this) - geofence = Geofence.Builder().setRequestId("Test") - .setCircularRegion(48.3575, 8.9745, 50F) - .setExpirationDuration(Geofence.NEVER_EXPIRE) - .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) - .build() - geofencingClient.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run { - addOnSuccessListener { - println("Geofence added") - } - addOnFailureListener { - println("Error: " + it.stackTrace.forEach { println(it.toString()) }) - } - } - //JWToken lesen val fis = openFileInput("JWToken") val isr = InputStreamReader(fis) @@ -119,6 +105,28 @@ class MainActivity : AppCompatActivity() { service = retrofit.create(GeofenceService::class.java) showUsername() + //Setup geofence + + + //Get Timetrack Accounts + /*val call = service.getAccounts() + call.enqueue(object: Callback> { + override fun onResponse( + call: Call>, + response: Response> + ) { + if (response.isSuccessful) { + val responseBody = response.body()!! + responseBody.forEach { + println(it.name) + } + } + + } + override fun onFailure(call: Call>, t: Throwable) { + println("Get Timetrack Accounts ended with errors. " + t.message) + } + })*/ val spinner: Spinner = findViewById(R.id.account_spinner) // Create an ArrayAdapter using the string array and a default spinner layout ArrayAdapter.createFromResource( @@ -130,6 +138,7 @@ class MainActivity : AppCompatActivity() { // Apply the adapter to the spinner spinner.adapter = adapter } + actionButton = findViewById(R.id.button_start_stop) actionButton.setOnClickListener { callStartStop() @@ -165,18 +174,41 @@ class MainActivity : AppCompatActivity() { override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { val firstname = response.body()?.firstname + val location = response.body()?.location lbl_username.text = "Hello " + firstname println("Body: " + firstname) + if (location?.latitude == null) { + Toast.makeText(this@MainActivity, "No geofence set for you", Toast.LENGTH_LONG) + .show() + } else { + initializeGeofence(location?.latitude, location?.longitude, location?.radius) + } } else { println("Response not successful: ${response.code()}") } } override fun onFailure(call: Call, t: Throwable) { - println("Response 'whoami' failed") + println("Response 'whoami' failed. " + t.message) } }) } + private fun initializeGeofence(lat: Double, long: Double, rad: Float) { + geofencingClient = LocationServices.getGeofencingClient(this) + geofence = Geofence.Builder().setRequestId("Test") + .setCircularRegion(lat, long, rad) + .setExpirationDuration(Geofence.NEVER_EXPIRE) + .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) + .build() + geofencingClient.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run { + addOnSuccessListener { + println("Geofence added with: latitude: $lat longitude: $long radius: $rad") + } + addOnFailureListener { + println("Error: " + it.stackTrace.forEach { println(it.toString()) }) + } + } + } private fun getGeofencingRequest(): GeofencingRequest { return GeofencingRequest.Builder().apply { diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt index 5cf681c..8759a25 100644 --- a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt @@ -11,4 +11,7 @@ interface GeofenceService { @GET("whoami") fun getUser(): Call + + @GET("accounts") + fun getAccounts(): Call> } \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesLocation.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesLocation.kt new file mode 100644 index 0000000..06c79e5 --- /dev/null +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesLocation.kt @@ -0,0 +1,19 @@ +package de.hft.geotracker.retrofit + +import com.google.gson.annotations.SerializedName + +class ValuesLocation( + latitude: Double, + longitude: Double, + radius: Int +) { + + @SerializedName("latitude") + var latitude = latitude + + @SerializedName("longitude") + var longitude = longitude + + @SerializedName("radius") + var radius = radius.toFloat() +} \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt new file mode 100644 index 0000000..3f94cd6 --- /dev/null +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt @@ -0,0 +1,19 @@ +package de.hft.geotracker.retrofit + +import com.google.gson.annotations.SerializedName + +class ValuesTimetrackAccounts( + revenue: Double, + name: String, + description: String +) { + + @SerializedName("revenue") + var revenue = revenue + + @SerializedName("name") + var name = name + + @SerializedName("description") + var description = description +} \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesUser.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesUser.kt index cb47e5b..76eb7a7 100644 --- a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesUser.kt +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesUser.kt @@ -7,7 +7,7 @@ class ValuesUser( firstname: String, lastname: String, username: String, - location: String, + location: ValuesLocation, id: Int ) { From c52daee815e42b4245acd4863776be8db9d38100 Mon Sep 17 00:00:00 2001 From: wiecktobi Date: Thu, 28 May 2020 16:19:55 +0200 Subject: [PATCH 2/3] Read, save and display account name, description and revenue --- .../hft/geotracker/activities/MainActivity.kt | 82 ++++++++------ .../geotracker/retrofit/EmbeddedAccounts.kt | 8 ++ .../geotracker/retrofit/GeofenceService.kt | 2 +- .../retrofit/ValuesTimetrackAccounts.kt | 17 +-- .../ValuesTimetrackAccountsEntries.kt | 19 ++++ .../app/src/main/res/layout/activity_home.xml | 102 +++++++++++++++--- .../app/src/main/res/layout/dropdown_menu.xml | 6 +- 7 files changed, 172 insertions(+), 64 deletions(-) create mode 100644 android/app/src/main/java/de/hft/geotracker/retrofit/EmbeddedAccounts.kt create mode 100644 android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccountsEntries.kt diff --git a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt index 2fe38d0..1667fd0 100644 --- a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt +++ b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt @@ -7,20 +7,15 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import android.os.Looper -import android.widget.ArrayAdapter -import android.widget.Spinner -import android.widget.TextView -import android.widget.Toast +import android.view.View +import android.widget.* import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat.requestPermissions import com.google.android.gms.location.* import de.hft.geotracker.GeofenceBroadcastReceiver import de.hft.geotracker.R -import de.hft.geotracker.retrofit.AuthenticationInterceptor -import de.hft.geotracker.retrofit.GeofenceService -import de.hft.geotracker.retrofit.ValuesTimetrackAccounts -import de.hft.geotracker.retrofit.ValuesUser +import de.hft.geotracker.retrofit.* import kotlinx.android.synthetic.main.activity_home.* import okhttp3.OkHttpClient import retrofit2.Call @@ -37,6 +32,7 @@ class MainActivity : AppCompatActivity() { lateinit var geofence: Geofence lateinit var actionButton: TextView var running = false + lateinit var accounts: ValuesTimetrackAccounts lateinit var service: GeofenceService lateinit var locationRequest: LocationRequest lateinit var fusedLocationClient: FusedLocationProviderClient @@ -105,39 +101,30 @@ class MainActivity : AppCompatActivity() { service = retrofit.create(GeofenceService::class.java) showUsername() - //Setup geofence - - //Get Timetrack Accounts - /*val call = service.getAccounts() - call.enqueue(object: Callback> { + val accountNames = mutableListOf() +// accountNames.add("None") + val call = service.getAccounts() + call.enqueue(object: Callback { override fun onResponse( - call: Call>, - response: Response> + call: Call, + response: Response ) { if (response.isSuccessful) { - val responseBody = response.body()!! - responseBody.forEach { - println(it.name) + accounts = response.body()!!.accounts + accounts.entries.forEach { + accountNames.add(it.name + "") } + initializeDropdown(accountNames) } - } - override fun onFailure(call: Call>, t: Throwable) { - println("Get Timetrack Accounts ended with errors. " + t.message) + override fun onFailure(call: Call, t: Throwable) { + accountNames.add("None") + initializeDropdown(accountNames) + Toast.makeText(this@MainActivity, "You dont have any Timetrack Accounts ", Toast.LENGTH_LONG) + .show() } - })*/ - val spinner: Spinner = findViewById(R.id.account_spinner) - // Create an ArrayAdapter using the string array and a default spinner layout - ArrayAdapter.createFromResource( - this, - R.array.accounts, android.R.layout.simple_spinner_item - ).also { adapter -> - // Specify the layout to use when the list of choices appears - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - // Apply the adapter to the spinner - spinner.adapter = adapter - } + }) actionButton = findViewById(R.id.button_start_stop) actionButton.setOnClickListener { @@ -193,6 +180,35 @@ class MainActivity : AppCompatActivity() { } }) } + private fun initializeDropdown(accountNames: MutableList) { + val spinner: Spinner = findViewById(R.id.account_spinner) + // Create an ArrayAdapter using the string array and a default spinner layout + val arrayAdapter = ArrayAdapter(this, R.layout.spinner_layout, accountNames) + arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + spinner.adapter = arrayAdapter + spinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, + view: View?, + position: Int, + id: Long + ) { + if (!accountNames.get(0).equals("rich")) { + display_description.setText(accounts.entries.get(position).description) + display_revenue.setText(accounts.entries.get(position).revenue.toString()) + } else { + display_description.visibility = View.GONE + display_description_layout.visibility = View.GONE + display_revenue.visibility = View.GONE + display_revenue_layout.visibility = View.GONE + } + println("Selected: " + accountNames.get(position)) + } + override fun onNothingSelected(parent: AdapterView<*>?) { + println("Nothing selected") + } + } + } private fun initializeGeofence(lat: Double, long: Double, rad: Float) { geofencingClient = LocationServices.getGeofencingClient(this) geofence = Geofence.Builder().setRequestId("Test") diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/EmbeddedAccounts.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/EmbeddedAccounts.kt new file mode 100644 index 0000000..2ec99bc --- /dev/null +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/EmbeddedAccounts.kt @@ -0,0 +1,8 @@ +package de.hft.geotracker.retrofit + +import com.google.gson.annotations.SerializedName + +class EmbeddedAccounts(accounts: ValuesTimetrackAccounts) { + @SerializedName("_embedded") + var accounts = accounts +} \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt index 8759a25..65cb132 100644 --- a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt @@ -13,5 +13,5 @@ interface GeofenceService { fun getUser(): Call @GET("accounts") - fun getAccounts(): Call> + fun getAccounts(): Call } \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt index 3f94cd6..e3af65a 100644 --- a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccounts.kt @@ -2,18 +2,7 @@ package de.hft.geotracker.retrofit import com.google.gson.annotations.SerializedName -class ValuesTimetrackAccounts( - revenue: Double, - name: String, - description: String -) { - - @SerializedName("revenue") - var revenue = revenue - - @SerializedName("name") - var name = name - - @SerializedName("description") - var description = description +class ValuesTimetrackAccounts(entries: Array) { + @SerializedName("accounts") + var entries = entries } \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccountsEntries.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccountsEntries.kt new file mode 100644 index 0000000..d16f368 --- /dev/null +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTimetrackAccountsEntries.kt @@ -0,0 +1,19 @@ +package de.hft.geotracker.retrofit + +import com.google.gson.annotations.SerializedName + +class ValuesTimetrackAccountsEntries( + revenue: Double, + name: String, + description: String +) { + + @SerializedName("revenue") + var revenue = revenue + + @SerializedName("name") + var name = name + + @SerializedName("description") + var description = description +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_home.xml b/android/app/src/main/res/layout/activity_home.xml index 61a59bd..5474830 100644 --- a/android/app/src/main/res/layout/activity_home.xml +++ b/android/app/src/main/res/layout/activity_home.xml @@ -55,16 +55,18 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" + android:layout_marginTop="@dimen/margin16" + android:layout_marginEnd="16dp" android:fontFamily="@font/montserrat" android:text="@string/timetrack_account" android:textAppearance="@style/text_style" android:textColor="@color/logo_white" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintEnd_toEndOf="@id/account_spinner" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/appBarLayout" - app:layout_constraintVertical_bias="0.19" /> + app:layout_constraintTop_toBottomOf="@+id/divider2" + app:layout_constraintVertical_bias="0.0" /> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/selected_acc" /> + + + + + + + + + + + + app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintTop_toBottomOf="@+id/display_revenue_layout" /> + app:layout_constraintStart_toStartOf="parent" /> \ No newline at end of file diff --git a/android/app/src/main/res/layout/dropdown_menu.xml b/android/app/src/main/res/layout/dropdown_menu.xml index 8413bf4..4dad12b 100644 --- a/android/app/src/main/res/layout/dropdown_menu.xml +++ b/android/app/src/main/res/layout/dropdown_menu.xml @@ -1,12 +1,14 @@ - + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> Date: Thu, 28 May 2020 20:49:58 +0200 Subject: [PATCH 3/3] Query track endpoint and show start/enddate --- .../hft/geotracker/activities/MainActivity.kt | 23 +++++++++++++- .../geotracker/retrofit/GeofenceService.kt | 4 +++ .../hft/geotracker/retrofit/ValuesTracking.kt | 30 +++++++++++++++++++ .../app/src/main/res/layout/activity_home.xml | 7 +++-- 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTracking.kt diff --git a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt index 1667fd0..ccaf3bf 100644 --- a/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt +++ b/android/app/src/main/java/de/hft/geotracker/activities/MainActivity.kt @@ -17,6 +17,7 @@ import de.hft.geotracker.GeofenceBroadcastReceiver import de.hft.geotracker.R import de.hft.geotracker.retrofit.* import kotlinx.android.synthetic.main.activity_home.* +import kotlinx.android.synthetic.main.dropdown_menu.* import okhttp3.OkHttpClient import retrofit2.Call import retrofit2.Callback @@ -32,6 +33,7 @@ class MainActivity : AppCompatActivity() { lateinit var geofence: Geofence lateinit var actionButton: TextView var running = false + var accName: String? = null lateinit var accounts: ValuesTimetrackAccounts lateinit var service: GeofenceService lateinit var locationRequest: LocationRequest @@ -151,6 +153,24 @@ class MainActivity : AppCompatActivity() { private fun callStartStop() { running = !running + if (running) { + account_spinner.visibility = View.GONE + } else { + account_spinner.visibility = View.VISIBLE + } + if (!accName.isNullOrEmpty()) { + val call = service.triggerTracking(accName!!) + call.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + latitude.text = response.body()?.startdate + longitude.text = response.body()?.enddate + println("Tracking event successful!") + } + override fun onFailure(call: Call, t: Throwable) { + println("Problem at start tracking: " + t.message) + } + }) + } println("StartStop pressed: $running") //ToDO call /track Endpoint } @@ -193,7 +213,8 @@ class MainActivity : AppCompatActivity() { position: Int, id: Long ) { - if (!accountNames.get(0).equals("rich")) { + if (!accountNames.get(0).equals("None")) { + accName = accounts.entries.get(position).name display_description.setText(accounts.entries.get(position).description) display_revenue.setText(accounts.entries.get(position).revenue.toString()) } else { diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt index 65cb132..d437f99 100644 --- a/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/GeofenceService.kt @@ -4,6 +4,7 @@ import retrofit2.Call import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.POST +import retrofit2.http.Query interface GeofenceService { @POST("/login") @@ -14,4 +15,7 @@ interface GeofenceService { @GET("accounts") fun getAccounts(): Call + + @GET("track") + fun triggerTracking(@Query("account") account: String): Call } \ No newline at end of file diff --git a/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTracking.kt b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTracking.kt new file mode 100644 index 0000000..50756e9 --- /dev/null +++ b/android/app/src/main/java/de/hft/geotracker/retrofit/ValuesTracking.kt @@ -0,0 +1,30 @@ +package de.hft.geotracker.retrofit + +import com.google.gson.annotations.SerializedName + +class ValuesTracking( + duration: Int, + start: String, + end: String, + account: String, + user: String, + type: String +) { + @SerializedName("duration") + var duration = duration + + @SerializedName("startdate") + var startdate = start + + @SerializedName("enddate") + var enddate = end + + @SerializedName("account") + var account = account + + @SerializedName("username") + var username = user + + @SerializedName("type") + var type = type +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_home.xml b/android/app/src/main/res/layout/activity_home.xml index 5474830..f267e14 100644 --- a/android/app/src/main/res/layout/activity_home.xml +++ b/android/app/src/main/res/layout/activity_home.xml @@ -188,11 +188,11 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" + android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:text="dummy" android:textAppearance="@style/text_style" android:textColor="@color/logo_white" - app:layout_constraintBottom_toTopOf="@+id/longitude" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/display_revenue_layout" /> @@ -202,12 +202,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" + android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:text="dummy" android:textAppearance="@style/text_style" - app:layout_constraintBottom_toTopOf="@+id/altitude" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" /> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/latitude" /> \ No newline at end of file