├── .github
└── workflows
│ └── manual.yml
├── .gitignore
├── CODEOWNERS
├── README.md
└── starter
├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── udacity
│ │ └── asteroidradar
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── udacity
│ │ │ └── asteroidradar
│ │ │ ├── Asteroid.kt
│ │ │ ├── BindingAdapters.kt
│ │ │ ├── Constants.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── PictureOfDay.kt
│ │ │ ├── api
│ │ │ └── NetworkUtils.kt
│ │ │ ├── detail
│ │ │ └── DetailFragment.kt
│ │ │ └── main
│ │ │ ├── MainFragment.kt
│ │ │ └── MainViewModel.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── asteroid_hazardous.png
│ │ ├── asteroid_safe.png
│ │ ├── ic_help_circle.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_status_normal.xml
│ │ ├── ic_status_potentially_hazardous.xml
│ │ └── placeholder_picture_of_day.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_detail.xml
│ │ └── fragment_main.xml
│ │ ├── menu
│ │ └── main_overflow_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── main_nav_graph.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── udacity
│ └── asteroidradar
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── screenshots
├── screen_1.png
├── screen_2.png
├── screen_3.png
└── screen_4.png
└── settings.gradle
/.github/workflows/manual.yml:
--------------------------------------------------------------------------------
1 | # Workflow to ensure whenever a Github PR is submitted,
2 | # a JIRA ticket gets created automatically.
3 | name: Manual Workflow
4 |
5 | # Controls when the action will run.
6 | on:
7 | # Triggers the workflow on pull request events but only for the master branch
8 | pull_request_target:
9 | types: [opened, reopened]
10 |
11 | # Allows you to run this workflow manually from the Actions tab
12 | workflow_dispatch:
13 |
14 | jobs:
15 | test-transition-issue:
16 | name: Convert Github Issue to Jira Issue
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Checkout
20 | uses: actions/checkout@master
21 |
22 | - name: Login
23 | uses: atlassian/gajira-login@master
24 | env:
25 | JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
26 | JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
27 | JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
28 |
29 | - name: Create NEW JIRA ticket
30 | id: create
31 | uses: atlassian/gajira-create@master
32 | with:
33 | project: CONUPDATE
34 | issuetype: Task
35 | summary: |
36 | Github PR nd940 - Android Kotlin Developer C2 | Repo: ${{ github.repository }} | PR# ${{github.event.number}}
37 | description: |
38 | Repo link: https://github.com/${{ github.repository }}
39 | PR no. ${{ github.event.pull_request.number }}
40 | PR title: ${{ github.event.pull_request.title }}
41 | PR description: ${{ github.event.pull_request.description }}
42 | In addition, please resolve other issues, if any.
43 | fields: '{"components": [{"name":"nd940 - Android Kotlin Developer"}], "customfield_16449":"https://classroom.udacity.com/", "customfield_16450":"Resolve the PR", "labels": ["github"], "priority":{"id": "4"}}'
44 |
45 | - name: Log created issue
46 | run: echo "Issue ${{ steps.create.outputs.issue }} was created"
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches/build_file_checksum.ser
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | .idea
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 |
14 |
15 | # gradle
16 | gradle/
17 | gradlew*
18 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @udacity/active-public-content
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Project Title
2 |
3 | Asteroid Radar
4 |
5 | ## Getting Started
6 |
7 | Asteroid Radar is an app to view the asteroids detected by NASA that pass near Earth, you can view all the detected asteroids in a period of time, their data (Size, velocity, distance to Earth) and if they are potentially hazardous.
8 |
9 | The app is consists of two screens: A Main screen with a list of all the detected asteroids and a Details screen that is going to display the data of that asteroid once it´s selected in the Main screen list. The main screen will also show the NASA image of the day to make the app more striking.
10 |
11 | This kind of app is one of the most usual in the real world, what you will learn by doing this are some of the most fundamental skills you need to know to work as a professional Android developer, as fetching data from the internet, saving data to a database, and display the data in a clear, clear, compelling UI.
12 |
13 | ## Requirements
14 |
15 | 1. Android Studio (Jellyfish or above)
16 | 2. JDK 21 with `JAVA_HOME` environment variable set. If you don't have JDK 21 installed or `JAVA_HOME` is not set, consider using a tool like `sdkman` to simplify the process. Refer to the sdkman documentation for installation instructions: [sdkman installation](https://sdkman.io/install)
17 |
18 | ### Screenshots
19 |
20 | 
21 | 
22 | 
23 | 
24 |
25 | ### Installation
26 |
27 | To get the project running on your local machine, you need to follow these steps:
28 |
29 | **Step 1: Clone the repo**
30 |
31 | Use this to clone it to your local machine:
32 | ```bash
33 | git clone https://github.com/udacity/REPOSITORY_NAME.git
34 | ```
35 |
36 | **Step 2: Check out the ‘master’ branch**
37 |
38 | This branch is going to let you start working with it. The command to check out a branch would be:
39 |
40 | ```bash
41 | git checkout master
42 | ```
43 |
44 | **Step 3: Run the project and check that it compiles correctly**
45 |
46 | Open the project in Android Studio and click the Run ‘app’ button, check that it runs correctly and you can see the app in your device or emulator.
47 |
48 | ## Testing
49 |
50 | Explain the steps needed to run any automated tests
51 |
52 | ### Break Down Tests
53 |
54 | Explain what each test does and why
55 |
56 | ```
57 | Examples here
58 | ```
59 | ## Project Instructions
60 |
61 | You will be provided with a starter code, which includes the necessary dependencies and plugins that you have been using along the courses and that you are going to need to complete this project.
62 |
63 | The most important dependencies we are using are:
64 | - Retrofit to download the data from the Internet.
65 | - Moshi to convert the JSON data we are downloading to usable data in form of custom classes.
66 | - Glide to download and cache images.
67 | - RecyclerView to display the asteroids in a list.
68 |
69 | We recommend you following the guidelines seen in the courses, as well as using the components from the Jetpack library:
70 | - ViewModel
71 | - Room
72 | - LiveData
73 | - Data Binding
74 | - Navigation
75 |
76 | Android Studio could display a message to update Gradle plugin, or another thing like Kotlin, although it is recommended to have the last versions, it could be you have to do other things in order to make it work.
77 |
78 | The application you will build must:
79 | - Include Main screen with a list of clickable asteroids as seen in the provided design.
80 | - Include a Details screen that displays the selected asteroid data once it’s clicked in the Main screen as seen in the provided design. The images in the details screen are going to be provided here, an image for a potentially hazardous asteroids and another one for the non potentially hazardous ones.
81 | - Download and parse data from the NASA NeoWS (Near Earth Object Web Service) API.
82 | - Save the selected asteroid data in the database using a button in details screen.
83 | - Once you save an asteroid in the database, you should be able to display the list of asteroids from web or the database in the main screen top menu.
84 | - Be able to cache the asteroids data by using a worker, so it downloads and saves week asteroids in background when device is charging and wifi is enabled.
85 | - App works in multiple screen sizes and orientations, also it provides talk back and push button navigation.
86 |
87 |
88 | ## Built With
89 |
90 | To build this project you are going to use the NASA NeoWS (Near Earth Object Web Service) API, which you can find here.
91 | https://api.nasa.gov/
92 |
93 | You will need an API Key which is provided for you in that same link, just fill the fields in the form and click Signup.
94 |
95 | ## License
96 |
97 |
98 |
--------------------------------------------------------------------------------
/starter/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/starter/README.md:
--------------------------------------------------------------------------------
1 | # Purpose of this Folder
2 |
3 | This folder should contain the scaffolded project files to get a student started on their project. This repo will be added to the Classroom for students to use, so please do not have any solutions in this folder.
4 |
5 | ## Note: Android Kotlin Gradle Update
6 | Use the updated Gradle version in the `~/gradle/wrapper/gradle-wrapper.properties` file:
7 | ```
8 | distributionUrl = https\://services.gradle.org/distributions/gradle-8.8-all.zip
9 | ```
10 |
--------------------------------------------------------------------------------
/starter/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/starter/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | id 'kotlin-kapt'
5 | id 'androidx.navigation.safeargs'
6 | id 'kotlin-parcelize'
7 | }
8 |
9 | android {
10 | namespace 'com.udacity.asteroidradar'
11 | compileSdk 34
12 |
13 | defaultConfig {
14 | applicationId "com.udacity.asteroidradar"
15 | minSdkVersion 24
16 | targetSdkVersion 34
17 | versionCode 1
18 | versionName "1.0"
19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20 | }
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | buildFeatures {
28 | dataBinding true
29 | }
30 | compileOptions {
31 | sourceCompatibility = JavaVersion.VERSION_21
32 | targetCompatibility = JavaVersion.VERSION_21
33 | }
34 | }
35 |
36 | dependencies {
37 | // Design
38 | implementation "androidx.appcompat:appcompat:$version_appcompat"
39 | implementation "androidx.constraintlayout:constraintlayout:$version_constraint_layout"
40 |
41 | // Core with Ktx
42 | implementation "androidx.core:core-ktx:$version_core"
43 |
44 | // ViewModel and LiveData
45 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$version_lifecycle"
46 |
47 | // Retrofit with Moshi Converter
48 | implementation "com.squareup.retrofit2:retrofit:$version_retrofit"
49 | implementation "com.squareup.retrofit2:converter-moshi:$version_retrofit"
50 | implementation "com.squareup.retrofit2:converter-scalars:$version_retrofit"
51 |
52 | // Moshi
53 | implementation "com.squareup.moshi:moshi:$version_moshi"
54 | implementation "com.squareup.moshi:moshi-kotlin:$version_moshi"
55 |
56 | // Navigation
57 | implementation "androidx.navigation:navigation-fragment-ktx:$version_navigation"
58 | implementation "androidx.navigation:navigation-ui-ktx:$version_navigation"
59 |
60 | // Room database
61 | implementation "androidx.room:room-runtime:$version_room"
62 | kapt "androidx.room:room-compiler:$version_room"
63 | // Kotlin Extensions and Coroutines support for Room
64 | implementation "androidx.room:room-ktx:$version_room"
65 |
66 | // Glide
67 | implementation "com.github.bumptech.glide:glide:$version_glide"
68 | annotationProcessor "com.github.bumptech.glide:compiler:$version_glide"
69 | implementation 'com.squareup.picasso:picasso:2.5.2'
70 |
71 | // WorkManager
72 | implementation "androidx.work:work-runtime-ktx:$version_work"
73 |
74 | // Tests
75 | testImplementation 'junit:junit:4.13.2'
76 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
77 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
78 | }
79 |
--------------------------------------------------------------------------------
/starter/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/starter/app/src/androidTest/java/com/udacity/asteroidradar/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.udacity.asteroidradar", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/starter/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/Asteroid.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import android.os.Parcelable
4 | import kotlinx.android.parcel.Parcelize
5 |
6 | @Parcelize
7 | data class Asteroid(val id: Long, val codename: String, val closeApproachDate: String,
8 | val absoluteMagnitude: Double, val estimatedDiameter: Double,
9 | val relativeVelocity: Double, val distanceFromEarth: Double,
10 | val isPotentiallyHazardous: Boolean) : Parcelable
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/BindingAdapters.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import android.widget.ImageView
4 | import android.widget.TextView
5 | import androidx.databinding.BindingAdapter
6 |
7 | @BindingAdapter("statusIcon")
8 | fun bindAsteroidStatusImage(imageView: ImageView, isHazardous: Boolean) {
9 | if (isHazardous) {
10 | imageView.setImageResource(R.drawable.ic_status_potentially_hazardous)
11 | } else {
12 | imageView.setImageResource(R.drawable.ic_status_normal)
13 | }
14 | }
15 |
16 | @BindingAdapter("asteroidStatusImage")
17 | fun bindDetailsStatusImage(imageView: ImageView, isHazardous: Boolean) {
18 | if (isHazardous) {
19 | imageView.setImageResource(R.drawable.asteroid_hazardous)
20 | } else {
21 | imageView.setImageResource(R.drawable.asteroid_safe)
22 | }
23 | }
24 |
25 | @BindingAdapter("astronomicalUnitText")
26 | fun bindTextViewToAstronomicalUnit(textView: TextView, number: Double) {
27 | val context = textView.context
28 | textView.text = String.format(context.getString(R.string.astronomical_unit_format), number)
29 | }
30 |
31 | @BindingAdapter("kmUnitText")
32 | fun bindTextViewToKmUnit(textView: TextView, number: Double) {
33 | val context = textView.context
34 | textView.text = String.format(context.getString(R.string.km_unit_format), number)
35 | }
36 |
37 | @BindingAdapter("velocityText")
38 | fun bindTextViewToDisplayVelocity(textView: TextView, number: Double) {
39 | val context = textView.context
40 | textView.text = String.format(context.getString(R.string.km_s_unit_format), number)
41 | }
42 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/Constants.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | object Constants {
4 | const val API_QUERY_DATE_FORMAT = "YYYY-MM-dd"
5 | const val DEFAULT_END_DATE_DAYS = 7
6 | const val BASE_URL = "https://api.nasa.gov/"
7 | }
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 |
6 | class MainActivity : AppCompatActivity() {
7 |
8 | override fun onCreate(savedInstanceState: Bundle?) {
9 | super.onCreate(savedInstanceState)
10 | setContentView(R.layout.activity_main)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/PictureOfDay.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import com.squareup.moshi.Json
4 |
5 | data class PictureOfDay(@Json(name = "media_type") val mediaType: String, val title: String,
6 | val url: String)
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/api/NetworkUtils.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar.api
2 |
3 | import com.udacity.asteroidradar.Asteroid
4 | import com.udacity.asteroidradar.Constants
5 | import org.json.JSONObject
6 | import java.text.SimpleDateFormat
7 | import java.util.*
8 | import kotlin.collections.ArrayList
9 |
10 | fun parseAsteroidsJsonResult(jsonResult: JSONObject): ArrayList {
11 | val nearEarthObjectsJson = jsonResult.getJSONObject("near_earth_objects")
12 |
13 | val asteroidList = ArrayList()
14 |
15 | val nextSevenDaysFormattedDates = getNextSevenDaysFormattedDates()
16 | for (formattedDate in nextSevenDaysFormattedDates) {
17 | if (nearEarthObjectsJson.has(formattedDate)) {
18 | val dateAsteroidJsonArray = nearEarthObjectsJson.getJSONArray(formattedDate)
19 |
20 | for (i in 0 until dateAsteroidJsonArray.length()) {
21 | val asteroidJson = dateAsteroidJsonArray.getJSONObject(i)
22 | val id = asteroidJson.getLong("id")
23 | val codename = asteroidJson.getString("name")
24 | val absoluteMagnitude = asteroidJson.getDouble("absolute_magnitude_h")
25 | val estimatedDiameter = asteroidJson.getJSONObject("estimated_diameter")
26 | .getJSONObject("kilometers").getDouble("estimated_diameter_max")
27 |
28 | val closeApproachData = asteroidJson
29 | .getJSONArray("close_approach_data").getJSONObject(0)
30 | val relativeVelocity = closeApproachData.getJSONObject("relative_velocity")
31 | .getDouble("kilometers_per_second")
32 | val distanceFromEarth = closeApproachData.getJSONObject("miss_distance")
33 | .getDouble("astronomical")
34 | val isPotentiallyHazardous = asteroidJson
35 | .getBoolean("is_potentially_hazardous_asteroid")
36 |
37 | val asteroid = Asteroid(id, codename, formattedDate, absoluteMagnitude,
38 | estimatedDiameter, relativeVelocity, distanceFromEarth, isPotentiallyHazardous)
39 | asteroidList.add(asteroid)
40 | }
41 | }
42 | }
43 |
44 | return asteroidList
45 | }
46 |
47 | private fun getNextSevenDaysFormattedDates(): ArrayList {
48 | val formattedDateList = ArrayList()
49 |
50 | val calendar = Calendar.getInstance()
51 | for (i in 0..Constants.DEFAULT_END_DATE_DAYS) {
52 | val currentTime = calendar.time
53 | val dateFormat = SimpleDateFormat(Constants.API_QUERY_DATE_FORMAT, Locale.getDefault())
54 | formattedDateList.add(dateFormat.format(currentTime))
55 | calendar.add(Calendar.DAY_OF_YEAR, 1)
56 | }
57 |
58 | return formattedDateList
59 | }
60 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/detail/DetailFragment.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar.detail
2 |
3 |
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import androidx.appcompat.app.AlertDialog
9 | import androidx.fragment.app.Fragment
10 | import com.udacity.asteroidradar.R
11 | import com.udacity.asteroidradar.databinding.FragmentDetailBinding
12 |
13 | class DetailFragment : Fragment() {
14 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
15 | savedInstanceState: Bundle?): View? {
16 | val binding = FragmentDetailBinding.inflate(inflater)
17 | binding.lifecycleOwner = this
18 |
19 | val asteroid = DetailFragmentArgs.fromBundle(arguments!!).selectedAsteroid
20 |
21 | binding.asteroid = asteroid
22 |
23 | binding.helpButton.setOnClickListener {
24 | displayAstronomicalUnitExplanationDialog()
25 | }
26 |
27 | return binding.root
28 | }
29 |
30 | private fun displayAstronomicalUnitExplanationDialog() {
31 | val builder = AlertDialog.Builder(activity!!)
32 | .setMessage(getString(R.string.astronomica_unit_explanation))
33 | .setPositiveButton(android.R.string.ok, null)
34 | builder.create().show()
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/main/MainFragment.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar.main
2 |
3 | import android.os.Bundle
4 | import android.view.*
5 | import androidx.fragment.app.Fragment
6 | import androidx.lifecycle.ViewModelProvider
7 | import com.udacity.asteroidradar.R
8 | import com.udacity.asteroidradar.databinding.FragmentMainBinding
9 |
10 | class MainFragment : Fragment() {
11 |
12 | private val viewModel: MainViewModel by lazy {
13 | ViewModelProvider(this).get(MainViewModel::class.java)
14 | }
15 |
16 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
17 | savedInstanceState: Bundle?): View? {
18 | val binding = FragmentMainBinding.inflate(inflater)
19 | binding.lifecycleOwner = this
20 |
21 | binding.viewModel = viewModel
22 |
23 | setHasOptionsMenu(true)
24 |
25 | return binding.root
26 | }
27 |
28 | override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
29 | inflater.inflate(R.menu.main_overflow_menu, menu)
30 | super.onCreateOptionsMenu(menu, inflater)
31 | }
32 |
33 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
34 | return true
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/starter/app/src/main/java/com/udacity/asteroidradar/main/MainViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar.main
2 |
3 | import androidx.lifecycle.ViewModel
4 |
5 | class MainViewModel : ViewModel() {
6 | }
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/asteroid_hazardous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/drawable/asteroid_hazardous.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/asteroid_safe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/drawable/asteroid_safe.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/ic_help_circle.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/ic_status_normal.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/ic_status_potentially_hazardous.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/drawable/placeholder_picture_of_day.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/layout/fragment_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
17 |
18 |
28 |
29 |
36 |
37 |
41 |
42 |
46 |
47 |
52 |
53 |
61 |
62 |
63 |
69 |
70 |
75 |
76 |
81 |
82 |
90 |
91 |
92 |
98 |
99 |
100 |
101 |
107 |
108 |
116 |
117 |
123 |
124 |
132 |
133 |
139 |
140 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
16 |
17 |
24 |
25 |
32 |
33 |
44 |
45 |
46 |
57 |
58 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/menu/main_overflow_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/starter/app/src/main/res/navigation/main_nav_graph.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
15 |
16 |
17 |
22 |
23 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #010613
4 | #010613
5 | #FF8282
6 | #010613
7 | #FFFFFF
8 | #D2D2D2
9 | #FF8282
10 |
11 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Asteroid Radar
3 |
4 | View week asteroids
5 | View today asteroids
6 | View saved asteroids
7 | Close approach date
8 | Absolute magnitude
9 | Estimated diameter
10 | Relative velocity
11 | Distance from earth
12 | %f au
13 | %f km
14 | %f km/s
15 | Image of the Day
16 | The astronomical unit (au) is a unit of length, roughly the distance from Earth to the Sun and equal to about 150 million kilometres (93 million miles)
17 | Astronomical unit definition
18 | Potentially hazardous asteroid image
19 | Not hazardous asteroid image
20 | This is NASA\'s picture of day, showing nothing yet
21 | NASA\'s picture of day: %s
22 |
23 |
--------------------------------------------------------------------------------
/starter/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/starter/app/src/test/java/com/udacity/asteroidradar/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.udacity.asteroidradar
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/starter/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | ext {
4 | version_core = "1.13.1"
5 | version_constraint_layout = "2.1.4"
6 | version_gradle = '8.4.2'
7 | version_kotlin = "1.9.24"
8 | version_lifecycle = "2.8.2"
9 | version_navigation = '2.7.7'
10 | version_glide = "4.16.0"
11 | version_moshi = "1.15.1"
12 | version_retrofit = "2.9.0"
13 | version_recyclerview = "1.3.2"
14 | version_work = "2.9.0"
15 | version_room = "2.6.1"
16 | version_appcompat = "1.7.0"
17 | }
18 |
19 | repositories {
20 | mavenCentral()
21 | google()
22 | }
23 | dependencies {
24 | classpath "com.android.tools.build:gradle:$version_gradle"
25 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_kotlin"
26 | classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$version_navigation"
27 |
28 | // NOTE: Do not place your application dependencies here; they belong
29 | // in the individual module build.gradle files
30 | }
31 | }
--------------------------------------------------------------------------------
/starter/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
--------------------------------------------------------------------------------
/starter/screenshots/screen_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/screenshots/screen_1.png
--------------------------------------------------------------------------------
/starter/screenshots/screen_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/screenshots/screen_2.png
--------------------------------------------------------------------------------
/starter/screenshots/screen_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/screenshots/screen_3.png
--------------------------------------------------------------------------------
/starter/screenshots/screen_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udacity/nd940-android-kotlin-c2-starter/6034fb6335c241b13d967bbe0cdc057d5d9bdcc6/starter/screenshots/screen_4.png
--------------------------------------------------------------------------------
/starter/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name='Asteroid Radar'
16 | include ':app'
17 |
--------------------------------------------------------------------------------