# AI Study Notes Maker — APK-ready Android Studio Project (Kotlin + Jetpack Compose)
This single-file document contains a **complete Android Studio project layout** and the essential files you can copy into a new project to build an APK. It's optimized for quick setup and uses Jetpack Compose, Kotlin coroutines, and OkHttp to call an AI notes-generation API (replace with your preferred AI endpoint).
> ⚠️ You must provide your own AI API key and set the endpoint URL. The sample uses a generic POST JSON format. Adjust headers/payload to match your AI provider (OpenAI, local LLM, etc.).
---
## Project file tree (what to create in Android Studio)
```
AIStudyNotesMaker/
├─ app/
│ ├─ src/main/AndroidManifest.xml
│ ├─ src/main/java/com/example/aistudynotes/MainActivity.kt
│ ├─ src/main/res/layout/ (not used — Compose)
│ ├─ src/main/res/values/themes.xml
│ ├─ src/main/res/values/colors.xml
│ └─ ...
├─ build.gradle (Project)
└─ app/build.gradle (Module: app)
```
---
### 1) Project-level build.gradle (Gradle Kotlin DSL style as text to paste in settings)
**(Create a standard Android project in Android Studio and replace module-level build.gradle with the one below.)**
```groovy
// Project-level build.gradle (Gradle Groovy DSL)
buildscript {
ext.kotlin_version = '1.9.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
```
---
### 2) app/build.gradle (Module)
```groovy
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.aistudynotes'
compileSdk 34
defaultConfig {
applicationId "com.example.aistudynotes"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
// Make sure to enable compose
vectorDrawables.useSupportLibrary = true
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.3'
}
kotlinOptions {
jvmTarget = '17'
}
packagingOptions {
resources {
excludes += ['/META-INF/{AL2.0,LGPL2.1}']
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.11.0'
implementation 'androidx.activity:activity-compose:1.8.0'
// Compose
implementation 'androidx.compose.ui:ui:1.5.3'
implementation 'androidx.compose.material:material:1.5.3'
implementation 'androidx.compose.ui:ui-tooling-preview:1.5.3'
// Lifecycle
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// OkHttp for networking
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.squareup.okio:okio:3.5.0'
// Kotlinx serialization (optional)
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0'
// Tooling
debugImplementation 'androidx.compose.ui:ui-tooling:1.5.3'
}
```
---
### 3) AndroidManifest.xml
```xml
```
---
### 4) MainActivity.kt (Compose UI + networking)
```kotlin
package com.example.aistudynotes
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AIStudyNotesApp()
}
}
}
@Composable
fun AIStudyNotesApp() {
var inputText by remember { mutableStateOf(TextFieldValue("")) }
var apiKey by remember { mutableStateOf("") }
var result by remember { mutableStateOf("") }
var loading by remember { mutableStateOf(false) }
val scroll = rememberScrollState()
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
Column(
modifier = Modifier
.padding(16.dp)
.verticalScroll(scroll),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("AI Study Notes Maker", style = MaterialTheme.typography.h5)
Spacer(modifier = Modifier.height(12.dp))
OutlinedTextField(
value = apiKey,
onValueChange = { apiKey = it },
label = { Text("AI API Key (paste here)") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = inputText,
onValueChange = { inputText = it },
label = { Text("Paste chapter text or upload content") },
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
maxLines = 20
)
Spacer(modifier = Modifier.height(12.dp))
Button(onClick = {
if (apiKey.isBlank()) {
result = "Please enter your AI API key."
return@Button
}
loading = true
result = ""
CoroutineScope(Dispatchers.IO).launch {
val resp = callAiGenerateNotes(apiKey, inputText.text)
loading = false
result = resp
}
}, modifier = Modifier.fillMaxWidth()) {
Text(if (loading) "Generating..." else "Generate Notes")
}
Spacer(modifier = Modifier.height(12.dp))
Text("Output:", style = MaterialTheme.typography.subtitle1)
Spacer(modifier = Modifier.height(8.dp))
Text(result)
Spacer(modifier = Modifier.height(24.dp))
Text("Tip: Use small chapters (<= 2k chars) for best results.")
}
}
}
}
// Networking: simple OkHttp POST. Change endpoint and payload to match your AI provider.
suspend fun callAiGenerateNotes(apiKey: String, content: String): String {
if (content.isBlank()) return "Please paste some study material to generate notes."
try {
val client = OkHttpClient.Builder().build()
// Example endpoint — replace with real AI endpoint
val url = "https://api.example.ai/v1/generate-notes"
// Example JSON payload — adjust according to the API you use
val json = JSONObject()
json.put("prompt", buildPrompt(content))
json.put("max_tokens", 800)
val mediaType = "application/json; charset=utf-8".toMediaType()
val body = json.toString().toRequestBody(mediaType)
val request = Request.Builder()
.url(url)
.post(body)
.addHeader("Authorization", "Bearer $apiKey")
.addHeader("Content-Type", "application/json")
.build()
val response = client.newCall(request).execute()
val respBody = response.body?.string() ?: ""
// Attempt to parse common response shapes: prefer simple return
// If your API returns structured JSON, extract the text accordingly.
return parseAiResponse(respBody)
} catch (e: Exception) {
e.printStackTrace()
return "Error: ${e.localizedMessage}"
}
}
fun buildPrompt(content: String): String {
// This is the template prompt you already liked; tweak as needed.
return "You are an AI Study Notes Generator.\nTake the following study material and produce: 1) Chapter Summary (150-200 words), 2) Key Points (8-15 bullets), 3) Important Definitions (5-10), 4) 10 MCQs with answers, 5) 5 Short Q&A, 6) 3 Long Q&A, 7) 10 Flashcards, 8) Text Mindmap.\nMaterial:\n" + content
}
fun parseAiResponse(responseBody: String): String {
// Best-effort: if response is JSON with a "text" field or similar, extract it.
try {
val obj = JSONObject(responseBody)
// check common keys
if (obj.has("text")) return obj.getString("text")
if (obj.has("output")) return obj.getString("output")
if (obj.has("choices")) {
val choices = obj.getJSONArray("choices")
if (choices.length() > 0) {
val first = choices.getJSONObject(0)
if (first.has("text")) return first.getString("text")
if (first.has("message")) {
val msg = first.getJSONObject("message")
if (msg.has("content")) return msg.getString("content")
}
}
}
// fallback to raw
return responseBody
} catch (e: Exception) {
return responseBody
}
}
```
---
### 5) Basic theme files (values)
**colors.xml**
```xml
#BB86FC
#6200EE
#3700B3
#03DAC5
```
**themes.xml** (simplified)
```xml
```
---
## How to build & generate APK (short steps)
1. Open Android Studio -> New Project -> Empty Compose Activity.
2. Replace the generated `MainActivity.kt`, `AndroidManifest.xml`, and module `build.gradle` with the files above.
3. Sync Gradle. Add INTERNET permission in manifest (provided).
4. In `MainActivity.kt` replace `url` in `callAiGenerateNotes` with your AI provider endpoint and ensure the payload matches the API.
5. Run on emulator or device. Generate -> After checking, Build -> Build Bundle(s) / APK(s) -> Build APK(s).
---
## Notes & Next steps you might want
- ✅ **Add file upload**: Accept PDFs/images and extract text (use ML Kit or PDFBox) — I can add that next.
- ✅ **Store API key securely**: Use EncryptedSharedPreferences, not plain text input.
- ✅ **Token limits & truncation**: Chunk long chapters and send multiple prompts.
- ✅ **Offline mode / on-device LLM**: Integrate local LLM (e.g., GGML-based) for offline generation.
- ✅ **Export PDF**: Convert generated notes to PDF using Android PdfDocument.
---
If you want, I can now:
- Produce the full project as a ZIP you can download (instructions included), or
- Add PDF export & print button, or
- Replace OkHttp calls with official OpenAI client code (if you plan to use OpenAI) and include exact request/response parsing.
Tell me which of the above you want next and I will update the project files.
0 $type={blogger}:
Post a Comment