diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 96973c7..2a73a49 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,10 +13,10 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - - - - + + + + diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/requests/AuthenticatedRequest.kt b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/AuthenticatedRequest.kt similarity index 95% rename from app/src/main/java/com/danilafe/fencelessgrazing/requests/AuthenticatedRequest.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/AuthenticatedRequest.kt index 6da2c81..5d374c7 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/requests/AuthenticatedRequest.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/AuthenticatedRequest.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing.requests +package com.danilafe.fencelessgrazing.requests.authenticated import com.android.volley.Response import com.android.volley.toolbox.StringRequest diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarDetailRequest.kt b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarDetailRequest.kt similarity index 77% rename from app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarDetailRequest.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarDetailRequest.kt index c22a72c..8fc106e 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarDetailRequest.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarDetailRequest.kt @@ -1,11 +1,8 @@ -package com.danilafe.fencelessgrazing.requests +package com.danilafe.fencelessgrazing.requests.authenticated import com.android.volley.Response -import com.android.volley.toolbox.StringRequest import com.danilafe.fencelessgrazing.model.CollarDetails -import com.danilafe.fencelessgrazing.model.CollarPos -import com.danilafe.fencelessgrazing.model.CollarSummary -import com.google.gson.reflect.TypeToken +import com.danilafe.fencelessgrazing.requests.toGsonListener /** * Request to the `/collars//details` API endpoint. Retrieves detailed information diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarHistoryRequest.kt b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarHistoryRequest.kt similarity index 82% rename from app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarHistoryRequest.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarHistoryRequest.kt index e9c1bc1..1a51b4f 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarHistoryRequest.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarHistoryRequest.kt @@ -1,10 +1,8 @@ -package com.danilafe.fencelessgrazing.requests +package com.danilafe.fencelessgrazing.requests.authenticated import com.android.volley.Response -import com.android.volley.toolbox.StringRequest import com.danilafe.fencelessgrazing.model.CollarPos -import com.danilafe.fencelessgrazing.model.CollarSummary -import com.google.gson.reflect.TypeToken +import com.danilafe.fencelessgrazing.requests.toGsonListener /** * A request to the `/collars//history` API endpoint. Retrieves the entire list diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarRequest.kt b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarRequest.kt similarity index 83% rename from app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarRequest.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarRequest.kt index c7dab0f..130c595 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/requests/CollarRequest.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/CollarRequest.kt @@ -1,9 +1,8 @@ -package com.danilafe.fencelessgrazing.requests +package com.danilafe.fencelessgrazing.requests.authenticated import com.android.volley.Response -import com.android.volley.toolbox.StringRequest import com.danilafe.fencelessgrazing.model.CollarSummary -import com.google.gson.reflect.TypeToken +import com.danilafe.fencelessgrazing.requests.toGsonListener /** * A request to the `/collars` API endpoint. Retrieves a list of collar summaries, represented diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/requests/DistanceTraveledRequest.kt b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/DistanceTraveledRequest.kt similarity index 85% rename from app/src/main/java/com/danilafe/fencelessgrazing/requests/DistanceTraveledRequest.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/DistanceTraveledRequest.kt index 5bf7319..3ccef29 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/requests/DistanceTraveledRequest.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/requests/authenticated/DistanceTraveledRequest.kt @@ -1,9 +1,8 @@ -package com.danilafe.fencelessgrazing.requests +package com.danilafe.fencelessgrazing.requests.authenticated import com.danilafe.fencelessgrazing.model.CollarDistance import com.android.volley.Response -import com.android.volley.toolbox.StringRequest -import com.google.gson.reflect.TypeToken +import com.danilafe.fencelessgrazing.requests.toGsonListener /** * A request to the `/collars/stats/distance` API endpoint. Retrieves diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarDetailActivity.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarDetailActivity.kt similarity index 85% rename from app/src/main/java/com/danilafe/fencelessgrazing/CollarDetailActivity.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarDetailActivity.kt index 5f06ff1..2665e33 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarDetailActivity.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarDetailActivity.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.activities import android.graphics.Color import androidx.appcompat.app.AppCompatActivity @@ -8,9 +8,10 @@ import android.widget.Toast 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.Polygon -import com.danilafe.fencelessgrazing.requests.CollarDetailRequest -import com.danilafe.fencelessgrazing.requests.CollarHistoryRequest +import com.danilafe.fencelessgrazing.requests.authenticated.CollarDetailRequest +import com.danilafe.fencelessgrazing.requests.authenticated.CollarHistoryRequest import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker @@ -166,23 +167,32 @@ class CollarDetailActivity : AppCompatActivity() { * Sends API requests that retrieve updated information about the collar. */ private fun triggerRefresh() { - val historyRequest = CollarHistoryRequest(getString(R.string.apiUrl), collarId, token, - Response.Listener { - dataPoints = it.map { p -> GeoPoint(p.longitude.toDouble(), p.latitude.toDouble()) } - }, - Response.ErrorListener { - Toast.makeText(this, "Failed to retrieve history of collar", Toast.LENGTH_SHORT).show() - } - ) - val detailRequest = CollarDetailRequest(getString(R.string.apiUrl), collarId, token, - Response.Listener { - collarName.text = it.name - collarStimulus.text = getString(R.string.collarSummaryStimulus, it.stimulus) - }, - Response.ErrorListener { - Toast.makeText(this, "Failed to retrieve details of collar", Toast.LENGTH_SHORT).show() - } - ) + val historyRequest = + CollarHistoryRequest(getString(R.string.apiUrl), + collarId, + token, + Response.Listener { + dataPoints = + it.map { p -> GeoPoint(p.longitude.toDouble(), p.latitude.toDouble()) } + }, + Response.ErrorListener { + Toast.makeText(this, "Failed to retrieve history of collar", Toast.LENGTH_SHORT) + .show() + } + ) + val detailRequest = + CollarDetailRequest(getString(R.string.apiUrl), + collarId, + token, + Response.Listener { + collarName.text = it.name + collarStimulus.text = getString(R.string.collarSummaryStimulus, it.stimulus) + }, + Response.ErrorListener { + Toast.makeText(this, "Failed to retrieve details of collar", Toast.LENGTH_SHORT) + .show() + } + ) queue.add(historyRequest) queue.add(detailRequest) } diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarListActivity.kt similarity index 83% rename from app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarListActivity.kt index 6317244..16e4f99 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/CollarListActivity.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.activities import android.content.Intent import androidx.appcompat.app.AppCompatActivity @@ -12,8 +12,11 @@ import androidx.recyclerview.widget.RecyclerView import com.android.volley.RequestQueue import com.android.volley.Response import com.android.volley.toolbox.Volley +import com.danilafe.fencelessgrazing.ui.components.CollarClickListener +import com.danilafe.fencelessgrazing.ui.components.CollarSummaryAdapter +import com.danilafe.fencelessgrazing.R import com.danilafe.fencelessgrazing.model.CollarSummary -import com.danilafe.fencelessgrazing.requests.CollarRequest +import com.danilafe.fencelessgrazing.requests.authenticated.CollarRequest import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.util.GeoPoint @@ -116,17 +119,20 @@ class CollarListActivity : AppCompatActivity() { * Sends the request to the API to retrieve an updated list of active collars. */ private fun triggerRefresh() { - val request = CollarRequest(getString(R.string.apiUrl), token, - Response.Listener { - summaries.clear() - summaries.addAll(it) - summaryAdapter.notifyDataSetChanged() - updateMap() - }, - Response.ErrorListener { - Toast.makeText(this, "Failed to retrieve collar list!", Toast.LENGTH_SHORT).show() - } - ) + val request = + CollarRequest(getString(R.string.apiUrl), + token, + Response.Listener { + summaries.clear() + summaries.addAll(it) + summaryAdapter.notifyDataSetChanged() + updateMap() + }, + Response.ErrorListener { + Toast.makeText(this, "Failed to retrieve collar list!", Toast.LENGTH_SHORT) + .show() + } + ) queue.add(request) } @@ -158,12 +164,16 @@ class CollarListActivity : AppCompatActivity() { */ private fun setupCollarList() { val layoutManager = LinearLayoutManager(collarList.context) - summaryAdapter = CollarSummaryAdapter(summaries, object : CollarClickListener { - override fun onCollarClick(collar: CollarSummary?) { - if (collar == null) return - startCollarDetailActivity(collar) - } - }) + summaryAdapter = + CollarSummaryAdapter( + summaries, + object : + CollarClickListener { + override fun onCollarClick(collar: CollarSummary?) { + if (collar == null) return + startCollarDetailActivity(collar) + } + }) collarList.adapter = summaryAdapter collarList.layoutManager = layoutManager collarList.addItemDecoration(DividerItemDecoration(collarList.context, layoutManager.orientation)) diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/DistanceTraveledGraph.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/DistanceTraveledGraph.kt similarity index 82% rename from app/src/main/java/com/danilafe/fencelessgrazing/DistanceTraveledGraph.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/DistanceTraveledGraph.kt index 69cd347..be6fb08 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/DistanceTraveledGraph.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/DistanceTraveledGraph.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.activities import android.os.Bundle import android.view.LayoutInflater @@ -9,8 +9,9 @@ import androidx.fragment.app.Fragment 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.CollarDistance -import com.danilafe.fencelessgrazing.requests.DistanceTraveledRequest +import com.danilafe.fencelessgrazing.requests.authenticated.DistanceTraveledRequest import com.github.mikephil.charting.charts.BarChart import com.github.mikephil.charting.components.XAxis import com.github.mikephil.charting.data.BarData @@ -61,14 +62,20 @@ class DistanceTraveledGraph() : Fragment() { val activity = requireActivity() val sharedPrefs = activity.getSharedPreferences("FencelessGrazing", 0) val token = sharedPrefs.getString("token", null)!! - val request = DistanceTraveledRequest(activity.getString(R.string.apiUrl), token, - Response.Listener { - updateChartData(it) - }, - Response.ErrorListener { - Toast.makeText(activity, "Failed to retrieve distance traveled!", Toast.LENGTH_SHORT).show() - } - ) + val request = + DistanceTraveledRequest(activity.getString(R.string.apiUrl), + token, + Response.Listener { + updateChartData(it) + }, + Response.ErrorListener { + Toast.makeText( + activity, + "Failed to retrieve distance traveled!", + Toast.LENGTH_SHORT + ).show() + } + ) queue.add(request) } diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/MainActivity.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/MainActivity.kt similarity index 95% rename from app/src/main/java/com/danilafe/fencelessgrazing/MainActivity.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/MainActivity.kt index fabc388..55a4eab 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/MainActivity.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/MainActivity.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.activities import android.content.Intent import androidx.appcompat.app.AppCompatActivity @@ -8,6 +8,7 @@ import android.widget.TextView import android.widget.Toast import com.android.volley.Response import com.android.volley.toolbox.Volley +import com.danilafe.fencelessgrazing.R import com.danilafe.fencelessgrazing.requests.LoginRequest /** diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/StatisticsActivity.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/StatisticsActivity.kt similarity index 82% rename from app/src/main/java/com/danilafe/fencelessgrazing/StatisticsActivity.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/StatisticsActivity.kt index 0c7c6c8..1483b8b 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/StatisticsActivity.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/activities/StatisticsActivity.kt @@ -1,10 +1,10 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.activities import androidx.appcompat.app.AppCompatActivity import android.os.Bundle -import androidx.fragment.app.FragmentActivity -import androidx.viewpager.widget.ViewPager import androidx.viewpager2.widget.ViewPager2 +import com.danilafe.fencelessgrazing.R +import com.danilafe.fencelessgrazing.ui.components.StatisticsGraphAdapter import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator @@ -37,7 +37,10 @@ class StatisticsActivity : AppCompatActivity() { tabLayout = findViewById(R.id.statisticsTabs) viewPager = findViewById(R.id.statisticsPager) - viewPager.adapter = StatisticsGraphAdapter(this) + viewPager.adapter = + StatisticsGraphAdapter( + this + ) TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = tabNames[position] }.attach() diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarClickListener.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarClickListener.kt similarity index 88% rename from app/src/main/java/com/danilafe/fencelessgrazing/CollarClickListener.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarClickListener.kt index fae185e..08da686 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarClickListener.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarClickListener.kt @@ -1,4 +1,4 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.components import com.danilafe.fencelessgrazing.model.CollarSummary diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarSummaryAdapter.kt similarity index 79% rename from app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarSummaryAdapter.kt index 24c6fb5..c9f8ce1 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarSummaryAdapter.kt @@ -1,15 +1,12 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.components -import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup -import android.widget.Toast import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.DiffUtil -import com.android.volley.Response -import com.android.volley.toolbox.Volley +import com.danilafe.fencelessgrazing.R import com.danilafe.fencelessgrazing.model.CollarSummary -import com.danilafe.fencelessgrazing.requests.CollarRequest +import com.danilafe.fencelessgrazing.requests.authenticated.CollarRequest /** * A [ListAdapter] subclass to display and manage a list of [CollarSummary] items @@ -21,7 +18,9 @@ import com.danilafe.fencelessgrazing.requests.CollarRequest class CollarSummaryAdapter( private val items: List, private val collarClickListener: CollarClickListener -) : ListAdapter(DiffCallback()) { +) : ListAdapter( + DiffCallback() +) { /** * [DiffUtil.ItemCallback] used for the [ListAdapter]. Compares items using @@ -37,14 +36,17 @@ class CollarSummaryAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollarViewHolder { val layout = LayoutInflater.from(parent.context).inflate(viewType, parent, false) - return CollarViewHolder(layout) + return CollarViewHolder( + layout + ) } override fun onBindViewHolder(holder: CollarViewHolder, position: Int) { holder.bindData(getItem(position), collarClickListener) } - override fun getItemViewType(position: Int): Int = R.layout.collar_summary_layout + override fun getItemViewType(position: Int): Int = + R.layout.collar_summary_layout override fun getItem(position: Int): CollarSummary = items[position] diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarViewHolder.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarViewHolder.kt similarity index 86% rename from app/src/main/java/com/danilafe/fencelessgrazing/CollarViewHolder.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarViewHolder.kt index 75a5bec..eb0e70f 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarViewHolder.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/CollarViewHolder.kt @@ -1,8 +1,9 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.components import android.view.View import android.widget.TextView import androidx.recyclerview.widget.RecyclerView +import com.danilafe.fencelessgrazing.R import com.danilafe.fencelessgrazing.model.CollarSummary /** @@ -28,7 +29,8 @@ class CollarViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { */ fun bindData(summary: CollarSummary, collarClickListener: CollarClickListener) { nameView.text = summary.name - positionView.text = itemView.resources.getString(R.string.collarSummaryLocation, + positionView.text = itemView.resources.getString( + R.string.collarSummaryLocation, summary.pos.longitude.toDouble(), summary.pos.latitude.toDouble()) itemView.setOnClickListener { collarClickListener.onCollarClick(summary) diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/StatisticsGraphAdapter.kt b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/StatisticsGraphAdapter.kt similarity index 62% rename from app/src/main/java/com/danilafe/fencelessgrazing/StatisticsGraphAdapter.kt rename to app/src/main/java/com/danilafe/fencelessgrazing/ui/components/StatisticsGraphAdapter.kt index d9dfeff..33393ef 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/StatisticsGraphAdapter.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/ui/components/StatisticsGraphAdapter.kt @@ -1,13 +1,15 @@ -package com.danilafe.fencelessgrazing +package com.danilafe.fencelessgrazing.ui.components import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter +import com.danilafe.fencelessgrazing.ui.activities.DistanceTraveledGraph /** * Adapter for the [ViewPager2][androidx.viewpager2.widget.ViewPager2] class. */ class StatisticsGraphAdapter(activity : FragmentActivity) : FragmentStateAdapter(activity) { override fun getItemCount(): Int = 1 - override fun createFragment(position: Int): Fragment = DistanceTraveledGraph() + override fun createFragment(position: Int): Fragment = + DistanceTraveledGraph() } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_collar_detail.xml b/app/src/main/res/layout/activity_collar_detail.xml index cb21952..8b91acb 100644 --- a/app/src/main/res/layout/activity_collar_detail.xml +++ b/app/src/main/res/layout/activity_collar_detail.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".CollarDetailActivity"> + tools:context=".ui.activities.CollarDetailActivity"> + tools:context=".ui.activities.CollarListActivity"> + tools:context=".ui.activities.MainActivity"> + tools:context=".ui.activities.StatisticsActivity">