Coding-Studio.com

Mobile App Development Tutorials & Insights

Amazon Bedrock AI Integration with Android App Without Backend | Kotlin & AWS Cognito Tutorial

Generative AI is becoming an important part of modern mobile applications. Android developers can integrate AI capabilities such as text generation, summarization, question answering, content generation and chat directly into mobile applications using Amazon Bedrock.

A common architecture is:

Android App → Your Backend API → Amazon Bedrock

But what if you don’t have your own backend server?

It is possible to build:

Android App → Amazon Cognito → Amazon Bedrock

In this architecture, the mobile application communicates directly with Amazon Bedrock using temporary AWS credentials rather than storing permanent AWS access keys inside the application.

Amazon recommends temporary credentials for applications, and its documentation specifically recommends Amazon Cognito for mobile applications.

This article explains the complete architecture and implementation approach.


What is Amazon Bedrock?

Amazon Bedrock is AWS’s managed generative AI service that provides access to foundation models from multiple providers through AWS APIs.

Instead of hosting an AI model yourself, your application sends a prompt to Amazon Bedrock and receives the generated response.

For example:

User enters:
"Summarize this paragraph"

        ↓

Android Application

        ↓

Amazon Bedrock Runtime

        ↓

Foundation Model

        ↓

AI-generated response

        ↓

Android UI

Amazon Bedrock currently supports multiple model providers and provides APIs such as Converse, Invoke, ConverseStream and InvokeModelWithResponseStream, depending on model compatibility. AWS recommends the bedrock-runtime endpoint for new applications.


Can Android Call Amazon Bedrock Directly?

Yes.

For an Android application, you don’t necessarily need to build your own REST API server.

A suitable architecture is:

                ┌──────────────────────┐
                │    Android App       │
                │                      │
                │ Kotlin / Compose     │
                └──────────┬───────────┘
                           │
                           │
                    Authentication
                           │
                           ▼
                ┌──────────────────────┐
                │   Amazon Cognito     │
                │   Identity Pool      │
                └──────────┬───────────┘
                           │
                 Temporary AWS
                    credentials
                           │
                           ▼
                ┌──────────────────────┐
                │ Amazon Bedrock       │
                │ Runtime              │
                └──────────┬───────────┘
                           │
                           ▼
                ┌──────────────────────┐
                │ Foundation Model     │
                │                      │
                │ Amazon / Anthropic / │
                │ Meta / Google / etc. │
                └──────────────────────┘

The important part is Amazon Cognito.

You should NOT put an AWS access key and secret access key directly inside an Android application.

Instead, Cognito can provide temporary, limited-privilege AWS credentials to the mobile application. AWS explicitly recommends Cognito for mobile applications.


Why Can’t I Put AWS Access Keys in the Android App?

You should never do this:

val accessKey = "AKIAxxxxxxxx"
val secretKey = "xxxxxxxxxxxxxxxx"

Even if you put these values inside:

  • local.properties
  • BuildConfig
  • encrypted strings
  • native C++ code
  • ProGuard/R8-obfuscated code

the credentials are ultimately distributed to the user’s device.

A determined attacker can extract application secrets.

The recommended approach is:

Android
   ↓
Cognito Identity Pool
   ↓
Temporary credentials
   ↓
Bedrock

Amazon Bedrock supports IAM permissions and temporary credentials.


Architecture Without Your Own Backend

The complete architecture looks like this:

                     AWS ACCOUNT
┌───────────────────────────────────────────────┐
│                                               │
│  ┌─────────────────┐                          │
│  │ Cognito         │                          │
│  │ Identity Pool   │                          │
│  └────────┬────────┘                          │
│           │                                   │
│           │ Temporary credentials             │
│           ▼                                   │
│  ┌─────────────────┐                          │
│  │ IAM Role        │                          │
│  │ Bedrock access  │                          │
│  └────────┬────────┘                          │
│           │                                   │
│           ▼                                   │
│  ┌─────────────────┐                          │
│  │ Bedrock Runtime │                          │
│  └────────┬────────┘                          │
│           │                                   │
│           ▼                                   │
│  ┌─────────────────┐                          │
│  │ Foundation      │                          │
│  │ Model           │                          │
│  └─────────────────┘                          │
│                                               │
└───────────────────────────────────────────────┘
                    ▲
                    │
                    │ Internet
                    │
          ┌─────────┴──────────┐
          │                    │
     ┌────┴─────┐       ┌─────┴─────┐
     │ Android  │       │   iOS     │
     │ App      │       │   App     │
     └──────────┘       └───────────┘

