Advertisement
Guest User

Untitled

a guest
Apr 16th, 2021
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 7.72 KB | None | 0 0
  1. const val CANCEL_TRACKING_TAG = "cancelTag"
  2.  
  3. @AndroidEntryPoint
  4. class TrackingFragment : Fragment() {
  5.  
  6.     private val viewModel: MainViewModel by viewModels()
  7.  
  8.     private var _binding: FragmentTrackingBinding? = null
  9.     private val binding get() = _binding!!
  10.  
  11.     private var map: GoogleMap? = null
  12.  
  13.     private var isTracking = false
  14.     private var pathPoints = mutableListOf<Polyline>()
  15.  
  16.     private var curTimeInMillis = 0L
  17.     private var menu: Menu? = null
  18.  
  19.     @set:Inject
  20.     var weight = 80f
  21.  
  22.     override fun onCreateView(
  23.         inflater: LayoutInflater,
  24.         container: ViewGroup?,
  25.         savedInstanceState: Bundle?
  26.     ): View? {
  27.         _binding = FragmentTrackingBinding.inflate(inflater, container, false)
  28.         setHasOptionsMenu(true)
  29.         binding.mapView.onCreate(savedInstanceState)
  30.         return binding.root
  31.     }
  32.  
  33.     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  34.         super.onViewCreated(view, savedInstanceState)
  35.  
  36.  
  37.         binding.mapView.getMapAsync {
  38.             map = it
  39.             addAllPolylines()
  40.         }
  41.  
  42.         binding.btnToggleRun.setOnClickListener {
  43.             toggleRun()
  44.         }
  45.         binding.btnFinishRun.setOnClickListener {
  46.             zoomToSeeWholeTrack()
  47.             endRunAndSaveToDb()
  48.         }
  49.         subscribeToObservers()
  50.  
  51.         if (savedInstanceState != null) {
  52.             val cancelTrackingFragment =
  53.                 parentFragmentManager.findFragmentByTag(CANCEL_TRACKING_TAG)
  54.                         as CancelTrackingFragment?
  55.             cancelTrackingFragment?.yesListener {
  56.                 stopRun()
  57.             }
  58.         }
  59.     }
  60.  
  61.     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
  62.         super.onCreateOptionsMenu(menu, inflater)
  63.         inflater.inflate(R.menu.tracking_menu, menu)
  64.         this.menu = menu
  65.     }
  66.  
  67.     override fun onPrepareOptionsMenu(menu: Menu) {
  68.         super.onPrepareOptionsMenu(menu)
  69.         if (curTimeInMillis > 0L) {
  70.             this.menu?.getItem(0)?.isVisible = true
  71.         }
  72.     }
  73.  
  74.     override fun onOptionsItemSelected(item: MenuItem): Boolean {
  75.         when (item.itemId) {
  76.             R.id.menu_cancelTracking -> showCancelTrackingDialog()
  77.         }
  78.         return super.onOptionsItemSelected(item)
  79.     }
  80.  
  81.     private fun showCancelTrackingDialog() {
  82.         CancelTrackingFragment().apply {
  83.             yesListener {
  84.                 stopRun()
  85.             }
  86.         }.show(parentFragmentManager, CANCEL_TRACKING_TAG)
  87.     }
  88.  
  89.     private fun stopRun() {
  90.         sendCommandToService(ACTION_STOP_SERVICE)
  91.         findNavController().navigate(R.id.action_trackingFragment_to_runFragment)
  92.     }
  93.  
  94.     private fun subscribeToObservers() {
  95.         TrackingService.isTracking.observe(viewLifecycleOwner) {
  96.             updateTracking(it)
  97.         }
  98.         TrackingService.pathPoints.observe(viewLifecycleOwner) {
  99.             pathPoints = it
  100.             addLatestPolyline()
  101.             moveCameraToUser()
  102.         }
  103.         TrackingService.timeRunInMillis.observe(viewLifecycleOwner) {
  104.             curTimeInMillis = it
  105.             val formattedTime = TrackingUtility.getFormattedStopWatchTime(curTimeInMillis, true)
  106.             binding.tvTimer.text = formattedTime
  107.         }
  108.     }
  109.  
  110.     private fun toggleRun() {
  111.         if (isTracking) {
  112.             menu?.getItem(0)?.isVisible = true
  113.             sendCommandToService(ACTION_PAUSE_SERVICE)
  114.         } else sendCommandToService(ACTION_START_OR_RESUME_SERVICE)
  115.     }
  116.  
  117.     private fun updateTracking(isTracking: Boolean) {
  118.         this.isTracking = isTracking
  119.         if (!isTracking && curTimeInMillis > 0L) {
  120.             binding.apply {
  121.                 btnToggleRun.text = "Start"
  122.                 btnFinishRun.visibility = View.VISIBLE
  123.             }
  124.         } else if (isTracking) {
  125.             binding.apply {
  126.                 btnToggleRun.text = "Stop"
  127.                 menu?.getItem(0)?.isVisible = true
  128.                 btnFinishRun.visibility = View.GONE
  129.             }
  130.         }
  131.     }
  132.  
  133.     private fun moveCameraToUser() {
  134.         if (pathPoints.isNotEmpty() && pathPoints.last().isNotEmpty()) {
  135.             map?.animateCamera(
  136.                 CameraUpdateFactory.newLatLngZoom(
  137.                     pathPoints.last().last(),
  138.                     MAP_ZOOM
  139.                 )
  140.             )
  141.         }
  142.     }
  143.  
  144.     private fun zoomToSeeWholeTrack() {
  145.         val bounds = LatLngBounds.Builder()
  146.         for (polyline in pathPoints)
  147.             for (positon in polyline) {
  148.                 bounds.include(positon)
  149.             }
  150.         map?.moveCamera(
  151.             CameraUpdateFactory.newLatLngBounds(
  152.                 bounds.build(),
  153.                 binding.mapView.width,
  154.                 binding.mapView.height,
  155.                 (binding.mapView.height * 0.05f).toInt()
  156.             )
  157.         )
  158.     }
  159.  
  160.     private fun addAllPolylines() {
  161.         for (polyline in pathPoints) {
  162.             val polylineOptions = PolylineOptions()
  163.                 .color(POLYLINE_COLOR)
  164.                 .width(POLYLINE_WIDTH)
  165.                 .addAll(polyline)
  166.  
  167.             map?.addPolyline(polylineOptions)
  168.         }
  169.     }
  170.  
  171.     private fun addLatestPolyline() {
  172.         if (pathPoints.isNotEmpty() && pathPoints.last().size > 1) {
  173.             val preLastLatLng = pathPoints.last()[pathPoints.last().size - 2]
  174.             val lastLatLng = pathPoints.last().last()
  175.             val polylineOptions = PolylineOptions()
  176.                 .color(POLYLINE_COLOR)
  177.                 .width(POLYLINE_WIDTH)
  178.                 .add(preLastLatLng, lastLatLng)
  179.  
  180.             map?.addPolyline(polylineOptions)
  181.         }
  182.     }
  183.  
  184.     private fun endRunAndSaveToDb() {
  185.         map?.snapshot { bitmap ->
  186.             var distanceInMiters = 0
  187.             for (polyline in pathPoints) {
  188.                 distanceInMiters += TrackingUtility.calculatePolylineLength(polyline).toInt()
  189.             }
  190.             val avgSpeed =
  191.                 round((distanceInMiters / 1000f) / (curTimeInMillis / 1000f / 60 / 60) * 10) / 10f
  192.             val dateTimestamp = Calendar.getInstance().timeInMillis
  193.             val caloriesBurned = ((distanceInMiters / 1000f) * weight).toInt()
  194.  
  195.             val run = Run(
  196.                 bitmap,
  197.                 dateTimestamp,
  198.                 avgSpeed,
  199.                 distanceInMiters,
  200.                 curTimeInMillis,
  201.                 caloriesBurned
  202.             )
  203.             viewModel.insertRun(run)
  204.             Snackbar.make(
  205.                 requireActivity().findViewById(R.id.rootView),
  206.                 "Run saved successfully",
  207.                 Snackbar.LENGTH_LONG
  208.             ).show()
  209.         }
  210.         stopRun()
  211.     }
  212.  
  213.     override fun onResume() {
  214.         super.onResume()
  215.         binding.mapView.onResume()
  216.     }
  217.  
  218.     override fun onStart() {
  219.         super.onStart()
  220.         binding.mapView.onStart()
  221.     }
  222.  
  223.     override fun onPause() {
  224.         super.onPause()
  225.         binding.mapView.onPause()
  226.     }
  227.  
  228.     override fun onStop() {
  229.         super.onStop()
  230.         binding.mapView.onStop()
  231.     }
  232.  
  233.     override fun onLowMemory() {
  234.         super.onLowMemory()
  235.         binding.mapView.onLowMemory()
  236.     }
  237.  
  238.     override fun onSaveInstanceState(outState: Bundle) {
  239.         super.onSaveInstanceState(outState)
  240.         binding.mapView.onSaveInstanceState(outState)
  241.     }
  242.  
  243.     private fun sendCommandToService(action: String) =
  244.         Intent(requireContext(), TrackingService::class.java).also {
  245.             it.action = action
  246.             requireContext().startService(it)
  247.         }
  248.  
  249.     override fun onDestroyView() {
  250.         super.onDestroyView()
  251.         binding.mapView.onDestroy()
  252.     }
  253.  
  254.     override fun onDestroy() {
  255.         super.onDestroy()
  256.         _binding = null
  257.     }
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement