Android Native Dev

by minimax-ai60aaae52bb2aMIT13K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 5 months ago

Android native application development and UI design guide. Covers Material Design 3, Kotlin/Compose development, project configuration, accessibility, and build troubleshooting. Read this before Android native application development.

Instructions onlySoftware Development
AI-generated overview

Guides Android native app development with Kotlin, Jetpack Compose, Material Design 3, and build troubleshooting.

What it does
Provides a reference guide for building Android native applications, covering project setup and Gradle configuration, Kotlin coding standards, Jetpack Compose patterns, resources and icons, and build error diagnosis. It also includes guidance on accessibility, adaptive screens, motion, performance, privacy, and testing. It produces instructions and code conventions rather than executable artifacts.
When to use it
Use it before starting Android native application development or when configuring an Android project. It is also useful for troubleshooting Gradle build errors and aligning Kotlin or Compose code with recommended standards.
Requirements
No scripts are included; it is instructions only. Following it assumes an Android development environment with Gradle and the Android SDK, and network access for dependency resolution.

1. Project Scenario Assessment

Before starting development, assess the current project state:

ScenarioCharacteristicsApproach
Empty DirectoryNo files presentFull initialization required, including Gradle Wrapper
Has Gradle Wrappergradlew and gradle/wrapper/ existUse ./gradlew directly for builds
Android Studio ProjectComplete project structure, may lack wrapperCheck wrapper, run gradle wrapper if needed
Incomplete ProjectPartial files presentCheck missing files, complete configuration

Key Principles:

  • Before writing business logic, ensure ./gradlew assembleDebug succeeds
  • If gradle.properties is missing, create it first and configure AndroidX

1.1 Required Files Checklist

MyApp/├── gradle.properties          # Configure AndroidX and other settings├── settings.gradle.kts├── build.gradle.kts           # Root level├── gradle/wrapper/│   └── gradle-wrapper.properties├── app/│   ├── build.gradle.kts       # Module level│   └── src/main/│       ├── AndroidManifest.xml│       ├── java/com/example/myapp/│       │   └── MainActivity.kt│       └── res/│           ├── values/│           │   ├── strings.xml│           │   ├── colors.xml│           │   └── themes.xml│           └── mipmap-*/       # App icons

2. Project Configuration

2.1 gradle.properties

properties
# Required configurationandroid.useAndroidX=trueandroid.enableJetifier=true
# Build optimizationorg.gradle.parallel=truekotlin.code.style=official
# JVM memory settings (adjust based on project size)# Small projects: 2048m, Medium: 4096m, Large: 8192m+# org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8

Note: If you encounter OutOfMemoryError during build, increase -Xmx value. Large projects with many dependencies may require 8GB or more.

2.2 Dependency Declaration Standards

