0

I am developing an android application for hiring bicycles which uses firebase database(realtime) and google maps.

Now i want to add a CountUp timer(in HH:mm:ss format) which tracks the ride time in server.

Why this requirement ?

As the ride time will be started by the customer once the ride is successfully booked, but will be ended only by the person managing the cycles at cycle stand from his app, when the bike is returned. (To ensure that the cycle has been returned safely)

How do i implement this timer in Firebase?

Till now i am implementing a CountUp Timer only at the customer end which uses Broadcast receiver to track the time in background.

One approach to solve this could be, that the customer ends the trip(only when customer is in 20 meters vicinity of cycle stand) and the same time be stored to firebase and the same be accessed by the person managing the cycle stand.

But there are some drawback to this approach:

What if a person ends the trip from outside stand and returns it after an hour, the time calculated will be wrong and will also hamper the availability status for next users.

   //Service Class
    public class BroadcastService extends Service {
        private Intent intent;
        public static final String BROADCAST_ACTION = "com.xyz";

        private Handler handler = new Handler();
        private long initial_time;
        long timeInMilliseconds = 0L;


        @Override
        public void onCreate() {
            super.onCreate();
            initial_time = SystemClock.uptimeMillis();
            intent = new Intent(BROADCAST_ACTION);
            handler.removeCallbacks(sendUpdatesToUI);
            handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
        }

        private Runnable sendUpdatesToUI = new Runnable() {
            public void run() {
                DisplayLoggingInfo();
                handler.postDelayed(this, 1000); // 1 seconds
            }
        };

        private void DisplayLoggingInfo() {

            timeInMilliseconds = SystemClock.uptimeMillis() - initial_time;

            int timer = (int) timeInMilliseconds / 1000;
            intent.putExtra("time", timer);
            sendBroadcast(intent);

        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            handler.removeCallbacks(sendUpdatesToUI);

        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }

    // Java class which runs when ride is active and shows the timer 

    public class RideIsActive extends AppCompatActivity {


        private TextView timer;
        private Button endRide;

        Intent intent;
        long timeSwapBuff = 0L;
        long updatedTime = 0L;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_ride_is_active);

            timer  = findViewById(R.id.timer);
            endRide = findViewById(R.id.endRide);

            startService(new Intent(this, BroadcastService.class));

            endRide.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    unregisterReceiver(broadcastReceiver);
                    stopService(intent);
                }
            });

        }

        private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                updateUI(intent);
            }
        };

        private void updateUI(Intent intent) {
            int time = intent.getIntExtra("time", 0);

            Log.d("Hello", "Time " + time);

            int hrs = time/3600;
            int mins = time / 60;
            int secs = time % 60;
            timer.setText(String.format("%02d", hrs) + ":" + String.format("%02d", mins) + ":"
                    + String.format("%02d", secs));
        }

        @Override
        protected void onResume() {
            super.onResume();
            registerReceiver(broadcastReceiver, new IntentFilter(BroadcastService.BROADCAST_ACTION));
        }



    //Layout

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".RideIsActive">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/timer"
            android:layout_centerInParent="true"
            android:textSize="25dp"
            android:textColor="#000000"
            android:text="00:00:00"/>

        <Button
            android:id="@+id/endRide"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="End Ride"
            android:textColor="@color/textBlack"
            android:background="@color/quantum_orange500"/>


    </RelativeLayout>

1 Answer 1

2

Each bike must have an id so under that id:

store the userStartTime in firebase

Store the userEndTime in firebase then also have the manager store the cycleStandEndTime.

You then have all the data in 3 fields in firebase and you can do whatever calculations you want.

totalUserUseTime = userEndTime - userStartTime

totalBikeRentalTime = cycleStandEndTime - userStartTime

Sign up to request clarification or add additional context in comments.

6 Comments

thanks @blundell for the answer. This seems to be a simple and a good approach. Will try it and let you know . My doubt is : What if user returns it the next day or some other day. Will it give us the exact total time? Is it fetching the clock time and then calculating,if yes then how to get the totalRentalTime from the Clock time? Thanks!
You shouldn't store clock time, but store seconds since epoch, i.e. store System.currentTimeMillis(). Only converting to clock time when you want to show it to the user. You then also might want to corroborate that time server side (in case people mess with their device clock)
So by what you are saying: I should first use System.currentTimeMillis() when the person booked the bike and store the same in database, then while checking out again i will store the System.currentTimeMillis() in database and subtracting 2nd from 1st will get me the totalRentalTime . Am i correct?
yeah exactly, that way you are storing the raw data, and can leverage it to do much more later
Yep that's what I mentioned in my other comment about device clock. You can use those approaches no problem. Instead of updating a database you could even ping a firebase function and then the function uses the time server-side to update the database
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.