MahaPrasada / Vatsalya

android app
MIT License
1 stars 0 forks source link

Ridesharing driver & rider apps using HyperTrack SDK

👉 Looking for the iOS version?

Apps demo

Uber’s business model has given rise to a large number of ridesharing services. Among other things, X equals moving, parking, courier, groceries, flowers, alcohol, dog walks, massages, dry cleaning, vets, medicines, car washes, roadside assistance and marijuana. Through these on-demand platforms, supply and demand are aggregated online for services to be fulfilled offline.

This open source repo/s uses HyperTrack SDK for developing real world Uber-like consumer & driver apps.

Architecture

Architecture

Step by step process of communication: 1. **Request pickup at location X for a ride to location Y** - Prior to requesting a pickup, Rider App has already signed up with Ride Sharing App Backend. Ride Sharing App Backend created a new document with the rider's data in its users collection - The rider chooses pickup and dropoff places. Rider App sends a request to Ride Sharing App Backend, which creates a new order in its orders collection in Cloud Firestore 2. **Assign ride to location X to driver** - Prior to the assignment, Driver App already signed up with Ride Sharing App Backend: - Ride Sharing App Backend created a new document with the driver's data in its users collection in Cloud Firestore - Driver App added name and metadata through HyperTrack SDK - HyperTrack SDK started tracking the driver's location - From this point, the driver can be seen in HyperTrack Dashboard 3. **Driver accepts ride to location X** - Driver App is checking with Ride Sharing App Backend periodically, looking for orders with the `NEW` status - Once the new order(s) show up, the driver can accept a chosen order. Ride Sharing Backend changes the order status to `ACCEPTED` and sets the driver's data in the order 4. **Create trip with destination X via Trips API** - Once the order status is changed, Ride Sharing Backend triggers `updateOrderStatus` Firebase Cloud Function. The function creates a trip from the driver's current position to the rider's pickup point using [HyperTrack API](https://www.hypertrack.com/docs/guides/track-trips-with-destination). Once the troop is created, the order status is changed to `PICKING_UP`. 5. **Rider tracks driver with ETA to location** - Driver and Rider Apps are subscribed to their order. When they see that the status is `PICKING_UP`, they use HyperTrackViews SDK to display the trip live from the order on a map 6. **Driver picks up rider at location X** - When the driver crosses destination geofence of the rider's pickup point, a webhook from HyperTrack to Ride Sharing App Backend's Firebase Cloud Function is triggered. This function updates the order to `REACHED_PICKUP` state 7. **Complete trip with destination X and create trip with destination Y via Trips API** - Upon receiving `REACHED_PICKUP` order state, Driver App shows a "Start Trip" button. When the driver presses it, Driver App changes the order status to `STARTED_RIDE` state - Upon receiving the `STARTED_RIDE` state, Ride Sharing App Backend's Firebase Cloud Function calls [HyperTrack APIs](https://hypertrack.com/docs/references/#references-apis-trips-complete-trip) to complete the previous trip and creates a new trip to the rider's destination. After the trip is created, the function updates the order status to `DROPPING_OFF` - When Driver and Rider Apps see `PICKING_UP` status, they both use HyperTrack Views SDK to display the new trip on a map 8. **Driver drops off rider at Location Y** - When the driver crosses the destination geofence of the rider's dropoff point, a webhook from HyperTrack to Ride Sharing App Backend's Firebase Cloud Function triggers again. This function updates the order to `REACHED_DROPOFF` state - Upon receiving `REACHED_DROPOFF` order state, the Driver app shows a "End Trip" button. When the driver presses it, Driver app changes the order status to `COMPLETED` state 9. **Complete trip with destination Y via Trips API** - Ride Sharing App Backend's Firebase Cloud Function proceeds to call [HyperTrack APIs](https://hypertrack.com/docs/references/#references-apis-trips-complete-trip) complete the dropoff trip - When this trip is completed, Rider and Driver Apps show trip summary using HyperTrack Views SDK

How Ridesharing sample apps use HyperTrack API

Ridesharing apps use HyperTrack Trips API to create and complete trips by using Firebase Cloud Functions. Firebase allows ridesharing sample appilcations integrate with HyperTrack Trips API via backend server integration.

For each rider's request that is accepted by the driver, a trip is created for the driver to pick up the rider at the rider's location. Once the pick up is completed, the trip is completed and then the new trip is created for the driver to get the rider to rider's destination. Once the rider reaches the destination and is dropped off, the trip is completed.

How Ridesharing sample apps use HyperTrack SDK

Ridesharing Driver app uses HyperTrack SDK to track driver's position in 3 cases:

You can find the SDK documentation here.

Push notifications

Driver app integrates HyperTrack SDK with push notifictions to:

SDK Initialization

HyperTrack SDK initializes successfully when nothing prevents it from tracking.

HyperTrack hyperTrack = HyperTrack.getInstance(context, HyperTrackUtils.getPubKey(context));

DeviceID, name and metadata

DeviceID is used to identify a device on HyperTrack. Driver app uses this ID when creating a user in Firebase. Device name and metadata are displayed in HyperTrack's dashboard. To make it easy for operators to find drivers by their name or filter them by metadata, Driver app sets those fields using User model from Firebase:

if (User.USER_ROLE_DRIVER.equals(user.role)) {
    HyperTrack hyperTrack = HyperTrack.getInstance(this, HyperTrackUtils.getPubKey(this));
    hyperTrack.setDeviceName(user.name);
    Map<String, Object> metadata = new HashMap<>();
    metadata.put("name", user.name);
    metadata.put("phone_number", user.phoneNumber);
    Map<String, Object> car = new HashMap<>();
    car.put("model", user.car.model);
    car.put("license_plate", user.car.licensePlate);
    metadata.put("car", car);
    hyperTrack.setDeviceMetadata
    user.deviceId = hyperTrack.getDeviceID();
}
FirebaseFirestoreApi.createUser(user)
        .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
            @Override
            public void onSuccess(DocumentReference documentReference) {
                Log.d(TAG, "DocumentSnapshot added with ID: " + documentReference.getId());
                user.id = documentReference.getId();
                next(user);
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "Error adding document", e);
            }
        });