kotlin
dependencies {    // Use BOM to manage Compose versions    implementation(platform("androidx.compose:compose-bom:2024.02.00"))    implementation("androidx.compose.ui:ui")    implementation("androidx.compose.material3:material3")        // Activity & ViewModel    implementation("androidx.activity:activity-compose:1.8.2")    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")}

2.3 Build Variants & Product Flavors

Product Flavors allow you to create different versions of your app (e.g., free/paid, dev/staging/prod).

Configuration in app/build.gradle.kts:

kotlin
android {    // Define flavor dimensions    flavorDimensions += "environment"        productFlavors {        create("dev") {            dimension = "environment"            applicationIdSuffix = ".dev"            versionNameSuffix = "-dev"                        // Different config values per flavor            buildConfigField("String", "API_BASE_URL", "\"https://dev-api.example.com\"")            buildConfigField("Boolean", "ENABLE_LOGGING", "true")                        // Different resources            resValue("string", "app_name", "MyApp Dev")        }                create("staging") {            dimension = "environment"            applicationIdSuffix = ".staging"            versionNameSuffix = "-staging"                        buildConfigField("String", "API_BASE_URL", "\"https://staging-api.example.com\"")            buildConfigField("Boolean", "ENABLE_LOGGING", "true")            resValue("string", "app_name", "MyApp Staging")        }                create("prod") {            dimension = "environment"            // No suffix for production                        buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")            buildConfigField("Boolean", "ENABLE_LOGGING", "false")            resValue("string", "app_name", "MyApp")        }    }        buildTypes {        debug {            isDebuggable = true            isMinifyEnabled = false        }        release {            isDebuggable = false            isMinifyEnabled = true            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")        }    }}

Build Variant Naming: {flavor}{BuildType} → e.g., devDebug, prodRelease

Gradle Build Commands:

bash
# List all available build variants./gradlew tasks --group="build"
# Build specific variant (flavor + buildType)./gradlew assembleDevDebug        # Dev flavor, Debug build./gradlew assembleStagingDebug    # Staging flavor, Debug build./gradlew assembleProdRelease     # Prod flavor, Release build
# Build all variants of a specific flavor./gradlew assembleDev             # All Dev variants (debug + release)./gradlew assembleProd            # All Prod variants
# Build all variants of a specific build type./gradlew assembleDebug           # All flavors, Debug build./gradlew assembleRelease         # All flavors, Release build
# Install specific variant to device./gradlew installDevDebug./gradlew installProdRelease
# Build and install in one command./gradlew installDevDebug && adb shell am start -n com.example.myapp.dev/.MainActivity

Access BuildConfig in Code:

Note: Starting from AGP 8.0, BuildConfig is no longer generated by default. You must explicitly enable it in your build.gradle.kts:

kotlin
android {    buildFeatures {        buildConfig = true    }}
kotlin
// Use build config values in your codeval apiUrl = BuildConfig.API_BASE_URLval isLoggingEnabled = BuildConfig.ENABLE_LOGGING
if (BuildConfig.DEBUG) {    // Debug-only code}

Flavor-Specific Source Sets:

app/src/├── main/           # Shared code for all flavors├── dev/            # Dev-only code and resources│   ├── java/│   └── res/├── staging/        # Staging-only code and resources├── prod/           # Prod-only code and resources├── debug/          # Debug build type code└── release/        # Release build type code

Multiple Flavor Dimensions (e.g., environment + tier):

kotlin
android {    flavorDimensions += listOf("environment", "tier")        productFlavors {        create("dev") { dimension = "environment" }        create("prod") { dimension = "environment" }                create("free") { dimension = "tier" }        create("paid") { dimension = "tier" }    }}// Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc.

3. Kotlin Development Standards

3.1 Naming Conventions

TypeConventionExample
Class/InterfacePascalCaseUserRepository, MainActivity
Function/VariablecamelCasegetUserName(), isLoading
ConstantSCREAMING_SNAKEMAX_RETRY_COUNT
Packagelowercasecom.example.myapp
ComposablePascalCase@Composable fun UserCard()

3.2 Code Standards (Important)

Null Safety:

kotlin
// ❌ Avoid: Non-null assertion !! (may crash)val name = user!!.name
// ✅ Recommended: Safe call + default valueval name = user?.name ?: "Unknown"
// ✅ Recommended: let handlinguser?.let { processUser(it) }

Exception Handling:

kotlin
// ❌ Avoid: Random try-catch in business layer swallowing exceptionsfun loadData() {    try {        val data = api.fetch()    } catch (e: Exception) {        // Swallowing exception, hard to debug    }}
// ✅ Recommended: Let exceptions propagate, handle at appropriate layersuspend fun loadData(): Result<Data> {    return try {        Result.success(api.fetch())    } catch (e: Exception) {        Result.failure(e)  // Wrap and return, let caller decide handling    }}
// ✅ Recommended: Unified handling in ViewModelviewModelScope.launch {    runCatching { repository.loadData() }        .onSuccess { _uiState.value = UiState.Success(it) }        .onFailure { _uiState.value = UiState.Error(it.message) }}

3.3 Threading & Coroutines (Critical)

Thread Selection Principles:

Operation TypeThreadDescription
UI UpdatesDispatchers.MainUpdate View, State, LiveData
Network RequestsDispatchers.IOHTTP calls, API requests
File I/ODispatchers.IOLocal storage, database operations
Compute IntensiveDispatchers.DefaultJSON parsing, sorting, encryption

Correct Usage:

kotlin
// In ViewModelviewModelScope.launch {    // Default Main thread, can update UI State    _uiState.value = UiState.Loading        // Switch to IO thread for network request    val result = withContext(Dispatchers.IO) {        repository.fetchData()    }        // Automatically returns to Main thread, update UI    _uiState.value = UiState.Success(result)}
// In Repository (suspend functions should be main-safe)suspend fun fetchData(): Data = withContext(Dispatchers.IO) {    api.getData()}

Common Mistakes:

kotlin
// ❌ Wrong: Updating UI on IO threadviewModelScope.launch(Dispatchers.IO) {    val data = api.fetch()    _uiState.value = data  // Crash or warning!}
// ❌ Wrong: Executing time-consuming operation on Main threadviewModelScope.launch {    val data = api.fetch()  // Blocking main thread! ANR}
// ✅ Correct: Fetch on IO, update on MainviewModelScope.launch {    val data = withContext(Dispatchers.IO) { api.fetch() }    _uiState.value = data}

3.4 Visibility Rules

kotlin
// Default is public, declare explicitly when neededclass UserRepository {           // public    private val cache = mutableMapOf<String, User>()  // Visible only within class    internal fun clearCache() {} // Visible only within module}
// data class properties are public by default, be careful when used across modulesdata class User(    val id: String,       // public    val name: String)

3.5 Common Syntax Pitfalls

kotlin
// ❌ Wrong: Accessing uninitialized lateinitclass MyViewModel : ViewModel() {    lateinit var data: String    fun process() = data.length  // May crash}
// ✅ Correct: Use nullable or default valueclass MyViewModel : ViewModel() {    var data: String? = null    fun process() = data?.length ?: 0}
// ❌ Wrong: Using return in lambdalist.forEach { item ->    if (item.isEmpty()) return  // Returns from outer function!}
// ✅ Correct: Use return@forEachlist.forEach { item ->    if (item.isEmpty()) return@forEach}

3.6 Server Response Data Class Fields Must Be Nullable

kotlin
// ❌ Wrong: Fields declared as non-null (server may not return them)data class UserResponse(    val id: String = "",    val name: String = "",    val avatar: String = "")
// ✅ Correct: All fields declared as nullabledata class UserResponse(    @SerializedName("id")    val id: String? = null,    @SerializedName("name")    val name: String? = null,    @SerializedName("avatar")    val avatar: String? = null)

3.7 Lifecycle Resource Management

kotlin
// ❌ Wrong: Only adding Observer, not removingclass MyView : View {    override fun onAttachedToWindow() {        super.onAttachedToWindow()        activity?.lifecycle?.addObserver(this)    }    // Memory leak!}
// ✅ Correct: Paired add and removeclass MyView : View {    override fun onAttachedToWindow() {        super.onAttachedToWindow()        activity?.lifecycle?.addObserver(this)    }
    override fun onDetachedFromWindow() {        activity?.lifecycle?.removeObserver(this)        super.onDetachedFromWindow()    }}

3.8 Logging Level Usage

kotlin
import android.util.Log
// Info: Key checkpoints in normal flowLog.i(TAG, "loadData: started, userId = $userId")
// Warning: Abnormal but recoverable situationsLog.w(TAG, "loadData: cache miss, fallback to network")
// Error: Failure/error situationsLog.e(TAG, "loadData failed: ${error.message}")
LevelUse Case
i (Info)Normal flow, method entry, key parameters
w (Warning)Recoverable exceptions, fallback handling, null returns
e (Error)Request failures, caught exceptions, unrecoverable errors

4. Jetpack Compose Standards

4.1 @Composable Context Rules

kotlin
// ❌ Wrong: Calling Composable from non-Composable functionfun showError(message: String) {    Text(message)  // Compile error!}
// ✅ Correct: Mark as @Composable@Composablefun ErrorMessage(message: String) {    Text(message)}
// ❌ Wrong: Using suspend outside LaunchedEffect@Composablefun MyScreen() {    val data = fetchData()  // Error!}
// ✅ Correct: Use LaunchedEffect@Composablefun MyScreen() {    var data by remember { mutableStateOf<Data?>(null) }    LaunchedEffect(Unit) {        data = fetchData()    }}

4.2 State Management

kotlin
// Basic Statevar count by remember { mutableStateOf(0) }
// Derived State (avoid redundant computation)val isEven by remember { derivedStateOf { count % 2 == 0 } }
// Persist across recomposition (e.g., scroll position)val scrollState = rememberScrollState()
// State in ViewModelclass MyViewModel : ViewModel() {    private val _uiState = MutableStateFlow(UiState())    val uiState: StateFlow<UiState> = _uiState.asStateFlow()}

4.3 Common Compose Mistakes

kotlin
// ❌ Wrong: Creating objects in Composable (created on every recomposition)@Composablefun MyScreen() {    val viewModel = MyViewModel()  // Wrong!}
// ✅ Correct: Use viewModel() or remember@Composablefun MyScreen(viewModel: MyViewModel = viewModel()) {    // ...}

5. Resources & Icons

5.1 App Icon Requirements

Must provide multi-resolution icons:

DirectorySizePurpose
mipmap-mdpi48x48Baseline
mipmap-hdpi72x721.5x
mipmap-xhdpi96x962x
mipmap-xxhdpi144x1443x
mipmap-xxxhdpi192x1924x

Recommended: Use Adaptive Icon (Android 8+):

xml
<!-- res/mipmap-anydpi-v26/ic_launcher.xml --><adaptive-icon>    <background android:drawable="@color/ic_launcher_background"/>    <foreground android:drawable="@mipmap/ic_launcher_foreground"/></adaptive-icon>

5.2 Resource Naming Conventions

TypePrefixExample
Layoutlayout_layout_main.xml
Imageic_, img_, bg_ic_user.png
Colorcolor_color_primary
String-app_name, btn_submit

5.3 Avoid Android Reserved Names (Important)

Variable names, resource IDs, colors, icons, and XML elements must not use Android reserved words or system resource names. Using reserved names causes build errors or resource conflicts.

Common Reserved Names to Avoid:

CategoryReserved Names (Do NOT Use)
Colorsbackground, foreground, transparent, white, black
Icons/Drawablesicon, logo, image, drawable
Viewsview, text, button, layout, container
Attributesid, name, type, style, theme, color
Systemapp, android, content, data, action

Examples:

xml
<!-- ❌ Wrong: Using reserved names --><color name="background">#FFFFFF</color><color name="icon">#000000</color>
<!-- ✅ Correct: Add prefix or specific naming --><color name="app_background">#FFFFFF</color><color name="icon_primary">#000000</color>
kotlin
// ❌ Wrong: Variable names conflict with systemval icon = R.drawable.my_iconval background = Color.White
// ✅ Correct: Use descriptive namesval appIcon = R.drawable.my_iconval screenBackground = Color.White
xml
<!-- ❌ Wrong: Drawable name conflicts --><ImageView android:src="@drawable/icon" />
<!-- ✅ Correct: Add prefix --><ImageView android:src="@drawable/ic_home" />

6. Build Error Diagnosis & Fixes

6.1 Common Error Quick Reference

Error KeywordCauseFix
Unresolved referenceMissing import or undefinedCheck imports, verify dependencies
Type mismatchType incompatibilityCheck parameter types, add conversion
Cannot accessVisibility issueCheck public/private/internal
@Composable invocationsComposable context errorEnsure caller is also @Composable
Duplicate classDependency conflictUse ./gradlew dependencies to investigate
AAPT: errorResource file errorCheck XML syntax and resource references

6.2 Fix Best Practices

  1. Read the complete error message first: Locate file and line number
  2. Check recent changes: Problems usually in latest modifications
  3. Clean Build: ./gradlew clean assembleDebug
  4. Check dependency versions: Version conflicts are common causes
  5. Refresh dependencies if needed: Clear cache and rebuild

6.3 Debugging Commands

bash
# Clean and build./gradlew clean assembleDebug
# View dependency tree (investigate conflicts)./gradlew :app:dependencies
# View detailed errors./gradlew assembleDebug --stacktrace
# Refresh dependencies./gradlew --refresh-dependencies

7. Material Design 3 Guidelines

Review Android UI files for compliance with Material Design 3 Guidelines and Android best practices.

Design Philosophy

M3 Core Principles
PrincipleDescription
PersonalDynamic color based on user preferences and wallpaper
AdaptiveResponsive across all screen sizes and form factors
ExpressiveBold colors and typography with personality
AccessibleInclusive design for all users
M3 Expressive (Latest)

The latest evolution adds emotion-driven UX through:

  • Vibrant, dynamic colors
  • Intuitive motion physics
  • Adaptive components
  • Flexible typography
  • Contrasting shapes (35 new shape options)

App Style Selection

Critical Decision: Match visual style to app category and target audience.

App CategoryVisual StyleKey Characteristics
Utility/ToolMinimalistClean, efficient, neutral colors
Finance/BankingProfessional TrustConservative colors, security-focused
Health/WellnessCalm & NaturalSoft colors, organic shapes
Kids (3-5)Playful SimpleBright colors, large targets (56dp+)
Kids (6-12)Fun & EngagingVibrant, gamified feedback
Social/EntertainmentExpressiveBrand-driven, gesture-rich
ProductivityClean & FocusedMinimal, high contrast
E-commerceConversion-focusedClear CTAs, scannable

See Design Style Guide [blocked] for detailed style profiles.

Quick Reference: Key Specifications

Color Contrast Requirements
ElementMinimum Ratio
Body text4.5:1
Large text (18sp+)3:1
UI components3:1
Touch Targets
TypeSize
Minimum48 × 48dp
Recommended (primary actions)56 × 56dp
Kids apps56dp+
Spacing between targets8dp minimum
8dp Grid System
TokenValueUsage
xs4dpIcon padding
sm8dpTight spacing
md16dpDefault padding
lg24dpSection spacing
xl32dpLarge gaps
xxl48dpScreen margins
Typography Scale (Summary)
CategorySizes
Display57sp, 45sp, 36sp
Headline32sp, 28sp, 24sp
Title22sp, 16sp, 14sp
Body16sp, 14sp, 12sp
Label14sp, 12sp, 11sp
Animation Duration
TypeDuration
Micro (ripples)50-100ms
Short (simple)100-200ms
Medium (expand/collapse)200-300ms
Long (complex)300-500ms
Component Dimensions
ComponentHeightMin Width
Button40dp64dp
FAB56dp56dp
Text Field56dp280dp
App Bar64dp-
Bottom Nav80dp-

Anti-Patterns (Must Avoid)

UI Anti-Patterns
  • More than 5 bottom navigation items
  • Multiple FABs on same screen
  • Touch targets smaller than 48dp
  • Inconsistent spacing (non-8dp multiples)
  • Missing dark theme support
  • Text on colored backgrounds without contrast check
Performance Anti-Patterns
  • Startup time > 2 seconds without progress indicator
  • Frame rate < 60 FPS (> 16ms per frame)
  • Crash rate > 1.09% (Google Play threshold)
  • ANR rate > 0.47% (Google Play threshold)
Accessibility Anti-Patterns
  • Missing contentDescription on interactive elements
  • Element type in labels (e.g., "Save button" instead of "Save")
  • Complex gestures in kids apps
  • Text-only buttons for non-readers

Review Checklist

  • 8dp spacing grid compliance
  • 48dp minimum touch targets
  • Proper typography scale usage
  • Color contrast compliance (4.5:1+ for text)
  • Dark theme support
  • contentDescription on all interactive elements
  • Startup < 2 seconds or shows progress
  • Visual style matches app category

Design References

TopicReference
Colors, Typography, Spacing, ShapesVisual Design [blocked]
Animation & TransitionsMotion System [blocked]
Accessibility GuidelinesAccessibility [blocked]
Large Screens & FoldablesAdaptive Screens [blocked]
Android Vitals & PerformancePerformance & Stability [blocked]
Privacy & SecurityPrivacy & Security [blocked]
Audio, Video, NotificationsFunctional Requirements [blocked]
App Style by CategoryDesign Style Guide [blocked]

8. Testing

Note: Only add test dependencies when the user explicitly asks for testing.

A well-tested Android app uses layered testing: fast local unit tests for logic, instrumentation tests for UI and integration, and Gradle Managed Devices to run emulators reproducibly on any machine — including CI.

8.1 Test Dependencies

Before adding test dependencies, inspect the project's existing versions to avoid conflicts:

  1. Check gradle/libs.versions.toml — if present, add test deps using the project's version catalog style
  2. Check existing build.gradle.kts for already-pinned dependency versions
  3. Match version families using the table below

Version Alignment Rules:

Test DependencyMust Align WithHow to Check
kotlinx-coroutines-testProject's kotlinx-coroutines-core versionSearch for kotlinx-coroutines in build files or version catalog
compose-ui-test-junit4Project's Compose BOM or compose-compilerSearch for compose-bom or compose.compiler in build files
espresso-*All Espresso artifacts must use the same versionSearch for espresso in build files
androidx.test:runner, rules, ext:junitShould use compatible AndroidX Test versionsSearch for androidx.test in build files
mockkMust support the project's Kotlin versionCheck kotlin version in root build.gradle.kts or version catalog

Dependencies Reference — add only the groups you need:

kotlin
dependencies {    // --- Local unit tests (src/test/) ---    testImplementation("junit:junit:<version>")                          // 4.13.2+    testImplementation("org.robolectric:robolectric:<version>")          // 4.16.1+    testImplementation("io.mockk:mockk:<version>")                      // match Kotlin version    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:<version>")  // match coroutines-core    testImplementation("androidx.arch.core:core-testing:<version>")      // InstantTaskExecutorRule for LiveData    testImplementation("app.cash.turbine:turbine:<version>")             // Flow/StateFlow testing
    // --- Instrumentation tests (src/androidTest/) ---    androidTestImplementation("androidx.test.ext:junit:<version>")    androidTestImplementation("androidx.test:runner:<version>")    androidTestImplementation("androidx.test:rules:<version>")    androidTestImplementation("androidx.test.espresso:espresso-core:<version>")    androidTestImplementation("androidx.test.espresso:espresso-contrib:<version>")   // RecyclerView, Drawer    androidTestImplementation("androidx.test.espresso:espresso-intents:<version>")   // Intent verification    androidTestImplementation("androidx.test.espresso:espresso-idling-resource:<version>")    androidTestImplementation("androidx.test.uiautomator:uiautomator:<version>")
    // --- Compose UI tests (only if project uses Compose) ---    androidTestImplementation("androidx.compose.ui:ui-test-junit4")      // version from Compose BOM    debugImplementation("androidx.compose.ui:ui-test-manifest")          // required for createComposeRule}

Note: If the project uses a Compose BOM, ui-test-junit4 and ui-test-manifest don't need explicit versions — the BOM manages them.

Enable Robolectric resource support in the android block:

kotlin
android {    testOptions {        unitTests.isIncludeAndroidResources = true  // required for Robolectric    }}

8.2 Testing by Layer

LayerLocationRuns OnSpeedUse For
Unit (JUnit)src/test/JVM~msViewModels, repos, mappers, validators
Unit + Robolectricsrc/test/JVM + simulated Android~100msCode needing Context, resources, SharedPrefs
Compose UI (local)src/test/JVM + Robolectric~100msComposable rendering & interaction
Espressosrc/androidTest/Device/Emulator~secondsView-based UI flows, Intents, DB integration
Compose UI (device)src/androidTest/Device/Emulator~secondsFull Compose UI flows with real rendering
UI Automatorsrc/androidTest/Device/Emulator~secondsSystem dialogs, notifications, multi-app
Managed Devicesrc/androidTest/Gradle-managed AVD~minutes (first run)CI, matrix testing across API levels

See Testing [blocked] for detailed examples, code patterns, and Gradle Managed Device configuration.

8.3 Testing Commands

bash
# Local unit tests (fast, no emulator)./gradlew test                          # all modules./gradlew :app:testDebugUnitTest        # app module, debug variant
# Single test class./gradlew :app:testDebugUnitTest --tests "com.example.myapp.CounterViewModelTest"
# Instrumentation tests (requires device or managed device)./gradlew connectedDebugAndroidTest     # on connected device./gradlew pixel6Api34DebugAndroidTest   # on managed device
# Both together./gradlew test connectedDebugAndroidTest
# Test with coverage report (JaCoCo)./gradlew testDebugUnitTest jacocoTestReport

Source and attribution

Source:minimax-ai/skillsinskills/android-native-devat commit60aaae5

License: MIT

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal