Practical 8
a) Aim: To create an uber clone.
Step to create a project
1. install the latest version of android studio
2. Start Android studio -> file -> new -> new project
3. Select empty activity and next
4. Enter project name of project and select language as kotlin and minimum sdk as API
24(“Nougat”;Android 7.0) and finish
5. After loading you will get a ‘MainActivity.kt’ and ‘activity_main.xml’. 7. Now you are
ready to code.
activity_practical_no8a.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:id="@+id/main" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PracticalNo8a">
<!-- Toolbar -->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:title="Ride Booking"
android:titleTextColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.gms.maps.MapView
android:id="@+id/mapView"
android:layout_width="0dp" android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Pickup Location -->
<EditText
android:id="@+id/pickupLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Pickup Location"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mapView" />
<!-- Destination Location -->
<EditText
android:id="@+id/destinationLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Destination"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pickupLocation" />
<!-- Fare Estimate --> <TextView
android:id="@+id/fareEstimate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Estimated Fare: Rs. 0.00"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/destinationLocation" />
<!-- Book Ride Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/bookRideButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@android:color/holo_blue_dark"
android:padding="12dp" android:text="Book Ride"
android:textColor="@android:color/white"
android:textSize="18sp" app:cornerRadius="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fareEstimate" />
<!-- View Rides Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/viewRidesButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@android:color/holo_green_dark"
android:padding="12dp" android:text="View Rides"
android:textColor="@android:color/white"
android:textSize="18sp" app:cornerRadius="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bookRideButton" />
<!-- Ride Details List -->
<ListView android:id="@+id/rideHistoryList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:padding="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewRidesButton" />
</androidx.constraintlayout.widget.ConstraintLayout>
PracticalNo8a.kt
package com.example.parcticaltyit
import android.Manifest import
android.annotation.SuppressLint import
android.content.pm.PackageManager import
android.location.Location import android.os.Bundle import
android.widget.ArrayAdapter import android.widget.Button
import android.widget.EditText import
android.widget.ListView import android.widget.TextView
import android.widget.Toast import
androidx.appcompat.app.AppCompatActivity import
androidx.core.app.ActivityCompat import
com.example.parcticaltyit.adapter.RideDatabaseHelper import
com.google.android.gms.location.FusedLocationProviderClie
nt import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap import
com.google.android.gms.maps.MapView import
com.google.android.gms.maps.OnMapReadyCallback import
com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
class PracticalNo8a : AppCompatActivity(), OnMapReadyCallback {
private lateinit var dbHelper: RideDatabaseHelper
private lateinit var pickupEditText: EditText private
lateinit var destinationEditText: EditText private lateinit
var fareTextView: TextView private lateinit var
bookRideButton: Button private lateinit var
viewRidesButton: Button private lateinit var
rideHistoryListView: ListView private lateinit var
rideListAdapter: ArrayAdapter<String> private val
rideList = ArrayList<String>()
private lateinit var mapView: MapView
private lateinit var googleMap: GoogleMap
private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?)
{ super.onCreate(savedInstanceState)
setContentView(R.layout.activity_practical_no8a)
// Initialize UI components dbHelper =
RideDatabaseHelper(this) pickupEditText =
findViewById(R.id.pickupLocation) destinationEditText =
findViewById(R.id.destinationLocation) fareTextView =
findViewById(R.id.fareEstimate) bookRideButton =
findViewById(R.id.bookRideButton) viewRidesButton =
findViewById(R.id.viewRidesButton) rideHistoryListView =
findViewById(R.id.rideHistoryList)
// Set up adapter for ListView rideListAdapter = ArrayAdapter(this,
android.R.layout.simple_list_item_1, rideList) rideHistoryListView.adapter =
rideListAdapter
// Initialize MapView mapView =
findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
// Initialize Location Services
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
// Handle ride booking
bookRideButton.setOnClickListener { val pickup =
pickupEditText.text.toString().trim() val destination =
destinationEditText.text.toString().trim()
val fare = "₹" + (100..500).random().toString() // Random fare for demo
if (pickup.isNotEmpty() && destination.isNotEmpty()) {
if (dbHelper.insertRide(pickup, destination, fare))
{ Toast.makeText(this, "Ride booked successfully!",
Toast.LENGTH_SHORT).show()
fareTextView.text = "Estimated Fare: $fare"
} else {
Toast.makeText(this, "Booking failed. Try again.",
Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "Please enter valid locations",
Toast.LENGTH_SHORT).show()
}
}
// Handle viewing ride history
viewRidesButton.setOnClickListener {
loadRides()
}
}
override fun onMapReady(map: GoogleMap)
{ googleMap = map
if (ActivityCompat.checkSelfPermission(
this, Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission( this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
){
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
),
LOCATION_PERMISSION_REQUEST_CODE
)
return
}
googleMap.isMyLocationEnabled = true // Show Blue Dot on Map
getCurrentLocation()
}
@SuppressLint("MissingPermission") private fun getCurrentLocation()
{ fusedLocationClient.lastLocation.addOnSuccessListener { location: Location?
-> if (location != null) { val userLatLng = LatLng(location.latitude,
location.longitude)
googleMap.addMarker(MarkerOptions().position(userLatLng).title("Your
Location"))
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLatLng, 15f))
} else {
Toast.makeText(this, "Unable to fetch location", Toast.LENGTH_SHORT).show()
}
}
}
@SuppressLint("Range") private
fun loadRides() { val cursor =
dbHelper.getAllRides()
rideList.clear()
if (cursor.moveToFirst()) {
do {
val pickup =
cursor.getString(cursor.getColumnIndex(RideDatabaseHelper.COLUMN_PICKUP))
val destination =
cursor.getString(cursor.getColumnIndex(RideDatabaseHelper.COLUMN_DESTINATION))
val fare =
cursor.getString(cursor.getColumnIndex(RideDatabaseHelper.COLUMN_FARE))
rideList.add("From: $pickup\nTo: $destination\nFare: $fare")
} while (cursor.moveToNext())
} cursor.close()
rideListAdapter.notifyDataSetChanged()
}
override fun onResume()
{ super.onResume()
mapView.onResume()
}
override fun onPause()
{ super.onPause()
mapView.onPause()
}
override fun onDestroy()
{ super.onDestroy()
mapView.onDestroy()
}
override fun onLowMemory()
{ super.onLowMemory()
mapView.onLowMemory()
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions:
Array<out String>, grantResults:
IntArray
){
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
getCurrentLocation()
} else {
Toast.makeText(this, "Location permission denied",
Toast.LENGTH_SHORT).show()
}
}
}
companion object { private const val
LOCATION_PERMISSION_REQUEST_CODE = 1
}
}
Create a new ‘Empty Activity’ from App -> New -> Activity -> Empty Activity and name it
as shown below. Let its xml file be default.
RideDatabaseHelper.kt
package com.example.uber
import android.content.ContentValues import
android.content.Context import
android.database.Cursor import
android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
class RideDatabaseHelper(context: Context) :
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object { private const val
DATABASE_NAME = "rides.db" private const val
DATABASE_VERSION = 1 const val
TABLE_NAME = "rides" const val COLUMN_ID =
"id" const val COLUMN_PICKUP = "pickup"
const val COLUMN_DESTINATION = "destination"
const val COLUMN_FARE = "fare"
}
override fun onCreate(db: SQLiteDatabase) { val
createTableQuery = ("CREATE TABLE $TABLE_NAME ("
+ "$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "$COLUMN_PICKUP TEXT, "
+ "$COLUMN_DESTINATION TEXT, "
+ "$COLUMN_FARE TEXT)")
db.execSQL(createTableQuery)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS $TABLE_NAME") onCreate(db)
}
fun insertRide(pickup: String, destination: String, fare: String): Boolean {
val db = this.writableDatabase val values = ContentValues()
values.put(COLUMN_PICKUP, pickup)
values.put(COLUMN_DESTINATION, destination)
values.put(COLUMN_FARE, fare)
val result = db.insert(TABLE_NAME, null, values)
db.close()
return result != -1L
}
fun getAllRides(): Cursor { val db = this.readableDatabase
return db.rawQuery("SELECT * FROM $TABLE_NAME", null)
}
}
Output:
Conclusion: This program has been implemented and executed successfully.