In HyperTrackViews SDK snippets, both Driver and Rider apps are using this ID to display driver on a map.

How Ridesharing sample apps use HyperTrack Views SDK

Both Rider and Driver apps use HyperTrackViews SDK to display realtime location and trip updates on a map.

Subscribing to location updates

Both Driver and Rider apps subscribe to driver's location updates using subscribeToDeviceUpdates(String, DeviceUpdatesHandler) method:

hyperTrackViews.subscribeToDeviceUpdates(mState.getUser().deviceId, this);

@Override
public void onTripUpdateReceived(Trip trip) {
    if (trip != null && mState.getOrder() != null && trip.getTripId().equals(mState.getOrder().tripId)) {
        mState.updateTrip(trip);
        if (Order.COMPLETED.equals(mState.getOrder().status) && "completed".equals(trip.getStatus())) {
            User user = User.USER_ROLE_DRIVER.equals(mState.getUser().role)
                    ? mState.getOrder().rider : mState.getOrder().driver;
            mView.showTripEndInfo(mState.getTrip(), user);
        }
    }
}

Placing device or trip on a map

Initialize HyperTrackViews and HyperTrackMap.

hyperTrackViews = HyperTrackViews.getInstance(mContext, HyperTrackUtils.getPubKey(context));
GoogleMapAdapter mapAdapter = new GoogleMapAdapter(googleMap, mapConfig);
hyperTrackMap = HyperTrackMap.getInstance(mContext, mapAdapter);

Rider's map binding:

hyperTrackMap.bind(new GpsLocationProvider(mContext));

After the order has driver's info and trip_id:

if (mState.driver == null) {
    GoogleMapAdapter mapAdapter = new GoogleMapAdapter(googleMap, driverMapConfig);
    mapAdapter.addTripFilter(this);
    mState.driver = HyperTrackMap.getInstance(mContext, mapAdapter);
    mState.driver.bind(hyperTrackViews, deviceId);
}
if (!TextUtils.isEmpty(mState.getOrder().tripId)) {
    mState.driver.subscribeTrip(mState.getOrder().tripId);
}

Driver's map binding:

hyperTrackMap.bind(hyperTrackViews, mState.getUser().deviceId);
hyperTrackMap.adapter().addTripFilter(this);

Making the device or trip center on a map

In apps that show tracking data, usually user needs to see all the data on the screen, be it current location, trip polylines or destination markers. This view needs to re-zoom with animation every time the data is changing. This is done in the real Uber app.

mapAdapter.setCameraFixedEnabled(true);

How to Begin

1. Get your keys

2. Set up rider & driver app

# Clone this repository
$ git clone https://github.com/hypertrack/ridesharing-android.git

# cd into the project directory
$ cd ridesharing-android

3. Set up Firebase

4. Run the apps

Documentation

For detailed documentation of the APIs, customizations and what all you can build using HyperTrack, please visit the official docs.

Contribute

Feel free to clone, use, and contribute back via pull requests. We'd love to see your pull requests - send them in! Please use the issues tracker to raise bug reports and feature requests.

We are excited to see what live location feature you build in your app using this project. Do ping us at help@hypertrack.com once you build one, and we would love to feature your app on our blog!

Support

Join our Slack community for instant responses. You can also email us at help@hypertrack.com.