There is no custom API server in this architecture.


Step 1: Create an AWS Account

First, create or use an AWS account.

From the AWS Console, you will primarily work with:

  • Amazon Bedrock
  • Amazon Cognito
  • IAM
  • CloudWatch

You do not need EC2, Lambda, API Gateway or your own web server for this basic architecture.


Step 2: Select an Amazon Bedrock Model

Open:

AWS Console → Amazon Bedrock → Foundation Models

Choose a model that supports the Bedrock API you intend to use.

For a conversational Android application, the Converse API is particularly convenient because it provides a consistent interface across supported message-based models.

For example, you might use an Amazon Nova model.

AWS’s current SDK for Kotlin provides Bedrock Runtime examples using Amazon Nova and the Converse API.

The important point is that model availability and API compatibility vary by model and AWS Region, so check the current model documentation before selecting the model.


Step 3: Check Model Access

Depending on the model and current AWS requirements, you may need to enable or request access to the model.

In the AWS Console:

Amazon Bedrock
      ↓
Model access / model catalog
      ↓
Select required model
      ↓
Enable/request access if required

Do this before troubleshooting Android code.

A common mistake is to write the mobile integration first and then discover that the selected model isn’t available in the selected Region.


Step 4: Create a Cognito Identity Pool

Now create an Amazon Cognito Identity Pool.

The identity pool is responsible for providing temporary AWS credentials to the Android application.

Conceptually:

Android App
     │
     │ Request AWS credentials
     ▼
Cognito Identity Pool
     │
     │
     ▼
Temporary credentials
     │
     ▼
IAM Role

AWS documents Cognito identity pools as a way to provide temporary, limited-privilege credentials to applications.

For a prototype, you can configure an identity pool with unauthenticated identities.

For a production application, authenticated identities are generally preferable.


Step 5: Configure Authentication

There are two broad approaches.

Option A — Unauthenticated users

The application receives temporary credentials without requiring the user to sign in.

Architecture:

Android
   ↓
Cognito Identity Pool
   ↓
Temporary credentials
   ↓
Bedrock

This is convenient for a proof of concept.

However, you should be careful with permissions because anyone who can run your application may potentially obtain credentials associated with the unauthenticated role.


Option B — Authenticated users

A better production architecture is:

Android
   ↓
User Login
   ↓
Cognito User Pool / external IdP
   ↓
Cognito Identity Pool
   ↓
Temporary AWS credentials
   ↓
Bedrock

Cognito supports user authentication and federation with identity providers.

For example:

Google Login
     ↓
Cognito
     ↓
Identity Pool
     ↓
Temporary AWS credentials
     ↓
Bedrock

Step 6: Create a Restricted IAM Role

This is one of the most important steps.

Do NOT give the mobile application’s IAM role unrestricted AWS permissions.

For example, the role should only have the Bedrock actions your application requires.

A conceptual policy might look like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "*"
    }
  ]
}

The exact permissions should be narrowed further for your actual model/resource configuration where supported.

For applications using the Converse API, make sure the permissions and resources align with the Bedrock resources and inference configuration you’re using.

AWS provides IAM guidance for Amazon Bedrock and recommends temporary credentials rather than long-lived credentials.


Step 7: Configure the Android Project

The AWS SDK for Kotlin can target Android API level 24 or higher, making it suitable for modern Android applications.

Add the AWS SDK for Kotlin modules needed for your implementation.

For Bedrock Runtime, the relevant module is:

aws.sdk.kotlin.services.bedrockruntime

The current AWS SDK for Kotlin Bedrock Runtime module exposes operations including:

Converse
ConverseStream
InvokeModel
InvokeModelWithResponseStream

among others.

Keep AWS SDK dependencies updated rather than copying an old version from an outdated tutorial.


Step 8: Obtain Temporary Credentials

Your Android application should obtain temporary credentials through Cognito.

Conceptually:

class AwsCredentialManager {

    suspend fun getCredentials() {
        // Obtain temporary credentials
        // from Cognito Identity Pool
    }
}

The credentials should contain temporary authentication information such as:

