Skip to content
This repository was archived by the owner on Jun 2, 2026. It is now read-only.

Integrate backend with a new Android app in Android Studio #53

Description

@garotm

Integrate backend with a new Android app in Android Studio

1. Create a New Android Project:

  • Open Android Studio: Launch Android Studio.
  • Start a New Project: Click "Start a new Android Studio project."
  • Choose "Empty Compose Activity": Select this template for a project using Jetpack Compose.
  • Click "Next".
  • Configure Your Project:
    • Name: Choose a name for your app (e.g., "RunOn").
    • Package name: Use com.flexrpl.runon (to match your backend and previous discussions).
    • Save location: Choose where you want to save your project.
    • Language: Select "Kotlin."
    • Minimum SDK: Choose an appropriate minimum SDK (API level).
  • Click "Finish."

2. New Project Structure:

com.flexrpl.runon/
  ├── data/
  │   ├── api/          # Retrofit interfaces
  │   ├── models/       # Data classes
  │   └── repository/   # Repository pattern
  ├── di/               # Dependency injection
  ├── ui/
  │   ├── components/   # Reusable UI components
  │   ├── screens/      # Main screens
  │   └── theme/        # App theme
  └── utils/            # Utility classes

3. Add Dependencies:

  • Open your app-level build.gradle file (usually app/build.gradle or build.gradle.kts for newer projects).
  • Add the following dependencies inside the dependencies block:
implementation("com.google.android.gms:play-services-auth:21.0.0") // Google Sign-In
implementation("com.squareup.retrofit2:retrofit:2.9.0") // Retrofit
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // Gson Converter for Retrofit (or use another converter like Moshi)
implementation("com.google.code.gson:gson:2.10.1") // Gson for JSON parsing (if not using a different library)
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") // Optional: For logging network requests
// You might need the Google API Client for handling dates/times if your backend doesn't return them in a readily usable format:
implementation("com.google.api-client:google-api-client-android:2.3.0")
implementation("com.google.apis:google-api-services-calendar:v3-rev20231027-2.0.0")
  • Sync Project with Gradle Files: Click the "Sync Now" button in the bar that appears at the top of Android Studio after you modify the build.gradle file.

4. Implement Google Sign-In:

  • Follow the Official Guide: Refer to the official Google Sign-In for Android documentation for detailed instructions: https://developers.google.com/identity/sign-in/android/sign-in [invalid URL removed]
  • Create GoogleSignInClient: In your main activity (or a dedicated authentication class), create a GoogleSignInClient object:
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions

// ...

lateinit var googleSignInClient: GoogleSignInClient

// ... in onCreate() or a similar initialization method ...

val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
    .requestIdToken(getString(R.string.server_client_id)) // Get the Web Client ID from strings.xml
    .requestEmail()
    .build()

googleSignInClient = GoogleSignIn.getClient(this, gso)
  • Add Web Client ID to strings.xml:
    • Open res/values/strings.xml.

    • Add a new string resource for your web client ID:

      ```xml
      <string name="server_client_id">YOUR_WEB_CLIENT_ID</string>
      ```
      
      Replace `YOUR_WEB_CLIENT_ID` with the actual **Web Client ID** from your Google Cloud Console (under Credentials).
      
  • Handle Sign-In Button: Add a sign-in button to your UI and trigger the sign-in flow when it's clicked.
  • Get ID Token: After successful sign-in, get the ID token from the GoogleSignInAccount object:
val account = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java)
val idToken = account?.idToken
  • Send ID Token to Backend: Send the idToken to your backend for verification (you'll do this in the Retrofit network calls later).

5. Create Data Models:

  • Create Kotlin data classes to represent the JSON objects you'll be sending to and receiving from your backend. For example:
data class SearchQuery(val query: String)

data class SearchResult(
    val title: String,
    val snippet: String,
    val link: String,
    val extractedDateTime: String? = null // Optional
)

data class CalendarEvent(
    val query: String? = null,
    val searchResult: SearchResult? = null,
    val startTime: String, // Example format: "2023-12-29T10:00:00"
    val endTime: String   // Example format: "2023-12-29T11:00:00"
)

6. Create a Service Interface (Retrofit):

  • Define a Kotlin interface to represent your backend API endpoints using Retrofit annotations:
import retrofit2.http.Body
import retrofit2.http.Header
import retrofit2.http.POST

interface RunOnApiService {
    @POST("/search")
    suspend fun search(
        @Header("Authorization") idToken: String, // Pass ID token in header
        @Body query: SearchQuery
    ): List<SearchResult>

    @POST("/calendar/event")
    suspend fun createCalendarEvent(
        @Header("Authorization") idToken: String, // Pass ID token in header
        @Body event: CalendarEvent
    ): Response<Unit> // Or a custom response object indicating success/failure
}

7. Implement Network Calls (Retrofit):

  • Create a Retrofit instance:
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

// ...

val logging = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY // Log request and response bodies (for debugging)
}

val client = OkHttpClient.Builder()
    .addInterceptor(logging)
    .build()

val retrofit = Retrofit.Builder()
    .baseUrl("YOUR_BACKEND_URL") // Replace with your backend URL (local or deployed)
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val apiService = retrofit.create(RunOnApiService::class.java)
  • Make network calls using the apiService instance and the functions you defined in the interface. For example:
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

// ...

// Example of making a search request:
runBlocking { // Or use viewModelScope.launch if you're inside a ViewModel
    launch {
        try {
            val idToken = "Bearer $idToken"
            val results = apiService.search(idToken, SearchQuery("running events near me"))
            // Process the search results and update the UI
        } catch (e: Exception) {
            // Handle error
        }
    }
}

8. Connect UI to Backend:

  • Design UI: Create the UI elements in your Compose activity (search bar, buttons, result display, etc.).
  • Trigger Network Calls: When the user performs an action (e.g., clicks a search button), trigger the corresponding network call to your backend using the apiService and the idToken.
  • Handle Responses: Update your UI based on the responses you receive from the backend. Display search results, show loading indicators, and handle errors appropriately.

Important Considerations:

  • Backend URL:
    • For local development, you'll likely use a localhost URL with ngrok (as we discussed before).
    • When you deploy your backend, you'll need to update the baseUrl in your Retrofit setup.
  • Error Handling: Implement proper error handling in your network calls and UI to provide a good user experience.
  • Threading: Make sure to perform network calls on a background thread (using coroutines, as shown in the example) to avoid blocking the main thread and causing UI freezes.
  • Security:
    • Always send the ID token in the Authorization header as a Bearer token (e.g., Authorization: Bearer <idToken>).
    • Do not hardcode your Web Client ID directly in your code. Use strings.xml to store it securely.

This comprehensive guide should provide you with a solid foundation for integrating your backend with your Android app.

Remember to replace placeholder values like YOUR_WEB_CLIENT_ID and YOUR_BACKEND_URL with your actual values.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

  • Status
    Backlog

Relationships

None yet

Development

No branches or pull requests

Issue actions