Access Key
Secret Key
Session Token
Expiration

The important difference is:

Permanent credentials
        ❌
        ↓
Stored inside APK

Temporary credentials
        ✅
        ↓
Obtained at runtime
        ↓
Expire automatically

AWS recommends temporary credentials for this type of application architecture.


Step 9: Create the Bedrock Runtime Client

Once the application has temporary credentials, create a Bedrock Runtime client.

Conceptually:

val bedrockClient = BedrockRuntimeClient {
    region = "us-east-1"

    // Configure your temporary
    // Cognito-backed credentials provider
}

The AWS SDK for Kotlin provides a dedicated BedrockRuntimeClient for model inference.

The exact credential-provider implementation depends on how you configure Cognito in your Android project.


Step 10: Send a Prompt Using Converse

For a chat application, the Converse API is a good starting point.

The basic flow is:

User enters prompt

      ↓

ViewModel

      ↓

AI Repository

      ↓

BedrockRuntimeClient

      ↓

Converse()

      ↓

Foundation Model

      ↓

Response

      ↓

ViewModel

      ↓

Compose UI

A simplified Kotlin example looks like:

suspend fun askBedrock(
    prompt: String
): String {

    val message = Message {
        role = ConversationRole.User

        content = listOf(
            ContentBlock.Text(prompt)
        )
    }

    val response = bedrockClient.converse {
        modelId = "your-model-id"
        messages = listOf(message)
    }

    return response.output
        ?.asMessage()
        ?.content
        ?.firstOrNull()
        ?.asText()
        ?: ""
}

The exact generated SDK types can change with SDK versions, so treat this as an architectural example and use the current SDK API reference for your installed version.

AWS provides an official Kotlin example of using Bedrock’s Converse API.


Step 11: Implement Streaming Responses

For a chat application, waiting for the entire response isn’t always the best user experience.

Instead:

User
 ↓
"Explain Kotlin Coroutines"
 ↓
Bedrock
 ↓
"Coroutines..."
 ↓
"are..."
 ↓
"a..."
 ↓
"lightweight..."

The UI can progressively display the response.

Amazon Bedrock supports streaming APIs including ConverseStream and InvokeModelWithResponseStream.

Your architecture becomes:

Android
   ↓
ConverseStream
   ↓
Bedrock
   ↓
Streaming tokens/chunks
   ↓
Flow<String>
   ↓
Compose UI

This works very well with Kotlin coroutines and Flow.


Step 12: Android Architecture

For a production Android application, I would structure the application like this:

com.example.aiapp

├── data
│   ├── aws
│   │   ├── CognitoCredentialProvider
│   │   └── BedrockDataSource
│   │
│   └── repository
│       └── AIRepositoryImpl
│
├── domain
│   ├── model
│   │   └── AIResponse
│   │
│   └── repository
│       └── AIRepository
│
├── presentation
│   ├── chat
│   │   ├── ChatViewModel
│   │   └── ChatScreen
│   │
│   └── components
│
└── di
    └── AwsModule

The dependency flow should be:

Compose UI
    ↓
ViewModel
    ↓
Use Case
    ↓
Repository
    ↓
BedrockDataSource
    ↓
AWS SDK
    ↓
Amazon Bedrock

This keeps AWS-specific implementation details out of your UI.


Step 13: Example ViewModel

A simplified ViewModel could look like:

class ChatViewModel(
    private val repository: AIRepository
) : ViewModel() {

    private val _response = MutableStateFlow("")
    val response = _response.asStateFlow()

    fun askQuestion(prompt: String) {

        viewModelScope.launch {

            try {

                repository.ask(prompt)
                    .collect { chunk ->

                        _response.value += chunk
                    }

            } catch (e: Exception) {

                // Handle error
            }
        }
    }
}

This is particularly useful when using ConverseStream.


Step 14: Handle AWS Errors

Your application should handle at least:

Authentication failure
Authorization failure
AccessDeniedException
Throttling
Model unavailable
Invalid model ID
Invalid request
Network failure
Timeout
Expired credentials
Region mismatch

For example:

try {

    val result = repository.ask(prompt)

} catch (e: Exception) {

    when {
        e.message?.contains("AccessDenied") == true -> {
            // IAM / permission problem
        }

        e.message?.contains("Throttl") == true -> {
            // Retry/backoff
        }

        else -> {
            // Generic error
        }
    }
}

Do not expose raw AWS exception messages directly to users.


Step 15: Region Is Important

Suppose your application uses:

us-east-1

Your Bedrock model must be available in that Region or accessible through an appropriate inference configuration.

Architecture:

Android
   ↓
Cognito
   ↓
us-east-1
   ↓
Bedrock Runtime
   ↓
Model

If the model isn’t available in the selected Region, you can encounter errors even though your IAM configuration is correct.

AWS maintains model availability and compatibility information by Region and API.


Step 16: Add Guardrails

For a production AI application, consider Amazon Bedrock Guardrails.

For example:

User prompt
    ↓
Bedrock
    ↓
Guardrail
    ↓
Foundation Model
    ↓
Response

Guardrails can help control harmful or unwanted content and provide additional governance.

The Bedrock Runtime API includes ApplyGuardrail, and model/API compatibility should be checked for your specific architecture.


Step 17: Do You Need API Gateway?

For your specific requirement:

No.

You don’t necessarily need:

Android
 ↓
API Gateway
 ↓
Lambda
 ↓
Bedrock

You can use:

Android
 ↓
Cognito
 ↓
Bedrock

This eliminates:

  • Your own REST API
  • API Gateway configuration
  • Lambda function
  • Backend deployment
  • Backend server maintenance

However, there is an important security and product-design tradeoff.


Direct Bedrock vs Backend Architecture

Architecture 1 — Direct Mobile Integration

Android
   ↓
Cognito
   ↓
Bedrock

Advantages

  • No custom backend
  • Simple architecture
  • Lower infrastructure complexity
  • Fast prototype development
  • Good for learning
  • Excellent for proof-of-concept applications

Disadvantages

  • AWS permissions are exposed to the client through temporary credentials
  • Fine-grained server-side business logic is harder
  • Usage controls require careful IAM/Cognito design
  • Abuse protection becomes more important
  • Prompt/business rules are visible in the client
  • You have less centralized control

Architecture 2 — Backend-Based Integration

Android
   ↓
Your API
   ↓
Lambda / Server
   ↓
Bedrock

Advantages

  • Centralized authorization
  • Easier usage controls
  • Better business-rule enforcement
  • Easier server-side prompt management
  • Easier integration with databases
  • Easier centralized logging and analytics

Disadvantages

  • More infrastructure
  • More development work
  • Additional operational cost
  • Backend maintenance

Which Architecture Should You Use?

For your stated requirement:

“I don’t have my own API server and I want AWS → Mobile direct integration.”

Start with:

Android
   ↓
Amazon Cognito Identity Pool
   ↓
Temporary AWS credentials
   ↓
Amazon Bedrock Runtime
   ↓
Converse / ConverseStream
   ↓
Foundation Model

This is a legitimate architecture for a mobile application, provided that IAM permissions, authentication and abuse controls are designed carefully.

For a production application with sensitive business logic or high-value AI functionality, consider introducing a backend later.


Important Security Consideration

A very important point:

No backend does not mean no security.

Your Android application is distributed to potentially untrusted devices.

Therefore:

DO NOT

Android
 ↓
Permanent AWS Access Key
 ↓
Bedrock

Instead:

Android
 ↓
Cognito
 ↓
Temporary credentials
 ↓
Restricted IAM Role
 ↓
Bedrock

AWS specifically recommends temporary credentials and identifies Cognito as the recommended approach for mobile applications.


Complete End-to-End Flow

Here is the complete flow for an Android AI application:

                USER
                  │
                  ▼
          ┌───────────────┐
          │ Android App   │
          │ Jetpack       │
          │ Compose       │
          └───────┬───────┘
                  │
                  │ Login / Identity
                  ▼
          ┌───────────────┐
          │   Cognito     │
          │ Identity Pool │
          └───────┬───────┘
                  │
                  │ Temporary credentials
                  ▼
          ┌───────────────┐
          │   IAM Role    │
          │ Restricted    │
          │ Permissions   │
          └───────┬───────┘
                  │
                  │ Signed AWS request
                  ▼
          ┌───────────────┐
          │   Bedrock     │
          │    Runtime    │
          └───────┬───────┘
                  │
                  │ Converse
                  │ / ConverseStream
                  ▼
          ┌───────────────┐
          │ Foundation    │
          │ Model         │
          └───────┬───────┘
                  │
                  │ AI response
                  ▼
          ┌───────────────┐
          │ Android UI    │
          │ Chat / Result │
          └───────────────┘

Example Use Cases

This architecture can be used to build:

AI Chat App

User → Question → Bedrock → Answer

AI Summarization App

Document
   ↓
Android
   ↓
Bedrock
   ↓
Summary

AI Writing Assistant

User text
   ↓
"Rewrite professionally"
   ↓
Bedrock
   ↓
Improved text

AI Learning App

Question
   ↓
Bedrock
   ↓
Explanation
   ↓
Quiz generation

AI Mobile Developer Assistant

For example:

User:
"Explain this Kotlin code"

        ↓

Amazon Bedrock

        ↓

AI explanation

Recommended Technology Stack

For an Android implementation, a modern stack could be:

Android
│
├── Kotlin
├── Jetpack Compose
├── ViewModel
├── Coroutines
├── StateFlow
│
├── AWS SDK for Kotlin
│
├── Amazon Cognito
│   └── Identity Pool
│
└── Amazon Bedrock
    └── Bedrock Runtime
        ├── Converse
        └── ConverseStream

The AWS SDK for Kotlin officially supports Android API level 24+ and provides Bedrock Runtime examples.


Recommended Development Strategy

If you are learning Amazon Bedrock integration, don’t start with a complex production application.

Build it in stages.

Phase 1 — AWS Console

Create AWS account
      ↓
Choose Region
      ↓
Enable model access
      ↓
Test model in Bedrock console

Phase 2 — Cognito

Create Identity Pool
      ↓
Configure authentication
      ↓
Create IAM role
      ↓
Add minimal Bedrock permissions

Phase 3 — Android

Create Android project
      ↓
Add AWS SDK for Kotlin
      ↓
Configure Cognito
      ↓
Obtain temporary credentials
      ↓
Create BedrockRuntimeClient

Phase 4 — AI

Text input
      ↓
Converse()
      ↓
AI response
      ↓
Display in Compose

Phase 5 — Production

Add:

Authentication
Rate limiting strategy
IAM restrictions
Guardrails
Error handling
Logging
Monitoring
Retry strategy
Cost controls

Cost Considerations

Amazon Bedrock is generally usage-based rather than requiring you to operate a model server yourself.

Your costs depend on factors such as:

  • Model
  • Input tokens
  • Output tokens
  • Requests
  • Region
  • Streaming/other API usage
  • Additional Bedrock features

Therefore, don’t assume that a direct mobile architecture is automatically free.

Before releasing the application publicly, configure appropriate AWS billing alerts and monitor Bedrock usage.


Final Architecture Recommendation

For your exact requirement, I recommend starting with this:

                  ANDROID APP
                       │
                       ▼
               Amazon Cognito
                Identity Pool
                       │
                       ▼
             Temporary Credentials
                       │
                       ▼
                  IAM Role
                       │
              Limited Bedrock
                permissions
                       │
                       ▼
             Bedrock Runtime
                       │
              ┌────────┴────────┐
              │                 │
          Converse        ConverseStream
              │                 │
              └────────┬────────┘
                       ▼
                 AI Model
                       │
                       ▼
                 AI Response
                       │
                       ▼
                 Android UI

The key takeaway is:

You do not need to build your own API server just to connect an Android application to Amazon Bedrock.

A direct mobile architecture can use Amazon Cognito + temporary AWS credentials + IAM + Amazon Bedrock Runtime, with the Android application calling Bedrock directly. AWS provides an SDK for Kotlin that supports Android and includes Bedrock Runtime examples.

For new Bedrock applications, AWS currently recommends the bedrock-runtime endpoint, with Converse being a useful model-agnostic API for supported message-based models.


All the below queries are answered in this post.

How to integrate Amazon Bedrock with Android app

How to use Amazon Bedrock without backend

Amazon Bedrock direct integration with Android

Amazon Bedrock Kotlin Android tutorial

How to call Amazon Bedrock from mobile app

Amazon Cognito and Bedrock Android integration

AWS generative AI integration in Android

Build AI Android app using Amazon Bedrock

Thank you..

Leave a Reply

Your email address will not be published. Required fields are marked *