├── demo
├── .gitignore
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── ru
│ │ │ └── spbstu
│ │ │ └── icc
│ │ │ └── kspt
│ │ │ └── andrei
│ │ │ └── mydemoapplication
│ │ │ ├── ExampleInstrumentedTest.java
│ │ │ └── UiAutomatorTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── ru
│ │ │ │ └── spbstu
│ │ │ │ └── icc
│ │ │ │ └── kspt
│ │ │ │ └── andrei
│ │ │ │ └── mydemoapplication
│ │ │ │ ├── Activity1.java
│ │ │ │ ├── Activity2.java
│ │ │ │ ├── Activity3.java
│ │ │ │ ├── ArticleListActivity.java
│ │ │ │ ├── ArticleListFragment.java
│ │ │ │ ├── DetailsActivity.java
│ │ │ │ ├── DetailsFragment.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── MyBroadcastReceiver.java
│ │ │ │ └── MyNewActivity.java
│ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ ├── gradient.xml
│ │ │ ├── ic_assistant_black_24dp.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── ic_launcher_square.png
│ │ │ └── shape.xml
│ │ │ ├── layout-land
│ │ │ ├── list_activity.xml
│ │ │ └── test.xml
│ │ │ ├── layout
│ │ │ ├── activity_1.xml
│ │ │ ├── activity_2.xml
│ │ │ ├── activity_3.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── content_main.xml
│ │ │ ├── details_activity.xml
│ │ │ ├── details_view.xml
│ │ │ ├── layouts_test.xml
│ │ │ ├── list_activity.xml
│ │ │ └── test.xml
│ │ │ ├── menu
│ │ │ └── menu_main.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
│ │ │ ├── values-ru
│ │ │ └── strings.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── ru
│ │ └── spbstu
│ │ └── icc
│ │ └── kspt
│ │ └── andrei
│ │ └── mydemoapplication
│ │ ├── ArticleListFragmentTest.java
│ │ ├── ArticleRobolectricListFragmentTest.java
│ │ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── labs
├── 01
│ ├── .gitignore
│ ├── .idea
│ │ ├── kotlinc.xml
│ │ ├── libraries
│ │ │ └── KotlinJavaRuntime.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── 01.iml
│ ├── TASK.md
│ ├── comment01.png
│ ├── constraint
│ │ ├── lab01_constraint_v01.png
│ │ ├── lab01_constraint_v02.png
│ │ ├── lab01_constraint_v03.png
│ │ ├── lab01_constraint_v04.png
│ │ ├── lab01_constraint_v05.png
│ │ ├── lab01_constraint_v06.png
│ │ ├── lab01_constraint_v07.png
│ │ ├── lab01_constraint_v08.png
│ │ ├── lab01_constraint_v09.png
│ │ ├── lab01_constraint_v10.png
│ │ ├── lab01_constraint_v11.png
│ │ ├── lab01_constraint_v12.png
│ │ ├── lab01_constraint_v13.png
│ │ ├── lab01_constraint_v14.png
│ │ ├── lab01_constraint_v15.png
│ │ ├── lab01_constraint_v16.png
│ │ ├── lab01_constraint_v17.png
│ │ ├── lab01_constraint_v18.png
│ │ ├── lab01_constraint_v19.png
│ │ ├── lab01_constraint_v20.png
│ │ ├── lab01_constraint_v21.png
│ │ ├── lab01_constraint_v22.png
│ │ ├── lab01_constraint_v23.png
│ │ ├── lab01_constraint_v24.png
│ │ ├── lab01_constraint_v25.png
│ │ ├── lab01_constraint_v26.png
│ │ ├── lab01_constraint_v27.png
│ │ ├── lab01_constraint_v28.png
│ │ ├── lab01_constraint_v29.png
│ │ ├── lab01_constraint_v30.png
│ │ └── meta.txt
│ ├── generator
│ │ └── Lab01Task02.kt
│ ├── linear
│ │ ├── 01.png
│ │ ├── 02.png
│ │ ├── 03.png
│ │ ├── 04.png
│ │ ├── 05.png
│ │ ├── 06.png
│ │ ├── 07.png
│ │ ├── 08.png
│ │ ├── 09.png
│ │ ├── 10.png
│ │ ├── 11.png
│ │ ├── 12.png
│ │ ├── 13.png
│ │ ├── 14.png
│ │ ├── 15.png
│ │ ├── 16.png
│ │ ├── 17.png
│ │ ├── 18.png
│ │ ├── 19.png
│ │ ├── 20.png
│ │ ├── 21.png
│ │ └── 22.png
│ └── variants.txt
├── 02
│ ├── TASK.md
│ ├── VARIANTS02.md
│ ├── VARIANTS03.txt
│ ├── continuewatch
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── app
│ │ │ ├── .gitignore
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.pro
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java
│ │ │ │ └── ru
│ │ │ │ │ └── spbstu
│ │ │ │ │ └── icc
│ │ │ │ │ └── kspt
│ │ │ │ │ └── lab2
│ │ │ │ │ └── continuewatch
│ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── res
│ │ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ │ │ ├── layout-land
│ │ │ │ └── activity_main.xml
│ │ │ │ ├── layout
│ │ │ │ └── activity_main.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
│ │ │ │ └── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ ├── build.gradle
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ └── settings.gradle
│ └── stat
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ └── sum.png
├── 03
│ ├── ANSWER02.md
│ ├── TASK.md
│ ├── activities.dia
│ ├── activities.svg
│ └── stat
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ └── sum.png
├── 04
│ ├── TASK.md
│ └── res
│ │ └── reference
│ │ ├── .gitignore
│ │ ├── app
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── androidTest
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── myapplication
│ │ │ │ ├── AboutUtils.kt
│ │ │ │ └── NavigationTest.kt
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── myapplication
│ │ │ │ ├── AboutActivity.kt
│ │ │ │ ├── BaseFragment.kt
│ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ ├── ic_dashboard_black_24dp.xml
│ │ │ ├── ic_home_black_24dp.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── ic_notifications_black_24dp.xml
│ │ │ ├── layout
│ │ │ ├── activity_about.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── fragment1.xml
│ │ │ ├── fragment2.xml
│ │ │ └── fragment3.xml
│ │ │ ├── menu
│ │ │ └── bottom_nav_menu.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ │ ├── navigation
│ │ │ └── mobile_navigation.xml
│ │ │ ├── values-night
│ │ │ └── themes.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── themes.xml
│ │ ├── build.gradle
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ └── settings.gradle
├── 06
│ └── TASK.md
├── 07
│ └── TASK.md
└── RecyclerView
│ ├── TASK.md
│ ├── biblib
│ ├── .gitignore
│ ├── README.md
│ ├── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── name
│ │ │ └── ank
│ │ │ └── lab4
│ │ │ ├── BibConfig.java
│ │ │ ├── BibDatabase.java
│ │ │ ├── BibEntry.java
│ │ │ ├── Keys.java
│ │ │ └── Types.java
│ │ └── test
│ │ ├── java
│ │ └── name
│ │ │ └── ank
│ │ │ └── lab4
│ │ │ └── BibDatabaseTest.java
│ │ └── resources
│ │ ├── mixed.bib
│ │ └── references.bib
│ └── samples
│ ├── articles.bib
│ └── mixed.bib
├── lectures
├── .gitignore
├── Lecture01_Introduction.md
├── Lecture02_Resources.md
├── Lecture03_AltRes_Activity.md
├── Lecture04_interacting.md
├── Lecture05_navigation.md
├── Lecture06-08_fragments.md
├── Lecture09_Testing.md
├── Lecture10_Implicit_Intents.md
├── Lecture11_threads_coroutines.md
├── Lecture13_services.md
├── Lecture14_schedulers_receivers.md
├── Lecture15_providers.md
├── LectureX_room.md
├── LectureY_ART.md
├── README.md
├── TASK.md
└── res
│ ├── 01-android-com.png
│ ├── 01-arch.png
│ ├── 01-build-new.png
│ ├── 01-build-pkg.png
│ ├── 01-build.png
│ ├── 01-perm-sample.png
│ ├── 01-project.png
│ ├── 01-qr-lectures.png
│ ├── 01-uses-feature-sample.png
│ ├── 02-adapter-layouts.png
│ ├── 02-buttons.png
│ ├── 02-checkbox.png
│ ├── 02-common-layouts.png
│ ├── 02-cross.png
│ ├── 02-edittext.png
│ ├── 02-imeoptions.png
│ ├── 02-layerlist.png
│ ├── 02-levellist.png
│ ├── 02-pat-a-cat.png
│ ├── 02-radiobutton.png
│ ├── 02-res-types.png
│ ├── 02-spinner.png
│ ├── 02-statelist.png
│ ├── 03-activity-backstack.png
│ ├── 03-activity-fw.png
│ ├── 03-dpi-bitmap-sizes.png
│ ├── 03-generalized-sizes.png
│ ├── 03-layout-dp.png
│ ├── 03-layout-px.png
│ ├── 03-win-ar.jpg
│ ├── Motorola-milestone-wikipedia.png
│ ├── Nexus_5_(1).jpg
│ ├── activity-lifecycle.png
│ ├── activity-states.png
│ ├── activity_fragment_lifecycle.png
│ ├── am_instrument.png
│ ├── android-profiler-no-safepoint.png
│ ├── android-startup.png
│ ├── android_test_orchestrator_flow.png
│ ├── anr.png
│ ├── ape_fwk_all.png
│ ├── app-architecture-gdd.png
│ ├── art-overview.png
│ ├── bottom-navigation.png
│ ├── c1-vs-tired.png
│ ├── camera2.png
│ ├── cms-major-gc.png
│ ├── content-provider-overview.png
│ ├── control-schematics.svg
│ ├── dalvik-gc-for-alloc.png
│ ├── dalvik-oom-on-halffull-heap.png
│ ├── dalvik-oom.png
│ ├── definework-flex-period.png
│ ├── densities-phone_2x.png
│ ├── diagram_backstack.png
│ ├── diagram_backstack_singletask_multiactivity.png
│ ├── diagram_multiple_instances.png
│ ├── diagram_multitasking.png
│ ├── doc_intent-filter-element.png
│ ├── espresso-cheatsheet.png
│ ├── espresso_sync.png
│ ├── fragment_lifecycle.png
│ ├── fragment_lifecycle_1.png
│ ├── fragment_lifecycle_2.png
│ ├── fragments.png
│ ├── g1-heap-structure.png
│ ├── g1-mixed-gc.png
│ ├── gen-full-gc.png
│ ├── gen-heap.png
│ ├── gen-minor-gc.png
│ ├── happens-before.png
│ ├── install-time-perms.png
│ ├── intents-common.png
│ ├── keeps-stopping.png
│ ├── kotlin-elizarov.png
│ ├── lab_qr.png
│ ├── layout-adaptive-breakpoints_2x.png
│ ├── layoutparams.png
│ ├── lifecycle-states.svg
│ ├── lifecycleowner-implementations.png
│ ├── navigation-graph_2x-callouts.png
│ ├── navigation-idioms.png
│ ├── notification.png
│ ├── nursery-schematic-unlabeled.svg
│ ├── observer-diagram.png
│ ├── observer-pattern.gif
│ ├── observer-sequence.png
│ ├── oreo-gc-regions.png
│ ├── overview-criteria.png
│ ├── postfix-arithmetics.jpg
│ ├── profiling-jug-async.png
│ ├── profiling-jug-jvisualvm.png
│ ├── profiling-jug-prog.png
│ ├── profiling-jug-safepoints.png
│ ├── pyramid.png
│ ├── recents.png
│ ├── res-selection-flowchart.png
│ ├── room_architecture.png
│ ├── run-time-perms.png
│ ├── save-restore-instance-state.png
│ ├── sequential-and-go-to-schematic.svg
│ ├── service-lc-bound.png
│ ├── service-lc-started.png
│ ├── service_binding_tree_lifecycle.png
│ ├── service_lifecycle.png
│ ├── share_via.png
│ ├── start-activity-for-result.svg
│ ├── storage_dataflow.png
│ ├── storage_datamodel.png
│ ├── storage_picker.svg
│ ├── studio-profiler.png
│ ├── synchronizes-with.png
│ ├── t-mobile-g1.jpg
│ ├── task-category-tree.png
│ ├── test_manifest.png
│ ├── testing-workflow.png
│ ├── top-app-bar.png
│ ├── user-data-overview-permissions-flow01.jpg
│ ├── viewgroup_2x.png
│ ├── viewmodel-lifecycle.png
│ ├── weak-gen-hypothesis.png
│ └── x2eq25.png
├── multithreading-demo.bundle
└── navigation-demo-2019.bundle
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # IntelliJ
37 | *.iml
38 | .idea
39 |
40 | # Keystore files
41 | # Uncomment the following lines if you do not want to check your keystore files in.
42 | #*.jks
43 | #*.keystore
44 | .DS_Store
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
56 |
57 | # fastlane
58 | fastlane/report.xml
59 | fastlane/Preview.html
60 | fastlane/screenshots
61 | fastlane/test_output
62 | fastlane/readme.md
--------------------------------------------------------------------------------
/demo/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/demo/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 27
5 | defaultConfig {
6 | applicationId "ru.spbstu.icc.kspt.andrei.mydemoapplication"
7 | minSdkVersion 18
8 | targetSdkVersion 27
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | targetCompatibility 1.8
21 | sourceCompatibility 1.8
22 | }
23 | testOptions {
24 | unitTests {
25 | unitTests.includeAndroidResources = true
26 | }
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(dir: 'libs', include: ['*.jar'])
32 | implementation 'com.android.support:appcompat-v7:27.1.1'
33 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
34 | implementation 'com.android.support:design:27.1.1'
35 | testImplementation 'junit:junit:4.12'
36 |
37 | testImplementation 'org.mockito:mockito-core:1.10.19'
38 | testImplementation 'androidx.test:core:1.0.0'
39 | testImplementation 'org.robolectric:robolectric:4.0.2'
40 |
41 | androidTestImplementation 'androidx.test:rules:1.1.0'
42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
43 | androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
44 | }
45 |
--------------------------------------------------------------------------------
/demo/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 |
--------------------------------------------------------------------------------
/demo/app/src/androidTest/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.os.RemoteException;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Rule;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import androidx.test.espresso.Espresso;
11 | import androidx.test.espresso.action.ViewActions;
12 | import androidx.test.espresso.assertion.ViewAssertions;
13 | import androidx.test.espresso.matcher.ViewMatchers;
14 | import androidx.test.platform.app.InstrumentationRegistry;
15 | import androidx.test.rule.ActivityTestRule;
16 | import androidx.test.runner.AndroidJUnit4;
17 | import androidx.test.uiautomator.UiDevice;
18 |
19 | import static org.hamcrest.Matchers.is;
20 |
21 | /**
22 | * Instrumented test, which will execute on an Android device.
23 | *
24 | * @see Testing documentation
25 | */
26 | @RunWith(AndroidJUnit4.class)
27 | public class ExampleInstrumentedTest {
28 |
29 | @Rule
30 | public ActivityTestRule mActivityRule
31 | = new ActivityTestRule<>(ArticleListActivity.class);
32 |
33 | @Test
34 | public void itemSelectedPort() throws RemoteException {
35 | UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationNatural();
36 | Espresso.onData(is("Item1"))
37 | .perform(ViewActions.click());
38 |
39 | Espresso.onView(ViewMatchers.withId(R.id.details_text))
40 | .check(ViewAssertions.matches(ViewMatchers.withText("Item1")));
41 | }
42 |
43 | @Test
44 | public void itemSelectedLand() throws RemoteException {
45 | UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationLeft();
46 | Espresso.onData(is("Item1"))
47 | .perform(ViewActions.click());
48 |
49 | Espresso.onView(ViewMatchers.withId(R.id.details_text))
50 | .check(ViewAssertions.matches(ViewMatchers.withText("Item1")));
51 | }
52 |
53 | @Test
54 | public void rotationTest() throws RemoteException {
55 | UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationNatural();
56 |
57 | Espresso.onData(is("Item1"))
58 | .perform(ViewActions.click());
59 |
60 | UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationLeft();
61 |
62 | Espresso.onView(ViewMatchers.withId(R.id.details_text))
63 | .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
64 |
65 | Espresso.onView(ViewMatchers.withId(android.R.id.list))
66 | .check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
67 |
68 | Espresso.pressBackUnconditionally();
69 |
70 | Assert.assertTrue(mActivityRule.getActivity().isFinishing());
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/demo/app/src/androidTest/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/UiAutomatorTest.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.graphics.Point;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 |
9 | import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
10 | import androidx.test.platform.app.InstrumentationRegistry;
11 | import androidx.test.uiautomator.UiDevice;
12 | import androidx.test.uiautomator.UiObject;
13 | import androidx.test.uiautomator.UiSelector;
14 |
15 | @RunWith(AndroidJUnit4ClassRunner.class)
16 | public class UiAutomatorTest {
17 | @Test
18 | public void testIcons() throws Exception {
19 | UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
20 | device.pressHome();
21 |
22 | device.waitForIdle();
23 | Point sz = device.getDisplaySizeDp();
24 | device.swipe(sz.x / 2, sz.y / 2 + sz.y / 4, sz.x / 2, sz.y / 2 - sz.y / 4, 5);
25 |
26 | device.waitForIdle();
27 | UiObject obj = device.findObject(new UiSelector().description("ListActivity"));
28 | // UiObject obj = device.findObject(new UiSelector().description("Calculator"));
29 | // UiScrollable launcherItem = new UiScrollable(new UiSelector().className("android.support.v7.widget.RecyclerView"));
30 | // launcherItem.scrollForward();
31 | // launcherItem.scrollDescriptionIntoView("YouTube");
32 | // UiObject obj = device.findObject(new UiSelector().description("YouTube"));
33 | obj.clickAndWaitForNewWindow();
34 |
35 | Assert.assertTrue(
36 | device.findObject(new UiSelector().packageName("ru.spbstu.icc.kspt.andrei.mydemoapplication")).exists()
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/demo/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/Activity1.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.view.View;
8 |
9 | public class Activity1 extends Activity {
10 | @Override
11 | protected void onCreate(@Nullable Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_1);
14 | findViewById(R.id.create_2).setOnClickListener(this::onCreate2Clicked);
15 | findViewById(R.id.create_3).setOnClickListener(this::onCreate3Clicked);
16 | }
17 |
18 | private void onCreate2Clicked(View view) {
19 | Intent i = new Intent(this, Activity2.class);
20 | startActivity(i);
21 | }
22 |
23 | private void onCreate3Clicked(View view) {
24 | Intent i = new Intent(this, Activity3.class);
25 | startActivity(i);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/Activity2.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.view.View;
8 |
9 | public class Activity2 extends Activity {
10 | private static final int RQ_BN1 = 1;
11 |
12 | @Override
13 | protected void onCreate(@Nullable Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setContentView(R.layout.activity_2);
16 | findViewById(R.id.create_3).setOnClickListener(this::onCreate3Clicked);
17 | findViewById(R.id.back_1).setOnClickListener(this::onBack1Clicked);
18 | }
19 |
20 | private void onBack1Clicked(View view) {
21 | finish();
22 | }
23 |
24 | private void onCreate3Clicked(View view) {
25 | Intent i = new Intent(this, Activity3.class);
26 | startActivityForResult(i, RQ_BN1);
27 | }
28 |
29 | @Override
30 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
31 | super.onActivityResult(requestCode, resultCode, data);
32 | if (requestCode == RQ_BN1){
33 | if (resultCode == Activity3.RESULT_TO_1){
34 | finish();
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/Activity3.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.view.View;
7 |
8 | public class Activity3 extends Activity {
9 | public static final int RESULT_TO_1 = RESULT_FIRST_USER + 0;
10 | private static final int RESULT_TO_2 = RESULT_FIRST_USER + 1;
11 | private static final int RESULT_TO_3 = RESULT_FIRST_USER + 2;
12 |
13 | @Override
14 | protected void onCreate(@Nullable Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_3);
17 | findViewById(R.id.back_1).setOnClickListener(this::onBack1Clicked);
18 | findViewById(R.id.back_2).setOnClickListener(this::onBack2Clicked);
19 | }
20 |
21 | private void onBack2Clicked(View view) {
22 | finish();
23 | }
24 |
25 | private void onBack1Clicked(View view) {
26 | setResult(RESULT_TO_1);
27 | finish();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ArticleListActivity.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.app.FragmentManager;
6 | import android.app.FragmentTransaction;
7 | import android.content.Intent;
8 | import android.content.IntentFilter;
9 | import android.content.pm.PackageManager;
10 | import android.content.res.Configuration;
11 | import android.os.Bundle;
12 | import android.provider.Telephony;
13 | import android.support.annotation.NonNull;
14 | import android.support.annotation.Nullable;
15 |
16 | public class ArticleListActivity extends Activity implements ArticleListFragment.ArticleListener {
17 | public static final String DETAILS_TX = "initial";
18 | public static final String LIST_FRAGMENT = "listFragment";
19 | public static final String DETAILS_FRAGMENT = "detailsFragment";
20 | public static final String NONE = "None";
21 | public static final int REQUEST_CODE = 1;
22 | private boolean twoPanes = false;
23 |
24 | @Override
25 | protected void onCreate(@Nullable Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.list_activity);
28 |
29 | twoPanes =
30 | (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
31 |
32 | FragmentManager mgr = getFragmentManager();
33 | mgr.popBackStack(DETAILS_TX, FragmentManager.POP_BACK_STACK_INCLUSIVE);
34 |
35 | FragmentTransaction tx = mgr.beginTransaction();
36 |
37 | if (mgr.findFragmentByTag(LIST_FRAGMENT) == null) {
38 | tx.add(R.id.fragment_holder, new ArticleListFragment(), LIST_FRAGMENT);
39 | }
40 |
41 | if (twoPanes) {
42 | tx.replace(R.id.fragment_holder_right, DetailsFragment.newInstance(NONE), DETAILS_FRAGMENT);
43 | }
44 |
45 | tx.commit();
46 |
47 | registerBroadcast();
48 | }
49 |
50 | private void registerBroadcast() {
51 | if (checkSelfPermission(Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED) {
52 | IntentFilter filter = new IntentFilter();
53 | filter.addAction(Intent.ACTION_POWER_CONNECTED);
54 | filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
55 | filter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
56 | registerReceiver(new MyBroadcastReceiver(), filter);
57 | } else {
58 | requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS}, REQUEST_CODE);
59 | }
60 | }
61 |
62 | @Override
63 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
64 | if (requestCode == REQUEST_CODE) {
65 | for (int grantResult : grantResults) {
66 | if (grantResult == PackageManager.PERMISSION_GRANTED) {
67 | registerBroadcast();
68 | }
69 | }
70 | }
71 | }
72 |
73 | @Override
74 | public void onArticle(String text) {
75 | FragmentManager mgr = getFragmentManager();
76 |
77 | if (twoPanes) {
78 | DetailsFragment detailsFragment = (DetailsFragment) mgr.findFragmentById(R.id.fragment_holder_right);
79 | detailsFragment.setText(text);
80 | } else {
81 | FragmentTransaction tx = mgr.beginTransaction();
82 | tx.replace(R.id.fragment_holder, DetailsFragment.newInstance(text), DETAILS_FRAGMENT);
83 | tx.addToBackStack(DETAILS_TX);
84 | tx.commit();
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ArticleListFragment.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Fragment;
4 | import android.app.ListFragment;
5 | import android.content.Context;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.view.View;
9 | import android.widget.ArrayAdapter;
10 | import android.widget.ListAdapter;
11 | import android.widget.ListView;
12 |
13 | public class ArticleListFragment extends ListFragment {
14 | interface ArticleListener {
15 | void onArticle(String text);
16 | }
17 |
18 | private String[] items = {"Item1", "Item2", "Item3"};
19 |
20 | private ArticleListener listener;
21 |
22 | @Override
23 | public void onAttach(Context context) {
24 | super.onAttach(context);
25 | try {
26 | listener = (ArticleListener) context;
27 | } catch (ClassCastException e) {
28 | throw new IllegalStateException("Activity must implement ArticleListener", e);
29 | }
30 | }
31 |
32 | ArticleListener getListener() {
33 | return listener;
34 | }
35 |
36 | void setListener(ArticleListener listener) {
37 | this.listener = listener;
38 | }
39 |
40 | @Override
41 | public void onListItemClick(ListView l, View v, int position, long id) {
42 | if (listener != null) {
43 | String text = items[position];
44 | listener.onArticle(text);
45 | }
46 | }
47 |
48 | @Override
49 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
50 | super.onActivityCreated(savedInstanceState);
51 | ListAdapter adapter = new ArrayAdapter<>(
52 | getActivity(),
53 | android.R.layout.simple_list_item_1,
54 | items
55 | );
56 |
57 | setListAdapter(adapter);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/DetailsActivity.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Activity;
4 | import android.app.FragmentManager;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 |
8 | public class DetailsActivity extends Activity {
9 | public static final String DETAILS_KEY = "ru.spbstu.icc.kspt.andrei.mydemoapplication.articletext";
10 |
11 | @Override
12 | protected void onCreate(@Nullable Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | setContentView(R.layout.details_activity);
15 |
16 | FragmentManager mgr = getFragmentManager();
17 | DetailsFragment detailsFragment =
18 | (DetailsFragment) mgr.findFragmentById(R.id.details_fragment);
19 | String text = getIntent().getStringExtra(DETAILS_KEY);
20 | detailsFragment.setText(text);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/DetailsFragment.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Fragment;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | public class DetailsFragment extends Fragment {
12 |
13 | public static final String KEY_DETAILS_TEXT = "ru.spbstu.icc.kspt.andrei.mydemoapplication.detailsText";
14 |
15 | public DetailsFragment() {
16 |
17 | }
18 |
19 | @Nullable
20 | @Override
21 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
22 | return inflater.inflate(R.layout.details_view, container, false);
23 | }
24 |
25 | @Override
26 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
27 | super.onActivityCreated(savedInstanceState);
28 | Bundle args = getArguments();
29 | setText(args.getString(KEY_DETAILS_TEXT));
30 | }
31 |
32 | public void setText(String text) {
33 | TextView detailsText = getActivity().findViewById(R.id.details_text);
34 | if (detailsText != null) {
35 | detailsText.setText(text);
36 | }
37 | }
38 |
39 | public static DetailsFragment newInstance(String text) {
40 | DetailsFragment res = new DetailsFragment();
41 | Bundle args = new Bundle();
42 | args.putString(KEY_DETAILS_TEXT, text);
43 | res.setArguments(args);
44 | return res;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/MainActivity.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.design.widget.Snackbar;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 | import android.widget.Button;
14 | import android.widget.Toast;
15 |
16 | public class MainActivity extends AppCompatActivity {
17 |
18 | public static final String TAG = "App";
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_main);
24 |
25 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
26 | setSupportActionBar(toolbar);
27 |
28 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
29 | fab.setOnClickListener(new View.OnClickListener() {
30 | @Override
31 | public void onClick(View view) {
32 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
33 | .setAction("Action", null).show();
34 | }
35 | });
36 | }
37 |
38 | @Override
39 | public boolean onCreateOptionsMenu(Menu menu) {
40 | // Inflate the menu; this adds items to the action bar if it is present.
41 | getMenuInflater().inflate(R.menu.menu_main, menu);
42 | return true;
43 | }
44 |
45 | @Override
46 | public boolean onOptionsItemSelected(MenuItem item) {
47 | // Handle action bar item clicks here. The action bar will
48 | // automatically handle clicks on the Home/Up button, so long
49 | // as you specify a parent activity in AndroidManifest.xml.
50 | int id = item.getItemId();
51 |
52 | //noinspection SimplifiableIfStatement
53 | if (id == R.id.action_settings) {
54 | return true;
55 | }
56 |
57 | return super.onOptionsItemSelected(item);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/MyBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.util.Log;
7 |
8 | public class MyBroadcastReceiver extends BroadcastReceiver {
9 |
10 | public static final String TAG = "BROADCAST";
11 |
12 | @Override
13 | public void onReceive(Context context, Intent intent) {
14 | Log.i(TAG, "Received intent: " + intent);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/demo/app/src/main/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/MyNewActivity.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.Button;
11 |
12 | public class MyNewActivity extends Activity {
13 |
14 | public static final String LIFECYCLE = "lifecycle";
15 | public static final String KEY_COUNTER = "counter";
16 |
17 | private int counter = 0;
18 |
19 | @Override
20 | protected void onSaveInstanceState(Bundle outState) {
21 | super.onSaveInstanceState(outState);
22 | outState.putInt(KEY_COUNTER, counter);
23 | }
24 |
25 | @Override
26 | protected void onCreate(@Nullable Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | this.setContentView(R.layout.test);
29 |
30 | if (savedInstanceState != null) {
31 | counter = savedInstanceState.getInt(KEY_COUNTER);
32 | }
33 |
34 | Button bn = findViewById(R.id.button);
35 | if (bn != null) {
36 | bn.setOnClickListener(this::myBnClicked);
37 | refreshBnText(bn);
38 | }
39 | }
40 |
41 | @Override
42 | protected void onStart() {
43 | super.onStart();
44 | Log.i(LIFECYCLE, "onStart");
45 | }
46 |
47 | @Override
48 | protected void onResume() {
49 | super.onResume();
50 | Log.i(LIFECYCLE, "onResume");
51 | }
52 |
53 | @Override
54 | protected void onPause() {
55 | super.onPause();
56 | Log.i(LIFECYCLE, "onPause");
57 | }
58 |
59 | @Override
60 | protected void onStop() {
61 | super.onStop();
62 | Log.i(LIFECYCLE, "onStop");
63 | }
64 |
65 | @Override
66 | protected void onDestroy() {
67 | super.onDestroy();
68 | Log.i(LIFECYCLE, "onDestroy");
69 | }
70 |
71 | public void myBnClicked(View view) {
72 | Button bn = (Button) view;
73 | counter++;
74 | refreshBnText(bn);
75 |
76 | Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:123"));
77 | startActivity(intent);
78 | }
79 |
80 | private void refreshBnText(Button bn) {
81 | String title = getResources().getString(R.string.title_click_count, counter);
82 | bn.setText(title);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/drawable/gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/drawable/ic_assistant_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/drawable/ic_launcher_square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/drawable/ic_launcher_square.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/drawable/shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout-land/list_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout-land/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/activity_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/activity_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/activity_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/details_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/details_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
22 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/layouts_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
27 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/list_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/layout/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
26 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | My demo application
3 | Settings
4 | Привет, мир!
5 | Количество раз нажато: %d
6 |
7 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 |
4 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | My demo application
3 | Settings
4 | Hello world!
5 | Start
6 | Clicked count: %d
7 | Create A2
8 | Create A3
9 | Back to 1
10 | Back to 2
11 |
12 |
--------------------------------------------------------------------------------
/demo/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/app/src/test/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ArticleListFragmentTest.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.content.Context;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.mockito.Mockito;
8 |
9 | public class ArticleListFragmentTest {
10 |
11 | public static abstract class ExContext extends Context implements ArticleListFragment.ArticleListener {
12 |
13 | }
14 |
15 |
16 | @Test
17 | public void onListItemClickInvokesListener() {
18 | // Given
19 | ArticleListFragment fragment = new ArticleListFragment();
20 | ArticleListFragment.ArticleListener listener = Mockito.mock(ArticleListFragment.ArticleListener.class);
21 | fragment.setListener(listener);
22 |
23 | // Action
24 | fragment.onListItemClick(null, null, 0, 0);
25 |
26 | // Assertion
27 | Mockito.verify(listener).onArticle("Item1");
28 | }
29 |
30 | @Test
31 | public void listenerSetInOnAttach() {
32 | // Given
33 | ArticleListFragment fragment = new ArticleListFragment();
34 | ExContext listener = Mockito.mock(ExContext.class);
35 |
36 | // Action
37 | fragment.onAttach(listener);
38 |
39 | // Assertion
40 | Assert.assertEquals(listener, fragment.getListener());
41 | }
42 |
43 | @Test
44 | public void testWait() throws InterruptedException {
45 | Object o = new Object();
46 | // synchronized (o) {
47 | // o.wait(1000);
48 | // }
49 | Thread.sleep(1000);
50 | }
51 | }
--------------------------------------------------------------------------------
/demo/app/src/test/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ArticleRobolectricListFragmentTest.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import android.app.FragmentManager;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 | import org.robolectric.Robolectric;
8 | import org.robolectric.RobolectricTestRunner;
9 |
10 | @RunWith(RobolectricTestRunner.class)
11 | public class ArticleRobolectricListFragmentTest {
12 |
13 | @Test
14 | public void listenerSetInOnAttach() {
15 | ArticleListActivity activity = Robolectric.buildActivity(ArticleListActivity.class)
16 | .create()
17 | // .start()
18 | // .resume()
19 | .get();
20 | FragmentManager fm = activity.getFragmentManager();
21 | // ArticleListFragment listFragment = (ArticleListFragment) fm.findFragmentById(R.id.list_fragment);
22 | // Assert.assertEquals(activity, listFragment.getListener());
23 | // Assert.assertTrue(activity == listFragment.getListener());
24 | // assertThat(listFragment.getListener(), sameInstance(activity));
25 | // ArticleListActivity spy = Mockito.spy(activity);
26 | // listFragment.onListItemClick(null, null, 0, 0);
27 | // Mockito.verify(spy).onArticle("Item1");
28 | }
29 | }
--------------------------------------------------------------------------------
/demo/app/src/test/java/ru/spbstu/icc/kspt/andrei/mydemoapplication/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.andrei.mydemoapplication;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/demo/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 |
--------------------------------------------------------------------------------
/demo/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/demo/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/demo/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Nov 22 03:46:45 MSK 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/demo/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/demo/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/labs/01/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /.idea/shelf/
3 | /.idea/workspace.xml
4 | /out
--------------------------------------------------------------------------------
/labs/01/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/labs/01/.idea/libraries/KotlinJavaRuntime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/labs/01/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/labs/01/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/labs/01/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/labs/01/01.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/labs/01/TASK.md:
--------------------------------------------------------------------------------
1 | # Лабораторная работа №1. Layouts
2 | ## Цели
3 | * Познакомиться со средой разработки Android Studio
4 | * Изучить основные принципы верстки layout с использованием XML
5 | * Изучить основные возможности и свойства `LinearLayout`
6 | * Изучить основные возможности и свойства `ConstraintLayout`
7 |
8 | ## Задачи
9 | ### Задача 1. LinearLayout
10 | #### Задание
11 | Создайте layout ресурсы для следующих макетов экрана с использованием [LinearLayout](https://developer.android.com/guide/topics/ui/layout/linear).
12 |
13 | Изображение 1 согласно [варианту](linear).
14 |
15 | Изображение 2 согласно [варианту](linear).
16 |
17 | [Варианты](variants.txt):
18 | ```log
19 | 1:{1,10}
20 | 2:{2,11}
21 | 3:{3,12}
22 | ...
23 | 13:{13,22}
24 | 14:{14,1}
25 | 15:{15,2}
26 | ...
27 | 22:{22,9}
28 | 23:{1,10}
29 | ...
30 | ```
31 |
32 | #### Указания
33 | * Изучите `LinearLayout` по документации: https://developer.android.com/guide/topics/ui/layout/linear. Особое внимание обратите на атрибуты: `layout_weight`, `gravity`, `layout_gravity`, `orientation`, `layout_height`, `layout_width`.
34 | * Изучите получившийся XML код. Опишите все XML теги и атрибуты, использованные в вёрстке. Объясните, почему выбраны именно такие значения для атрибутов у разных виджетов.
35 | * Многие задачи можно решить разными способами. Предложите два решения хотя бы для одной из задач.
36 |
37 | #### Пояснения
38 | * Цифрами (1, 2, 3) обозначены произвольные widget’ы (`button`, `imageView`, `textView`, и т.д.). Используйте разные виджеты для разных цифр в рамках одного задания.
39 | * Если в рисунке указана только высота или ширина (`w` или `h`), то второй размер можно выбрать произвольно (например, `wrap_content`). Например, на рисунке
40 | 
41 | ширина (`w`) не указана, и может быть использована `wrap_content`. Небольшие отступы внутрь от обрамляющего квадрата добавлены только для улучшения визуального восприятия картинки и могут быть проигнорированы при xml вёрстке.
42 |
43 | ### Задача 2. ConstraintLayout
44 | #### Задание
45 | Решите задачу 1 (обе подзадачи) с использованием [ConstraintLayout](https://developer.android.com/training/constraint-layout)
46 |
47 | #### Указания:
48 | * Изучите `ConstraintLayout` по документации: https://developer.android.com/training/constraint-layout. Особое внимание обратите на атрибуты: `layout_constraintDimensionRatio`, `layout_constraintHorizontal_weight`, `layout_constraintVertical_weight`.
49 | * Изучите получившийся XML код. Опишите все XML атрибуты, использованные в вёрстке, не использовавшиеся для решения предыдущего задания. Объясните, почему выбраны именно такие значения для атрибутов у разных виджетов.
50 |
51 |
52 | ### Задача 3. ConstraintLayout
53 | Создайте layout ресурс для следующего макета экрана с использованием ConstraintLayout.
54 |
55 | Изображение 3 согласно [варианту](constraint).
56 |
57 | #### Пояснения
58 | * Цифрами (1, 2, 3) обозначены произвольные widget’ы (`button`, `imageView`, `textView`, и т.д.). Используйте разные виджеты для разных цифр в рамках одного задания.
59 | * `ConstraintLayout` имеет форму квадрата, занимает максимальную площадь и располагается в центре экрана.
60 | * Все фигуры имеют размеры `A*B/5`, где `A` — некоторое число, легко угадываемое из иллюстрации к заданию, `B` — размер стороны квадрата `ConstraintLayoout`.
61 |
62 | # Общие рекомендации
63 |
64 | * Разные задачи рекомендуется решать в разных layout файлах. Всего должно получиться 6 (или более) xml файлов.
65 | * Для выполнения заданий не обязательно запускать приложение на реальном устройстве или эмуляторе (достаточно результатов preview в Android Studio).
66 | 
67 |
68 | ## Отчет
69 | Отчет должен содержать формулировку целей, решения задач с ответами на дополнительные вопросы из раздела «указания» и выводы. Работа должна содержать 6 листингов (по одному для каждой задачи)
70 | Выводы должны содержать обоснование, почему автор отчета считает, что все цели были достигнуты, а также ответы на следующие вопросы:
71 | * В каких случаях целесообразно использовать `LinearLayout`, в каких `ConstraintLayout`?
72 |
73 | ## Дополнительные файлы
74 |
75 | 1. Помимо отчёта необходимо прислать сами xml файлы одним архивом. Файлы внутри архива должны называться
76 | `layout_{task:1,2,3}_{img:1,2..}_[alt].xml`
77 | Например:
78 | * `layout_1_14.xml` — задача №1, решение для layout из рисунка `14.png`
79 | * `layout_1_14_alt.xml` — альтернативное решение задачи №1 для рисунка `14.png`
80 | * `layout_3_28.xml` — решение задачи №3 для layout из рисунка `28.png`
81 | 2. Отчёт или сопроводительное письмо должны содержать ссылку на полный проект (например, ссылку на репозиторий в github), который можно загрузить в Android Studio.
82 |
83 |
84 | ## Вспомогательные материалы:
85 | * https://classroom.udacity.com/courses/ud9012 (Lesson 1 “Build Your First App”, Lesson 2 “Layouts”)
86 | * startandroid [Урок 180](https://startandroid.ru/ru/uroki/vse-uroki-spiskom/489-urok-180-constraintlayout-osnovy.html), [Урок 181](https://startandroid.ru/ru/uroki/vse-uroki-spiskom/490-urok-181-constraintslayout-advanced.html), [Урок 182](https://startandroid.ru/ru/uroki/vse-uroki-spiskom/491-urok-182-constraintlayout-chain-weight-barrier-group.html)
87 |
--------------------------------------------------------------------------------
/labs/01/comment01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/comment01.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v01.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v02.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v03.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v04.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v05.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v06.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v07.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v08.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v09.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v10.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v11.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v12.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v13.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v14.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v15.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v16.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v17.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v18.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v19.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v20.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v21.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v22.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v23.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v24.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v25.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v26.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v27.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v28.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v29.png
--------------------------------------------------------------------------------
/labs/01/constraint/lab01_constraint_v30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/constraint/lab01_constraint_v30.png
--------------------------------------------------------------------------------
/labs/01/constraint/meta.txt:
--------------------------------------------------------------------------------
1 | id:1
2 | 1;0;1;1;1
3 | 2;0;1;4;4
4 | 3;2;3;0;0
5 | 4;0;1;3;3
6 | 5;3;3;1;2
7 | 6;3;3;3;4
8 | id:2
9 | 1;1;2;0;0
10 | 2;1;2;3;3
11 | 3;1;2;4;4
12 | 4;3;3;2;3
13 | 5;0;0;1;2
14 | 6;4;4;1;2
15 | id:3
16 | 1;0;1;4;4
17 | 2;3;4;4;4
18 | 3;3;4;3;3
19 | 4;2;2;0;1
20 | 5;3;3;0;1
21 | 6;2;2;2;3
22 | id:4
23 | 1;0;1;3;3
24 | 2;3;4;3;3
25 | 3;2;3;1;1
26 | 4;1;2;2;2
27 | 5;3;4;0;0
28 | 6;0;0;0;1
29 | 7;4;4;1;2
30 | id:5
31 | 1;1;2;4;4
32 | 2;0;1;0;0
33 | 3;1;2;1;1
34 | 4;1;2;2;2
35 | 5;4;4;2;3
36 | 6;4;4;0;1
37 | id:6
38 | 1;0;1;0;0
39 | 2;2;3;2;2
40 | 3;3;4;3;3
41 | 4;0;1;2;2
42 | 5;2;2;0;1
43 | 6;3;3;0;1
44 | 7;2;2;3;4
45 | id:7
46 | 1;0;1;4;4
47 | 2;2;3;2;2
48 | 3;3;4;4;4
49 | 4;1;2;0;0
50 | 5;1;1;1;2
51 | 6;4;4;2;3
52 | id:8
53 | 1;0;1;2;2
54 | 2;2;3;3;3
55 | 3;2;3;2;2
56 | 4;0;1;4;4
57 | 5;4;4;2;3
58 | 6;3;3;0;1
59 | id:9
60 | 1;2;3;4;4
61 | 2;1;2;0;0
62 | 3;0;1;2;2
63 | 4;1;2;3;3
64 | 5;0;1;1;1
65 | 6;2;2;1;2
66 | 7;3;3;0;1
67 | id:10
68 | 1;0;1;0;0
69 | 2;1;2;3;3
70 | 3;0;1;2;2
71 | 4;2;3;1;1
72 | 5;3;3;3;4
73 | 6;0;0;3;4
74 | 7;4;4;2;3
75 | id:11
76 | 1;3;4;0;0
77 | 2;0;1;4;4
78 | 3;0;1;3;3
79 | 4;2;3;4;4
80 | 5;3;3;2;3
81 | 6;2;2;0;1
82 | id:12
83 | 1;3;4;2;2
84 | 2;1;2;4;4
85 | 3;3;4;1;1
86 | 4;3;4;4;4
87 | 5;0;0;1;2
88 | 6;2;2;2;3
89 | id:13
90 | 1;3;4;4;4
91 | 2;0;1;1;1
92 | 3;0;1;2;2
93 | 4;3;4;3;3
94 | 5;1;2;3;3
95 | 6;4;4;1;2
96 | 7;3;3;1;2
97 | id:14
98 | 1;2;3;2;2
99 | 2;3;4;4;4
100 | 3;1;2;1;1
101 | 4;2;3;0;0
102 | 5;0;1;4;4
103 | 6;4;4;0;1
104 | 7;1;1;2;3
105 | id:15
106 | 1;1;2;1;1
107 | 2;1;2;4;4
108 | 3;1;2;0;0
109 | 4;3;4;0;0
110 | 5;3;3;1;2
111 | 6;4;4;1;2
112 | 7;2;2;2;3
113 | id:16
114 | 1;0;1;1;1
115 | 2;0;1;2;2
116 | 3;3;4;1;1
117 | 4;3;4;2;2
118 | 5;4;4;3;4
119 | 6;2;2;3;4
120 | 7;3;3;3;4
121 | id:17
122 | 1;1;2;2;2
123 | 2;3;4;3;3
124 | 3;1;2;0;0
125 | 4;3;4;1;1
126 | 5;0;0;2;3
127 | 6;1;1;3;4
128 | id:18
129 | 1;1;2;3;3
130 | 2;0;1;4;4
131 | 3;3;4;4;4
132 | 4;1;2;2;2
133 | 5;0;1;1;1
134 | 6;3;3;1;2
135 | 7;0;0;2;3
136 | id:19
137 | 1;1;2;4;4
138 | 2;3;4;2;2
139 | 3;3;4;4;4
140 | 4;0;1;2;2
141 | 5;0;0;0;1
142 | 6;4;4;0;1
143 | 7;1;1;0;1
144 | id:20
145 | 1;3;4;0;0
146 | 2;1;2;3;3
147 | 3;0;1;2;2
148 | 4;1;2;4;4
149 | 5;3;3;2;3
150 | 6;4;4;2;3
151 | id:21
152 | 1;3;4;2;2
153 | 2;1;2;0;0
154 | 3;1;2;2;2
155 | 4;1;2;1;1
156 | 5;2;2;3;4
157 | 6;0;0;3;4
158 | 7;0;0;0;1
159 | id:22
160 | 1;1;2;1;1
161 | 2;3;4;3;3
162 | 3;0;1;3;3
163 | 4;1;2;2;2
164 | 5;2;2;3;4
165 | 6;4;4;0;1
166 | 7;3;3;1;2
167 | id:23
168 | 1;1;2;1;1
169 | 2;3;4;0;0
170 | 3;2;3;4;4
171 | 4;0;1;3;3
172 | 5;4;4;2;3
173 | 6;2;2;2;3
174 | id:24
175 | 1;3;4;4;4
176 | 2;2;3;0;0
177 | 3;2;3;1;1
178 | 4;2;3;2;2
179 | 5;0;0;1;2
180 | 6;0;0;3;4
181 | 7;1;1;0;1
182 | id:25
183 | 1;1;2;1;1
184 | 2;2;3;0;0
185 | 3;3;4;1;1
186 | 4;3;4;2;2
187 | 5;1;1;2;3
188 | 6;0;0;0;1
189 | 7;2;2;3;4
190 | id:26
191 | 1;1;2;4;4
192 | 2;2;3;0;0
193 | 3;0;1;3;3
194 | 4;3;4;4;4
195 | 5;2;2;1;2
196 | 6;4;4;0;1
197 | id:27
198 | 1;2;3;0;0
199 | 2;2;3;1;1
200 | 3;1;2;2;2
201 | 4;1;2;3;3
202 | 5;0;0;3;4
203 | 6;4;4;2;3
204 | 7;3;3;3;4
205 | id:28
206 | 1;2;3;2;2
207 | 2;1;2;3;3
208 | 3;3;4;4;4
209 | 4;3;4;3;3
210 | 5;0;0;2;3
211 | 6;1;1;1;2
212 | 7;0;0;0;1
213 | id:29
214 | 1;0;1;3;3
215 | 2;0;1;0;0
216 | 3;3;4;4;4
217 | 4;0;0;1;2
218 | 5;4;4;2;3
219 | 6;2;2;3;4
220 | id:30
221 | 1;3;4;1;1
222 | 2;0;1;1;1
223 | 3;3;4;4;4
224 | 4;0;1;2;2
225 | 5;2;2;1;2
226 | 6;1;1;3;4
227 | 7;3;3;2;3
228 |
--------------------------------------------------------------------------------
/labs/01/linear/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/01.png
--------------------------------------------------------------------------------
/labs/01/linear/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/02.png
--------------------------------------------------------------------------------
/labs/01/linear/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/03.png
--------------------------------------------------------------------------------
/labs/01/linear/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/04.png
--------------------------------------------------------------------------------
/labs/01/linear/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/05.png
--------------------------------------------------------------------------------
/labs/01/linear/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/06.png
--------------------------------------------------------------------------------
/labs/01/linear/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/07.png
--------------------------------------------------------------------------------
/labs/01/linear/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/08.png
--------------------------------------------------------------------------------
/labs/01/linear/09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/09.png
--------------------------------------------------------------------------------
/labs/01/linear/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/10.png
--------------------------------------------------------------------------------
/labs/01/linear/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/11.png
--------------------------------------------------------------------------------
/labs/01/linear/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/12.png
--------------------------------------------------------------------------------
/labs/01/linear/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/13.png
--------------------------------------------------------------------------------
/labs/01/linear/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/14.png
--------------------------------------------------------------------------------
/labs/01/linear/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/15.png
--------------------------------------------------------------------------------
/labs/01/linear/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/16.png
--------------------------------------------------------------------------------
/labs/01/linear/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/17.png
--------------------------------------------------------------------------------
/labs/01/linear/18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/18.png
--------------------------------------------------------------------------------
/labs/01/linear/19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/19.png
--------------------------------------------------------------------------------
/labs/01/linear/20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/20.png
--------------------------------------------------------------------------------
/labs/01/linear/21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/21.png
--------------------------------------------------------------------------------
/labs/01/linear/22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/01/linear/22.png
--------------------------------------------------------------------------------
/labs/01/variants.txt:
--------------------------------------------------------------------------------
1 | varnt = позиция в алфавитно-упорядоченном списке группы (1, 2, ...)
2 | img1 = ((varnt - 1) % 22) + 1
3 | img2 = ((varnt + 8) % 22) + 1
4 | img3 = varnt
5 |
6 | 1-10
7 | 2-11
8 | 3-12
9 | 4-13
10 | 5-14
11 | 6-15
12 | 7-16
13 | 8-17
14 | 9-18
15 | 10-19
16 | 11-20
17 | 12-21
18 | 13-22
19 | 14-1
20 | 15-2
21 | 16-3
22 | 17-4
23 | 18-5
24 | 19-6
25 | 20-7
26 | 21-8
27 | 22-9
--------------------------------------------------------------------------------
/labs/02/VARIANTS02.md:
--------------------------------------------------------------------------------
1 | # Варианты задания №2 (Лабораторная работа №2)
2 | 1. MCC/MNC код
3 | 1. SmallestWidth
4 | 1. Available width
5 | 1. Available height
6 | 1. Screen size
7 | 1. Screen aspect
8 | 1. Round screen
9 | 1. UI mode
10 | 1. Night mode
11 | 1. Touchscreen type
12 | 1. Keyboard availability
13 | 1. Primary text input method
14 | 1. Navigation key availability
15 | 1. Primary non-touch navigation method
16 | 1. Platform Version (API level)
17 |
18 | Варианты 16-30 вычисляются как (var-15). Например, вариант 22 == вариант 7.
--------------------------------------------------------------------------------
/labs/02/continuewatch/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/README.md:
--------------------------------------------------------------------------------
1 | # Задание
2 |
3 | Разработать приложение, которое считает сколько секунд пользователь провел в
4 | приложении, т.е.:
5 | * Приложение считает секунды, когда оно отображается на экране
6 | * Приложение не считает секунды, когда оно не отображается на экране
7 |
8 | PS: continuewatch - это ассоциация автора на слово stopwatch. Приложение не является
9 | традиционным stopwatch (секундомером), но чем-то на него похоже.
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 |
6 | android {
7 | compileSdk 31
8 |
9 | defaultConfig {
10 | applicationId "com.example.myapplication"
11 | minSdk 23
12 | targetSdk 31
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | kotlinOptions {
30 | jvmTarget = '1.8'
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | implementation 'androidx.core:core-ktx:1.6.0'
37 | implementation 'androidx.appcompat:appcompat:1.3.1'
38 | implementation 'com.google.android.material:material:1.4.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
40 | testImplementation 'junit:junit:4.13.2'
41 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
43 | }
44 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/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 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/java/ru/spbstu/icc/kspt/lab2/continuewatch/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package ru.spbstu.icc.kspt.lab2.continuewatch
2 |
3 | import android.os.Bundle
4 | import android.widget.TextView
5 | import androidx.appcompat.app.AppCompatActivity
6 |
7 | class MainActivity : AppCompatActivity() {
8 | var secondsElapsed: Int = 0
9 | lateinit var textSecondsElapsed: TextView
10 |
11 | var backgroundThread = Thread {
12 | while (true) {
13 | Thread.sleep(1000)
14 | textSecondsElapsed.post {
15 | textSecondsElapsed.setText("Seconds elapsed: " + secondsElapsed++)
16 | }
17 | }
18 | }
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | setContentView(R.layout.activity_main)
23 | textSecondsElapsed = findViewById(R.id.textSecondsElapsed)
24 | backgroundThread.start()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/layout-land/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Continue Watch
3 |
4 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:7.0.2"
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | task clean(type: Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/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 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/continuewatch/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/labs/02/continuewatch/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 15 22:51:06 AST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
7 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/labs/02/continuewatch/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | include ':app'
9 | rootProject.name='Continue Watch'
10 |
--------------------------------------------------------------------------------
/labs/02/stat/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/stat/1.png
--------------------------------------------------------------------------------
/labs/02/stat/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/stat/2.png
--------------------------------------------------------------------------------
/labs/02/stat/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/stat/3.png
--------------------------------------------------------------------------------
/labs/02/stat/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/stat/4.png
--------------------------------------------------------------------------------
/labs/02/stat/sum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/02/stat/sum.png
--------------------------------------------------------------------------------
/labs/03/ANSWER02.md:
--------------------------------------------------------------------------------
1 | # Решение задачи №2
2 | Посмотрим внимательнее на эскиз
3 |
4 | 
5 |
6 | * `Activity1` всегда запускает `Activity2`. Можно использовать `Activity1#startActivity` для этой операции.
7 | * `Activity2` может вернуться в `Activity1` или перейти в новую `Activity3`. Для первой операции можно просто использовать метод `Activity2#finish`. Вторая операция интереснее, т.к. нам понадобится узнать, что привело к завершению `Activity3`. Используем `sartActivityForResult`.
8 | * `Activity3` может вернуться в `Activity1` или в `Activity2`. Для возврата в `Activity2` можно просто использовать метод `Activity3#finish`. Для возврата в `Activity1` понадобится помощь со стороны `Activity2`. Для того, чтобы известить `Activity2` о необходимости завершиться, используем код возврата, который передадим с помощью метода `Activity3#setResult`, только после этого вызовем метод `Activity3#finish`. `Activity2` в методе `Activity2#onActivityResult` должна проверить причину завершения `Activity3`: если `Activity3` завершилась из-за того, что пользователь нажал `toFirst`, то вызовем метод `Activity2#finish`. В случае `toSecond` дополнительных действий не требуется.
9 |
--------------------------------------------------------------------------------
/labs/03/activities.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/activities.dia
--------------------------------------------------------------------------------
/labs/03/stat/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/1.png
--------------------------------------------------------------------------------
/labs/03/stat/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/2.png
--------------------------------------------------------------------------------
/labs/03/stat/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/3.png
--------------------------------------------------------------------------------
/labs/03/stat/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/4.png
--------------------------------------------------------------------------------
/labs/03/stat/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/5.png
--------------------------------------------------------------------------------
/labs/03/stat/sum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/03/stat/sum.png
--------------------------------------------------------------------------------
/labs/04/res/reference/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 | local.properties
11 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/labs/04/res/reference/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 |
6 | android {
7 | compileSdk 30
8 |
9 | defaultConfig {
10 | applicationId "com.example.myapplication"
11 | minSdk 23
12 | targetSdk 30
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | kotlinOptions {
30 | jvmTarget = '1.8'
31 | }
32 | buildFeatures {
33 | viewBinding true
34 | }
35 | testOptions {
36 | unitTests.includeAndroidResources = true
37 | }
38 | }
39 |
40 | dependencies {
41 |
42 | implementation 'androidx.core:core-ktx:1.6.0'
43 | implementation 'androidx.appcompat:appcompat:1.3.1'
44 | implementation 'com.google.android.material:material:1.4.0'
45 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
46 | implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
47 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
48 | implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
49 | implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
50 | implementation 'androidx.test.espresso:espresso-contrib:3.4.0'
51 |
52 | // Required -- JUnit 4 framework
53 | testImplementation("junit:junit:4.13.2")
54 |
55 | testImplementation "androidx.test.ext:junit-ktx:1.1.3"
56 | testImplementation "androidx.test:core-ktx:1.4.0"
57 | testImplementation 'org.robolectric:robolectric:4.6'
58 |
59 | testImplementation 'androidx.test.espresso:espresso-core:3.4.0'
60 | testImplementation("androidx.navigation:navigation-testing:2.3.5")
61 | debugImplementation("androidx.fragment:fragment-testing:1.3.6")
62 |
63 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
64 | debugImplementation "androidx.test:core-ktx:1.4.0"
65 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
66 |
67 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/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
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/androidTest/java/com/example/myapplication/AboutUtils.kt:
--------------------------------------------------------------------------------
1 | package com.example.myapplication
2 |
3 | import android.view.Gravity
4 | import androidx.test.espresso.Espresso.onView
5 | import androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu
6 | import androidx.test.espresso.action.ViewActions.click
7 | import androidx.test.espresso.assertion.ViewAssertions.matches
8 | import androidx.test.espresso.contrib.DrawerActions
9 | import androidx.test.espresso.contrib.DrawerMatchers.isClosed
10 | import androidx.test.espresso.contrib.NavigationViewActions
11 | import androidx.test.espresso.matcher.ViewMatchers.withId
12 | import androidx.test.espresso.matcher.ViewMatchers.withText
13 |
14 | private fun openAboutViaBottomNav() {
15 | onView(withId(R.id.nav_view)).perform(click())
16 | }
17 |
18 | private fun openAboutViaDrawer() {
19 | // Open Drawer to click on navigation.
20 | onView(withId(R.id.drawer_layout))
21 | .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed.
22 | .perform(DrawerActions.open()); // Open Drawer
23 |
24 | // Start the screen of your activity.
25 | onView(withId(R.id.drawer_nav_view))
26 | .perform(NavigationViewActions.navigateTo(R.id.aboutActivity))
27 | }
28 |
29 | private fun openAboutViaOptions() {
30 | openContextualActionModeOverflowMenu()
31 | onView(withText(R.string.title_about))
32 | .perform(click())
33 | }
34 |
35 | fun openAbout() = openAboutViaBottomNav()
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/androidTest/java/com/example/myapplication/NavigationTest.kt:
--------------------------------------------------------------------------------
1 | package com.example.myapplication
2 |
3 | import androidx.test.core.app.launchActivity
4 | import androidx.test.espresso.Espresso
5 | import androidx.test.espresso.NoActivityResumedException
6 | import androidx.test.espresso.action.ViewActions
7 | import androidx.test.espresso.assertion.ViewAssertions
8 | import androidx.test.espresso.matcher.ViewMatchers
9 | import androidx.test.ext.junit.runners.AndroidJUnit4
10 | import org.junit.Assert.fail
11 | import org.junit.Test
12 | import org.junit.runner.RunWith
13 |
14 | /**
15 | * Instrumented test, which will execute on an Android device.
16 | *
17 | * See [testing documentation](http://d.android.com/tools/testing).
18 | */
19 | @RunWith(AndroidJUnit4::class)
20 | class NavigationTest {
21 | @Test
22 | fun testAbout() {
23 | launchActivity()
24 | openAbout()
25 | Espresso.onView(ViewMatchers.withId(R.id.activity_about))
26 | .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
27 | }
28 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/java/com/example/myapplication/AboutActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.myapplication
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 |
6 | class AboutActivity : AppCompatActivity() {
7 | override fun onCreate(savedInstanceState: Bundle?) {
8 | super.onCreate(savedInstanceState)
9 | setContentView(R.layout.activity_about)
10 | }
11 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/java/com/example/myapplication/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | package com.example.myapplication
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.Fragment
8 | import androidx.navigation.fragment.findNavController
9 |
10 | class Fragment1 : BaseFragment(R.layout.fragment1)
11 | class Fragment2 : BaseFragment(R.layout.fragment2)
12 | class Fragment3 : BaseFragment(R.layout.fragment3)
13 |
14 | abstract class BaseFragment(private val res: Int) : Fragment() {
15 |
16 | override fun onCreateView(
17 | inflater: LayoutInflater,
18 | container: ViewGroup?,
19 | savedInstanceState: Bundle?
20 | ): View? {
21 | val layout = inflater.inflate(res, container, false)
22 |
23 | layout.findViewById(R.id.bnToFirst)?.setOnClickListener {
24 | findNavController().navigate(R.id.action_to1)
25 | }
26 |
27 | layout.findViewById(R.id.bnToSecond)?.setOnClickListener {
28 | findNavController().navigate(R.id.action_to2)
29 | }
30 |
31 | layout.findViewById(R.id.bnToThird)?.setOnClickListener {
32 | findNavController().navigate(R.id.action_to3)
33 | }
34 |
35 | return layout
36 | }
37 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/java/com/example/myapplication/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.myapplication
2 |
3 | import android.os.Bundle
4 | import android.view.Menu
5 | import android.view.MenuItem
6 | import androidx.appcompat.app.AppCompatActivity
7 | import androidx.navigation.findNavController
8 | import androidx.navigation.ui.*
9 | import com.example.myapplication.databinding.ActivityMainBinding
10 | open class MainActivity : AppCompatActivity() {
11 |
12 |
13 | private lateinit var binding: ActivityMainBinding
14 | private lateinit var appBarConfiguration: AppBarConfiguration
15 |
16 | override fun onCreate(savedInstanceState: Bundle?) {
17 | super.onCreate(savedInstanceState)
18 |
19 | binding = ActivityMainBinding.inflate(layoutInflater)
20 | setContentView(binding.root)
21 |
22 | val navController = findNavController(R.id.nav_host_fragment_activity_main)
23 | appBarConfiguration = AppBarConfiguration(navController.graph, binding.drawerLayout)
24 |
25 | setupActionBarWithNavController(navController, appBarConfiguration)
26 | binding.navView.setupWithNavController(navController)
27 | binding.drawerNavView.setupWithNavController(navController)
28 | }
29 |
30 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
31 | // Inflate the menu; this adds items to the action bar if it is present.
32 | menuInflater.inflate(R.menu.bottom_nav_menu, menu)
33 | return true
34 | }
35 |
36 |
37 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
38 | return NavigationUI.onNavDestinationSelected(
39 | item, findNavController(R.id.nav_host_fragment_activity_main)
40 | ) || super.onOptionsItemSelected(item)
41 | }
42 |
43 | override fun onSupportNavigateUp(): Boolean {
44 | val navController = findNavController(R.id.nav_host_fragment_activity_main)
45 | return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
46 | }
47 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/drawable/ic_dashboard_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/drawable/ic_home_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/drawable/ic_notifications_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
15 |
16 |
27 |
28 |
39 |
40 |
41 |
49 |
50 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/layout/fragment1.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/layout/fragment2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
25 |
26 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/layout/fragment3.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
25 |
26 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/navigation/mobile_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
21 |
22 |
26 |
29 |
32 |
33 |
37 |
40 |
44 |
45 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | My Application
3 |
4 | About
5 | About text
6 |
7 | To Second
8 | To Third
9 | To First
10 |
--------------------------------------------------------------------------------
/labs/04/res/reference/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/labs/04/res/reference/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:7.0.0"
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | task clean(type: Delete) {
17 | delete rootProject.buildDir
18 | }
--------------------------------------------------------------------------------
/labs/04/res/reference/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=-Xmx2048m -Dfile.encoding=UTF-8
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
--------------------------------------------------------------------------------
/labs/04/res/reference/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/04/res/reference/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/labs/04/res/reference/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Oct 31 17:43:12 MSK 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/labs/04/res/reference/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/labs/04/res/reference/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | jcenter() // Warning: this repository is going to shut down soon
7 | }
8 | }
9 | rootProject.name = "My Application"
10 | include ':app'
11 |
--------------------------------------------------------------------------------
/labs/06/TASK.md:
--------------------------------------------------------------------------------
1 | # Лабораторная работа №6. Многопоточные Android приложения.
2 |
3 | ## Цели
4 | Получить практические навыки разработки многопоточных приложений:
5 | 1. Организация обработки длительных операций в background (worker) thread:
6 | * Запуск фоновой операции (Coroutine/ExecutionService/Thread)
7 | * Остановка фоновой операции (Coroutine/ExecutionService/Thread)
8 | 1. Публикация данных из background (worker) thread в main (ui) thread.
9 |
10 | Освоить 3 основные группы API для разработки многопоточных приложений:
11 | 1. Kotlin Coroutines
12 | 1. ExecutionService
13 | 1. Java Threads
14 |
15 | ## Задачи
16 | ### Задача 1. Альтернативные решения задачи "не секундомер" из Лаб. 2
17 | Используйте приложение "не секундомер", получившееся в результате выполнения [Лабораторной работы №2](../02/TASK.md). Разработайте несколько альтернативных приложений "не секундомер", отличающихся друг от друга организацией многопоточной работы. Опишите все известные Вам решения.
18 |
19 | #### Указания
20 | К моменту выполнения работы Вам должно быть известно, как минимум, 4 принципиально разных подхода к решению задачи. В отчете должны появиться, как минимум, 3 решения:
21 | 1. С помощью Java Threads (фактически, это оригинальный код, однако на этот раз необходимо убедиться, что потоки запускаются и останавливаются в определенные моменты времени. Опишите эти моменты времени в отчете. Обратите внимание, что потоки не должны существовать, когда приложение не отображается на экране).
22 | 1. С помощью [ExecutionService](https://developer.android.com/guide/background/threading). Это та же программа, что и в предыдущем пункте, только в этой версии программы потоки не будут создаваться вручную. Потоки могут существовать, когда приложение находится в background, однако нужно убедиться, что этот поток ничего не делает.
23 | 1. С помощью [Kotlin Coroutines](https://developer.android.com/kotlin/coroutines). В качестве знакомства с корутинами рекомендуется выполнить шаги 1-6 (включительно) из codelab: https://codelabs.developers.google.com/codelabs/kotlin-coroutines
24 |
25 | Во всех случаях необходимо обращать внимание на то, когда запускаются потоки/задачи и когда они останавливаются: приложение не должно тратить впустую ресурсы ОС, когда оно не отображается на экране.
26 |
27 | Как и в любом другом приложении, необходимо уделить особое внимание поведению приложения в ситуации перезапуска Activity (например, в результате поворота экрана). Не должно появляться более одного активного потока/задачи для подсчета времени.
28 |
29 | Также можно улучшить точность подсчета времени. `sleep(1000)` не гарантирует остановку потока *ровно* на 1000 мс. Подумайте, как избавиться от накапливающейся ошибки. Для улучшения мыслительного процесса поменяйте `sleep(1000)` на `sleep(Random.nextInt(2000))`, чтобы не возникало ложного ощущения, что число `1000` можно скорректировать на какое-либо количество миллисекунд.
30 |
31 | ### Задача 2. Загрузка картинки в фоновом потоке
32 | Создайте приложение, которое скачивает картинку из интернета и размещает ее в `ImageView` в `Activity`. Используйте `ExecutorService` для решения этой задачи. Пример закачки картинки:
33 | ```java
34 | URL newurl = new URL(photo_url_str);
35 | mIcon_val = BitmapFactory.decodeStream(newurl.openConnection().getInputStream());
36 | profile_photo.setImageBitmap(mIcon_val);
37 | ```
38 |
39 | ### Задача 3. Загрузка картинки в фоновом потоке (Kotlin Coroutines)
40 | Перепишите предыдущее приложение с использованием Kotlin Coroutines.
41 |
42 | ### Задача 4. Использование сторонних библиотек
43 | Многие "стандартные" задачи имеют "стандартные" решения. Задача скачивания изображения в фоне возникает настолько часто, что уже сравнительно давно решение этой задачи занимает всего лишь несколько строчек. Убедитесь в этом на примере одной (любой) библиотеки [Glide](https://github.com/bumptech/glide#how-do-i-use-glide), [picasso](https://square.github.io/picasso/) или [fresco](https://frescolib.org/docs/index.html).
44 |
45 | ### Задача 5* (по желанию). Using Kotlin Coroutines Codelab
46 | Выполните все шаги codelab https://codelabs.developers.google.com/codelabs/kotlin-coroutines
47 |
48 | Результаты выполнения этого задания не обязательно отображать в отчёте. Выполнение этого задания не влияет на аттестацию.
49 |
50 |
51 | # Общие Рекомендации
52 |
53 |
54 | ## Отчет
55 | Отчет должен содержать формулировку целей, решения задач с ответами на дополнительные вопросы из раздела «указания», выводы. Выводы должны содержать:
56 | 1. информацию о том, как достигается каждая из задач в разных группах API: запуск фоновой задачи, остановка фоновой задачи, передача данных из фонового потока в UI поток;
57 | 2. любую дополнительную уместную информацию на усмотрение студента;
58 |
59 | ## Дополнительные файлы
60 |
61 | 1. Отчёт или сопроводительное письмо должны содержать ссылку на полный проект с решением всех задач, кроме codelabs (или несколько проектов), который можно загрузить в Android Studio.
62 |
63 | ## Статистика (по желанию)
64 | В отчете укажите примерное время решения каждой из предложенных задач, включая время ознакомления со справочными материалами (время решения не влияет на оценку: только на анонимный сбор статистики для корректировки сложности задач в будущем).
65 |
66 | # Вспомогательные материалы
67 | ## Основные
68 | 1. https://developer.android.com/kotlin/coroutines
69 | 1. http://developer.android.com/reference/android/os/AsyncTask.html
70 | 1. https://developer.android.com/reference/java/lang/Thread
71 |
72 | ## Дополнительные
73 | 1. http://developer.alexanderklimov.ru/android/theory/asynctask.php
74 | 1. https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md
75 |
--------------------------------------------------------------------------------
/labs/07/TASK.md:
--------------------------------------------------------------------------------
1 | # Лабораторная работа №7. Сервисы и Broadcast Receivers.
2 |
3 | ## Цели
4 | Получить практические навыки разработки сервисов (started и bound) и Broadcast Receivers.
5 |
6 | ## Задачи
7 | ### Задача 1. Started сервис для скачивания изображения
8 | В [лабораторной работе №6](../06/TASK.md) был разработан код, скачивающий картинку из интернета. На основе этого кода разработайте started service, скачивающий файл из интернета. URL изображения для скачивания должен передаваться в Intent. Убедитесь (и опишите доказательство в отчете), что код для скачивания исполняется не в UI потоке
9 |
10 | Добавьте в разработанный сервис функцию отправки broadcast сообщения по завершении скачивания. Сообщение (Intent) должен содержать путь к скачанному файлу.
11 |
12 | ### Задача 2. Broadcast Receiver
13 | Разработайте два приложения: первое приложение содержит 1 activity с 1 кнопкой, при нажатии на которую запускается сервис по скачиванию файла. Второе приложение содержит 1 broadcast receiver и 1 activity. Broadcast receiver по получении сообщения из сервиса инициирует отображение *пути* к изображению в `TextView` в Activity.
14 |
15 | ### Задача 3. Bound Service для скачивания изображения
16 | Сделайте разработанный сервис одновременно bound И started: переопределите метод `onBind`. Из тела метода возвращайте `IBinder`, полученный из класса [`Messenger`](https://developer.android.com/guide/components/bound-services?hl=ru#Messenger). Убедитесь (доказательство опишите в отчете), что код скачивания файла исполняется не в UI потоке.
17 |
18 | Измените способ запуска сервиса в первом приложении: вместо `startService` используйте `bindService`. При нажатии на кнопку отправляйте сообщение [`Message`](https://developer.android.com/reference/android/os/Message.html?hl=ru), используя класс `Messenger`, полученный из интерфейса `IBinder` в методе [`onServiceConnected`](https://developer.android.com/reference/android/content/ServiceConnection.html?hl=ru#onServiceConnected(android.content.ComponentName,%20android.os.IBinder)).
19 |
20 | Добавьте в первое приложение `TextView`, а в сервис отправку [обратного](https://developer.android.com/reference/android/os/Message.html?hl=ru#replyTo) сообщения с местоположением скачанного файла. При получении сообщения от сервиса приложение должно отобразить путь к файлу на экране.
21 |
22 | Обратите внимание, что разработанный сервис должен быть одновременно bound И started. Если получен интент через механизм started service, то сервис скачивает файл и отправляет broadcast (started service не знает своих клиентов и не предназначен для двухсторонней коммуникации). Если получен message через механизм bound service, то скачивается файл и результат отправляется тому клиенту, который запросил этот файл (т.к. bound service знает всех своих клиентов и может им отвечать).
23 |
24 | ## Задача 4**. Shared Storage и знакомство с ContentProvider
25 | Эта задача имеет высокую сложность. Выполнение этого задания не обязательно.
26 |
27 | Вместо отображения пути к картинке во всех приложениях отображайте саму картинку. Для решения задачи рекомендуется воспользоваться MediaStore API (https://developer.android.com/training/data-storage/shared/media?hl=ru)
28 |
29 | # Отчет
30 | Отчет должен содержать формулировку целей, решения задач с ответами на дополнительные вопросы, выводы. Выводы должны содержать убедительное обоснование, почему автор отчета считает, что все цели были достигнуты. Например, обоснование может включать краткую информацию о том, как достигалась каждая из поставленных целей.
31 |
32 | В отчете укажите примерное время решения каждой из предложенных задач, включая время ознакомления со справочными материалами (время решения не влияет на оценку: только на анонимный сбор статистики для корректировки сложности задач в будущем).
33 |
34 | # Вспомогательные материалы
35 | ## Основные
36 | 1. https://developer.android.com/guide/components/services?hl=ru
37 | 1. https://developer.android.com/guide/components/broadcasts?hl=ru
38 | 1. https://developer.android.com/training/data-storage/app-specific?hl=ru
39 |
40 | ## Дополнительные
41 | 1.
42 |
--------------------------------------------------------------------------------
/labs/RecyclerView/TASK.md:
--------------------------------------------------------------------------------
1 | # Лабораторная работа №4. RecyclerView.
2 |
3 | ## Цели
4 | 1. Ознакомиться с принципами работы adapter-based views.
5 | 1. Получить практические навыки разработки адаптеров для view.
6 |
7 | ## Задачи
8 |
9 | В вашем распоряжении имеется [библиотека](biblib), предоставляющая программный доступ к записям в формате [bibtex](http://www.bibtex.org). Библиотека имеет 2 режима работы: normal и strict. В strict mode работает искусственное ограничение: в памяти нельзя хранить более `name.ank.lab4.BibConfig#maxValid=20` записей одновременно. При извлечении `maxValid+1`й записи 1я извелеченная запись становится невалидной (при доступе к полям кидаются исключения). Это ограничение позволит быстрее выявлять ошибки при работе с `RecyclerView` и адаптерами.
10 |
11 | ### Задача 1. Знакомство с библиотекой (unit test)
12 | Ознакомьтесь со strict mode библиотеки, проиллюстрировав его работу unit-тестом.
13 |
14 | #### Указания
15 | 1. Изучите демонстрационное предложенную [библиотеку](biblib), уделите особое внимание файлу [BibDatabaseTest.java](biblib/src/test/java/name/ank/lab4/BibDatabaseTest.java). В этом файле тестируется (демонстрируется) создание библиотеки (см. `setup()`), чтение одной записи (см. `getFirstEntry()`) и normal (не strict) mode (см. `normalModeDoesNotThrowException()`). Посмотрите на пример [исходных данных](biblib/src/test/resources/references.bib), при необходимости загляните [внутрь библиотеки](biblib/src/main/java/name/ank/lab4).
16 | 1. Напишите несколько тестов с помощью которых вы можете сами себя проверить, что правильно поняли, как работает флаг `BibConfig#strict` и `BibConfig#shuffle` (в `BibDatabaseTest.java` оставлены шаблоны методов).
17 | 1. Соберите jar файл используя команду `./gradlew build`. Результаты сборки будут доступны по пути `build/libs/biblib.jar`. Обратите внимание, что сборка завершится ошибкой, если какие-либо тесты не проходят.
18 |
19 | ### Задача 2. Знакомство с RecyclerView.
20 | Напишите Android приложение, которое выводит все записи из bibtex файла на экран, используя предложенную библиотеку и `RecyclerView`. На выбор предлагается решить одну из двух задач:
21 |
22 | #### Задача 2.1. Однородный список (задача обычной сложности).
23 | В качестве исходных данных используйте файл [articles.bib](samples/articles.bib) . Обратите внимание, что все записи имеют одинаковый формат (@article).
24 |
25 | #### Задача 2.2*. Неоднородный список (задача повышенной сложности).
26 | В качестве исходных данных используйте файл [mixed.bib](samples/mixed.bib) . Обратите внимание, что записи имеют разный формат (@article, @misc, @inproceedings, etc). Используйте разное визуальное отображение для записей разного типа.
27 |
28 |
29 | #### Пояснения
30 | 1. При выводе записей не обязательно выводить все поля. Придумайте некоторый "адекватный" формат отображения данных. Выбор формата отображения поясните в отчете.
31 | 1. Записи можно выводить списком (list), сеткой (grid) или любым другим способом.
32 |
33 | #### Указания
34 | 1. Файлы с исходными данными скачайте и разместите в ресурсы приложения (`raw` ресурс).
35 | 1. Подключите библиотеку как зависимость на прекомпилированный jar файл (https://developer.android.com/studio/projects/android-library#AddDependency).
36 | 1. Ознакомьтесь с описанием RecyclerView (https://developer.android.com/guide/topics/ui/layout/recyclerview) и решите выбранную задачу.
37 |
38 | ### Задача 3. Бесконечный список.
39 | Сделайте список из предыдущей задачи бесконечным: после последнего элемента все записи повторяются, начиная с первой.
40 |
41 | #### Указания
42 | 1. Модифицируйте код адаптера так, чтобы добиться желаемого поведения приложения
43 |
44 | # Отчет
45 | Отчет должен содержать формулировку целей, решения задач с ответами на дополнительные вопросы из раздела «указания», выводы. Выводы должны содержать убедительное обоснование, почему автор отчета считает, что все цели были достигнуты. Например, обоснование может включать краткую информацию о том, как достигалась каждая из поставленных целей.
46 |
47 | В отчете укажите примерное время решения каждой из предложенных задач, включая время ознакомления со справочными материалами (время решения не влияет на оценку: только на анонимный сбор статистики для корректировки сложности задач в будущем).
48 |
49 | # Вспомогательные материалы
50 | ## Основные
51 | 1. https://developer.android.com/guide/topics/ui/layout/recyclerview
52 | 1. https://www.udacity.com/course/developing-android-apps-with-kotlin--ud9012 (Lesson 7: RecyclerView)
53 |
54 | ## Дополнительные (на русском языке)
55 | 1.
56 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | build
3 | .gradle
4 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/README.md:
--------------------------------------------------------------------------------
1 | # Building
2 | ```bash
3 | ./gradlew build
4 | ```
5 | JAR file will be created in `build/libs/biblib.jar`
6 |
7 | Note that there are 2 failing test. Add the test method body or use `./gradlew assemble` instead.
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | repositories {
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | compile "org.jbibtex:jbibtex:1.0.17"
9 | testCompile "junit:junit:4.12"
10 | }
11 |
12 | jar {
13 | from {
14 | configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/labs/RecyclerView/biblib/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 15 22:51:06 AST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/main/java/name/ank/lab4/BibConfig.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 | public class BibConfig {
4 | /**
5 | * Should the database be shuffled or not (useful for debugging and testing).
6 | * May be modified at any moment. Only affects newly created {@link BibDatabase} instances.
7 | */
8 | public boolean shuffle = true;
9 |
10 | /**
11 | * Strict mode enabled flag.
12 | * May be modified at any time. Affects all the existing instances of {@link BibEntry}.
13 | */
14 | public boolean strict = false;
15 |
16 | /**
17 | * How many instances of {@link BibEntry} should remain valid. Has effect only if {@link #strict} set to {@code true}.
18 | */
19 | public long maxValid = 20;
20 | }
21 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/main/java/name/ank/lab4/BibDatabase.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 | import java.io.IOException;
4 | import java.io.Reader;
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 | import org.jbibtex.BibTeXDatabase;
9 | import org.jbibtex.BibTeXEntry;
10 | import org.jbibtex.BibTeXParser;
11 | import org.jbibtex.ParseException;
12 |
13 | public class BibDatabase {
14 |
15 | private final List entries;
16 | private BibConfig cfg;
17 |
18 |
19 | public BibDatabase(Reader reader) throws IOException {
20 | this(reader, new BibConfig());
21 | }
22 |
23 | /**
24 | * Constructor.
25 | * @param reader database source. Caller should take care anc close the reader after the constructor exits.
26 | * @throws IOException when underlying parser fails to read the database
27 | */
28 | public BibDatabase(Reader reader, BibConfig cfg) throws IOException {
29 | this.cfg = cfg;
30 | try {
31 | BibTeXParser bibtexParser = new BibTeXParser();
32 | BibTeXDatabase database = bibtexParser.parse(reader);
33 | entries = new ArrayList<>(database.getEntries().values());
34 | if (cfg.shuffle) {
35 | Collections.shuffle(entries);
36 | }
37 | } catch (ParseException e) {
38 | throw new IOException(e);
39 | }
40 | }
41 |
42 | /**
43 | * Gets database entry
44 | * @param idx index in the database. Note that {@link BibConfig#shuffle} flag may affect the order in different instances.
45 | * @return database entry at the requested index.
46 | * @throws IndexOutOfBoundsException when requested index does not exist.
47 | */
48 | public BibEntry getEntry(int idx) throws IndexOutOfBoundsException {
49 | return new BibEntry(entries.get(idx), cfg);
50 | }
51 |
52 | /**
53 | * Database size
54 | */
55 | public int size() {
56 | return entries.size();
57 | }
58 |
59 | public BibConfig getCfg() {
60 | return cfg;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/main/java/name/ank/lab4/BibEntry.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 | import java.util.concurrent.atomic.AtomicLong;
4 | import org.jbibtex.BibTeXEntry;
5 | import org.jbibtex.Value;
6 |
7 | public class BibEntry {
8 |
9 | private static final AtomicLong latestOrder = new AtomicLong();
10 | private final long myOrder;
11 | private BibTeXEntry delegate;
12 | private BibConfig cfg;
13 |
14 | BibEntry(BibTeXEntry delegate, BibConfig cfg) {
15 | myOrder = latestOrder.incrementAndGet();
16 | this.delegate = delegate;
17 | this.cfg = cfg;
18 | }
19 |
20 | private void assertDelegateIsValid() {
21 | if (cfg.strict) {
22 | long latestOrder = BibEntry.latestOrder.get();
23 | if (myOrder + cfg.maxValid <= latestOrder) {
24 | throw new IllegalStateException(
25 | String.format("This object has already been invalidated. myOrder=%d, latestOrder=%d", myOrder, latestOrder)
26 | );
27 | }
28 | }
29 | }
30 |
31 | /**
32 | * Gets bibtex type of this entry
33 | * @return bibtex type
34 | */
35 | public Types getType() {
36 | assertDelegateIsValid();
37 | Types ret = Types.fromBtValue(delegate.getType());
38 | assert ret != null : "All the types must have mappings: " + delegate.getType();
39 | return ret;
40 | }
41 |
42 | /**
43 | * Gets field by its key (if any)
44 | * @param key field to return
45 | * @return field value or {@code null} if the key does not exist
46 | */
47 | public String getField(Keys key) {
48 | assertDelegateIsValid();
49 | Value field = delegate.getField(key.getBtKey());
50 | if (field != null) {
51 | return field.toUserString();
52 | } else {
53 | return null;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/main/java/name/ank/lab4/Keys.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 | import org.jbibtex.BibTeXEntry;
4 | import org.jbibtex.Key;
5 |
6 | public enum Keys {
7 | ADDRESS(BibTeXEntry.KEY_ADDRESS),
8 | ANNOTE(BibTeXEntry.KEY_ANNOTE),
9 | AUTHOR(BibTeXEntry.KEY_AUTHOR),
10 | BOOKTITLE(BibTeXEntry.KEY_BOOKTITLE),
11 | CHAPTER(BibTeXEntry.KEY_CHAPTER),
12 | CROSSREF(BibTeXEntry.KEY_CROSSREF),
13 | DOI(BibTeXEntry.KEY_DOI),
14 | EDITION(BibTeXEntry.KEY_EDITION),
15 | EDITOR(BibTeXEntry.KEY_EDITOR),
16 | EPRINT(BibTeXEntry.KEY_EPRINT),
17 | HOWPUBLISHED(BibTeXEntry.KEY_HOWPUBLISHED),
18 | INSTITUTION(BibTeXEntry.KEY_INSTITUTION),
19 | JOURNAL(BibTeXEntry.KEY_JOURNAL),
20 | KEY(BibTeXEntry.KEY_KEY),
21 | MONTH(BibTeXEntry.KEY_MONTH),
22 | NOTE(BibTeXEntry.KEY_NOTE),
23 | NUMBER(BibTeXEntry.KEY_NUMBER),
24 | ORGANIZATION(BibTeXEntry.KEY_ORGANIZATION),
25 | PAGES(BibTeXEntry.KEY_PAGES),
26 | PUBLISHER(BibTeXEntry.KEY_PUBLISHER),
27 | SCHOOL(BibTeXEntry.KEY_SCHOOL),
28 | SERIES(BibTeXEntry.KEY_SERIES),
29 | TITLE(BibTeXEntry.KEY_TITLE),
30 | TYPE(BibTeXEntry.KEY_TYPE),
31 | URL(BibTeXEntry.KEY_URL),
32 | VOLUME(BibTeXEntry.KEY_VOLUME),
33 | YEAR(BibTeXEntry.KEY_YEAR);
34 |
35 | private final Key btKey;
36 |
37 | Keys(Key key) {
38 | this.btKey = key;
39 | }
40 |
41 | Key getBtKey() {
42 | return btKey;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/main/java/name/ank/lab4/Types.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import org.jbibtex.BibTeXEntry;
6 | import org.jbibtex.Key;
7 |
8 | public enum Types {
9 | ARTICLE(BibTeXEntry.TYPE_ARTICLE),
10 | BOOK(BibTeXEntry.TYPE_BOOK),
11 | BOOKLET(BibTeXEntry.TYPE_BOOKLET),
12 | CONFERENCE(BibTeXEntry.TYPE_CONFERENCE),
13 | INBOOK(BibTeXEntry.TYPE_INBOOK),
14 | INCOLLECTION(BibTeXEntry.TYPE_INCOLLECTION),
15 | INPROCEEDINGS(BibTeXEntry.TYPE_INPROCEEDINGS),
16 | MANUAL(BibTeXEntry.TYPE_MANUAL),
17 | MASTERSTHESIS(BibTeXEntry.TYPE_MASTERSTHESIS),
18 | MISC(BibTeXEntry.TYPE_MISC),
19 | PHDTHESIS(BibTeXEntry.TYPE_PHDTHESIS),
20 | PROCEEDINGS(BibTeXEntry.TYPE_PROCEEDINGS),
21 | TECHREPORT(BibTeXEntry.TYPE_TECHREPORT),
22 | UNPUBLISHED(BibTeXEntry.TYPE_UNPUBLISHED);
23 |
24 | private static final Map typeMapping = new HashMap<>();
25 |
26 | static {
27 | for (Types value : Types.values()) {
28 | typeMapping.put(value.btType, value);
29 | }
30 | }
31 |
32 | private final Key btType;
33 |
34 | Types(Key typeArticle) {
35 | btType = typeArticle;
36 | }
37 |
38 | static Types fromBtValue(Key typeArticle) {
39 | return typeMapping.get(typeArticle);
40 | }
41 |
42 | Key getBtType() {
43 | return btType;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/test/java/name/ank/lab4/BibDatabaseTest.java:
--------------------------------------------------------------------------------
1 | package name.ank.lab4;
2 |
3 |
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 |
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 |
10 | import static org.junit.Assert.assertNotNull;
11 | import static org.junit.Assert.fail;
12 |
13 | public class BibDatabaseTest {
14 |
15 | private BibDatabase openDatabase(String s) throws IOException {
16 | try (InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream(s))) {
17 | return new BibDatabase(reader);
18 | }
19 | }
20 |
21 | @Test
22 | public void getFirstEntry() throws IOException {
23 | BibDatabase database = openDatabase("/references.bib");
24 | BibEntry first = database.getEntry(0);
25 | Assert.assertEquals(Types.ARTICLE, first.getType());
26 | Assert.assertEquals("The semantic web", first.getField(Keys.TITLE));
27 | Assert.assertNull("Field 'chapter' does not exist", first.getField(Keys.CHAPTER));
28 | }
29 |
30 | @Test
31 | public void normalModeDoesNotThrowException() throws IOException {
32 | BibDatabase database = openDatabase("/mixed.bib");
33 | BibConfig cfg = database.getCfg();
34 | cfg.strict = false;
35 |
36 | BibEntry first = database.getEntry(0);
37 | for (int i = 0; i < cfg.maxValid + 1; i++) {
38 | BibEntry unused = database.getEntry(0);
39 | assertNotNull("Should not throw any exception @" + i, first.getType());
40 | }
41 | }
42 |
43 | @Test
44 | public void canReadAllItemsFromMixed() throws IOException {
45 | BibDatabase database = openDatabase("/mixed.bib");
46 |
47 | for (int i = 0; i < database.size(); i++) {
48 | BibEntry entry = database.getEntry(i);
49 | assertNotNull(entry.getType());
50 | }
51 | }
52 |
53 | @Test
54 | public void strictModeThrowsException() {
55 | fail("Not implemented");
56 | }
57 |
58 | @Test
59 | public void shuffleFlag() {
60 | fail("Not implemented");
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/labs/RecyclerView/biblib/src/test/resources/references.bib:
--------------------------------------------------------------------------------
1 | @article{semanticweb,
2 | title = {The semantic web},
3 | author = {Berners-Lee, Tim and Hendler, James and Lassila, Ora and others},
4 | journal = {Scientific American},
5 | volume = {284},
6 | number = {5},
7 | pages = {28--37},
8 | year = {2001},
9 | publisher = {New York, NY, USA:}
10 | }
11 |
--------------------------------------------------------------------------------
/lectures/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 |
--------------------------------------------------------------------------------
/lectures/README.md:
--------------------------------------------------------------------------------
1 | # Вопросы для подготовки к экзамену
2 | 1. Android SDK, API level, Support Libraries/AndroidX, структура приложения.
3 | 1. Компиляция проекта, типы ресурсов.
4 | 2. (ЛР1) View, ViewGroup, LayoutParams, Common Layouts, Adapter Layouts.
5 | 3. (ЛР2) Альтернативные ресурсы, алгоритм best match.
6 | 3. (ЛР2) Activity. Жизненный цикл.
7 | 4. Activity. Сохранение состояния (ViewModel, Saved instance state, Persistent storage).
8 | 4. ViewBinding library. DataBinding library.
9 | 4. (ЛР3) Lifecycle, LifecycleOwner, Observer, LifecycleObserver, LiveData.
10 | 5. (ЛР3) Task & BackStack (task affinity, launch mode).
11 | 5. (ЛР3) Fragment. Философия, жизненный цикл, fragment manager, navigation graph.
12 | 10. Intent, intent-filter, intent resolution (implicit & explicit intents).
13 | 7. (ЛР4) Тестирование Android приложений: JUnit, Robolectric, Espresso, UI Automator.
14 | 10. Android permissions.
15 | 11. (ЛР5) Многопоточная обработка (Java threads, ExecutorService, Kotlin coroutines).
16 | 13. Значимость процессов. Doze mode, App Standby.
17 | 14. Background Tasks: Immediate, Exact, Deferred
18 | 14. Broadcast receivers.
19 | 13. Services: started, bound. Интерфейс IBinder.
20 | 15. Content providers, Temporary URI permissions
21 | 15. Storage access framework
22 | 15. ~~Не в доступе: ROOM: Database, DAO, Entity.~~
23 | 9. ~~Не в доступе: публикация приложений в google play~~
24 |
25 | # Полезные ссылки:
26 | 1. https://developer.android.com/guide
27 | 1. https://www.udacity.com/course/ud9012 - Developing Android Apps with Kotlin byGoogle (англ.б бесплатный)
28 | 1. Cheat sheet: состояния activity и fragment:
29 | 1. [https://medium.com/androiddevelopers/the-android-lifecycle-cheat-sheet-part-i-single-activities-e49fd3d202ab?](The Android Lifecycle cheat sheet — part I: Single Activities)
30 | 1. [https://medium.com/androiddevelopers/the-android-lifecycle-cheat-sheet-part-ii-multiple-activities-a411fd139f24?](The Android Lifecycle cheat sheet — part II: Multiple activities)
31 | 1. [https://medium.com/androiddevelopers/the-android-lifecycle-cheat-sheet-part-iii-fragments-afc87d4f37fd?](The Android Lifecycle cheat sheet — part III : Fragments)
32 | 1. [https://medium.com/androiddevelopers/the-android-lifecycle-cheat-sheet-part-iv-49946659b094](The Android Lifecycle cheat sheet — part IV : ViewModels, Translucent Activities and Launch Modes)
33 |
--------------------------------------------------------------------------------
/lectures/res/01-android-com.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-android-com.png
--------------------------------------------------------------------------------
/lectures/res/01-arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-arch.png
--------------------------------------------------------------------------------
/lectures/res/01-build-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-build-new.png
--------------------------------------------------------------------------------
/lectures/res/01-build-pkg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-build-pkg.png
--------------------------------------------------------------------------------
/lectures/res/01-build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-build.png
--------------------------------------------------------------------------------
/lectures/res/01-perm-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-perm-sample.png
--------------------------------------------------------------------------------
/lectures/res/01-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-project.png
--------------------------------------------------------------------------------
/lectures/res/01-qr-lectures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-qr-lectures.png
--------------------------------------------------------------------------------
/lectures/res/01-uses-feature-sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/01-uses-feature-sample.png
--------------------------------------------------------------------------------
/lectures/res/02-adapter-layouts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-adapter-layouts.png
--------------------------------------------------------------------------------
/lectures/res/02-buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-buttons.png
--------------------------------------------------------------------------------
/lectures/res/02-checkbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-checkbox.png
--------------------------------------------------------------------------------
/lectures/res/02-common-layouts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-common-layouts.png
--------------------------------------------------------------------------------
/lectures/res/02-cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-cross.png
--------------------------------------------------------------------------------
/lectures/res/02-edittext.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-edittext.png
--------------------------------------------------------------------------------
/lectures/res/02-imeoptions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-imeoptions.png
--------------------------------------------------------------------------------
/lectures/res/02-layerlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-layerlist.png
--------------------------------------------------------------------------------
/lectures/res/02-levellist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-levellist.png
--------------------------------------------------------------------------------
/lectures/res/02-pat-a-cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-pat-a-cat.png
--------------------------------------------------------------------------------
/lectures/res/02-radiobutton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-radiobutton.png
--------------------------------------------------------------------------------
/lectures/res/02-res-types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-res-types.png
--------------------------------------------------------------------------------
/lectures/res/02-spinner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-spinner.png
--------------------------------------------------------------------------------
/lectures/res/02-statelist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/02-statelist.png
--------------------------------------------------------------------------------
/lectures/res/03-activity-backstack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-activity-backstack.png
--------------------------------------------------------------------------------
/lectures/res/03-activity-fw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-activity-fw.png
--------------------------------------------------------------------------------
/lectures/res/03-dpi-bitmap-sizes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-dpi-bitmap-sizes.png
--------------------------------------------------------------------------------
/lectures/res/03-generalized-sizes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-generalized-sizes.png
--------------------------------------------------------------------------------
/lectures/res/03-layout-dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-layout-dp.png
--------------------------------------------------------------------------------
/lectures/res/03-layout-px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-layout-px.png
--------------------------------------------------------------------------------
/lectures/res/03-win-ar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/03-win-ar.jpg
--------------------------------------------------------------------------------
/lectures/res/Motorola-milestone-wikipedia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/Motorola-milestone-wikipedia.png
--------------------------------------------------------------------------------
/lectures/res/Nexus_5_(1).jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/Nexus_5_(1).jpg
--------------------------------------------------------------------------------
/lectures/res/activity-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/activity-lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/activity-states.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/activity-states.png
--------------------------------------------------------------------------------
/lectures/res/activity_fragment_lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/activity_fragment_lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/am_instrument.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/am_instrument.png
--------------------------------------------------------------------------------
/lectures/res/android-profiler-no-safepoint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/android-profiler-no-safepoint.png
--------------------------------------------------------------------------------
/lectures/res/android-startup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/android-startup.png
--------------------------------------------------------------------------------
/lectures/res/android_test_orchestrator_flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/android_test_orchestrator_flow.png
--------------------------------------------------------------------------------
/lectures/res/anr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/anr.png
--------------------------------------------------------------------------------
/lectures/res/ape_fwk_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/ape_fwk_all.png
--------------------------------------------------------------------------------
/lectures/res/app-architecture-gdd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/app-architecture-gdd.png
--------------------------------------------------------------------------------
/lectures/res/art-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/art-overview.png
--------------------------------------------------------------------------------
/lectures/res/bottom-navigation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/bottom-navigation.png
--------------------------------------------------------------------------------
/lectures/res/c1-vs-tired.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/c1-vs-tired.png
--------------------------------------------------------------------------------
/lectures/res/camera2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/camera2.png
--------------------------------------------------------------------------------
/lectures/res/cms-major-gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/cms-major-gc.png
--------------------------------------------------------------------------------
/lectures/res/content-provider-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/content-provider-overview.png
--------------------------------------------------------------------------------
/lectures/res/dalvik-gc-for-alloc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/dalvik-gc-for-alloc.png
--------------------------------------------------------------------------------
/lectures/res/dalvik-oom-on-halffull-heap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/dalvik-oom-on-halffull-heap.png
--------------------------------------------------------------------------------
/lectures/res/dalvik-oom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/dalvik-oom.png
--------------------------------------------------------------------------------
/lectures/res/definework-flex-period.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/definework-flex-period.png
--------------------------------------------------------------------------------
/lectures/res/densities-phone_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/densities-phone_2x.png
--------------------------------------------------------------------------------
/lectures/res/diagram_backstack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/diagram_backstack.png
--------------------------------------------------------------------------------
/lectures/res/diagram_backstack_singletask_multiactivity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/diagram_backstack_singletask_multiactivity.png
--------------------------------------------------------------------------------
/lectures/res/diagram_multiple_instances.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/diagram_multiple_instances.png
--------------------------------------------------------------------------------
/lectures/res/diagram_multitasking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/diagram_multitasking.png
--------------------------------------------------------------------------------
/lectures/res/doc_intent-filter-element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/doc_intent-filter-element.png
--------------------------------------------------------------------------------
/lectures/res/espresso-cheatsheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/espresso-cheatsheet.png
--------------------------------------------------------------------------------
/lectures/res/espresso_sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/espresso_sync.png
--------------------------------------------------------------------------------
/lectures/res/fragment_lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/fragment_lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/fragment_lifecycle_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/fragment_lifecycle_1.png
--------------------------------------------------------------------------------
/lectures/res/fragment_lifecycle_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/fragment_lifecycle_2.png
--------------------------------------------------------------------------------
/lectures/res/fragments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/fragments.png
--------------------------------------------------------------------------------
/lectures/res/g1-heap-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/g1-heap-structure.png
--------------------------------------------------------------------------------
/lectures/res/g1-mixed-gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/g1-mixed-gc.png
--------------------------------------------------------------------------------
/lectures/res/gen-full-gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/gen-full-gc.png
--------------------------------------------------------------------------------
/lectures/res/gen-heap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/gen-heap.png
--------------------------------------------------------------------------------
/lectures/res/gen-minor-gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/gen-minor-gc.png
--------------------------------------------------------------------------------
/lectures/res/happens-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/happens-before.png
--------------------------------------------------------------------------------
/lectures/res/install-time-perms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/install-time-perms.png
--------------------------------------------------------------------------------
/lectures/res/intents-common.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/intents-common.png
--------------------------------------------------------------------------------
/lectures/res/keeps-stopping.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/keeps-stopping.png
--------------------------------------------------------------------------------
/lectures/res/kotlin-elizarov.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/kotlin-elizarov.png
--------------------------------------------------------------------------------
/lectures/res/lab_qr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/lab_qr.png
--------------------------------------------------------------------------------
/lectures/res/layout-adaptive-breakpoints_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/layout-adaptive-breakpoints_2x.png
--------------------------------------------------------------------------------
/lectures/res/layoutparams.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/layoutparams.png
--------------------------------------------------------------------------------
/lectures/res/lifecycleowner-implementations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/lifecycleowner-implementations.png
--------------------------------------------------------------------------------
/lectures/res/navigation-graph_2x-callouts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/navigation-graph_2x-callouts.png
--------------------------------------------------------------------------------
/lectures/res/navigation-idioms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/navigation-idioms.png
--------------------------------------------------------------------------------
/lectures/res/notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/notification.png
--------------------------------------------------------------------------------
/lectures/res/observer-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/observer-diagram.png
--------------------------------------------------------------------------------
/lectures/res/observer-pattern.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/observer-pattern.gif
--------------------------------------------------------------------------------
/lectures/res/observer-sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/observer-sequence.png
--------------------------------------------------------------------------------
/lectures/res/oreo-gc-regions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/oreo-gc-regions.png
--------------------------------------------------------------------------------
/lectures/res/overview-criteria.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/overview-criteria.png
--------------------------------------------------------------------------------
/lectures/res/postfix-arithmetics.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/postfix-arithmetics.jpg
--------------------------------------------------------------------------------
/lectures/res/profiling-jug-async.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/profiling-jug-async.png
--------------------------------------------------------------------------------
/lectures/res/profiling-jug-jvisualvm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/profiling-jug-jvisualvm.png
--------------------------------------------------------------------------------
/lectures/res/profiling-jug-prog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/profiling-jug-prog.png
--------------------------------------------------------------------------------
/lectures/res/profiling-jug-safepoints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/profiling-jug-safepoints.png
--------------------------------------------------------------------------------
/lectures/res/pyramid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/pyramid.png
--------------------------------------------------------------------------------
/lectures/res/recents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/recents.png
--------------------------------------------------------------------------------
/lectures/res/res-selection-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/res-selection-flowchart.png
--------------------------------------------------------------------------------
/lectures/res/room_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/room_architecture.png
--------------------------------------------------------------------------------
/lectures/res/run-time-perms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/run-time-perms.png
--------------------------------------------------------------------------------
/lectures/res/save-restore-instance-state.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/save-restore-instance-state.png
--------------------------------------------------------------------------------
/lectures/res/service-lc-bound.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/service-lc-bound.png
--------------------------------------------------------------------------------
/lectures/res/service-lc-started.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/service-lc-started.png
--------------------------------------------------------------------------------
/lectures/res/service_binding_tree_lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/service_binding_tree_lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/service_lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/service_lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/share_via.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/share_via.png
--------------------------------------------------------------------------------
/lectures/res/storage_dataflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/storage_dataflow.png
--------------------------------------------------------------------------------
/lectures/res/storage_datamodel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/storage_datamodel.png
--------------------------------------------------------------------------------
/lectures/res/studio-profiler.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/studio-profiler.png
--------------------------------------------------------------------------------
/lectures/res/synchronizes-with.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/synchronizes-with.png
--------------------------------------------------------------------------------
/lectures/res/t-mobile-g1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/t-mobile-g1.jpg
--------------------------------------------------------------------------------
/lectures/res/task-category-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/task-category-tree.png
--------------------------------------------------------------------------------
/lectures/res/test_manifest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/test_manifest.png
--------------------------------------------------------------------------------
/lectures/res/testing-workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/testing-workflow.png
--------------------------------------------------------------------------------
/lectures/res/top-app-bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/top-app-bar.png
--------------------------------------------------------------------------------
/lectures/res/user-data-overview-permissions-flow01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/user-data-overview-permissions-flow01.jpg
--------------------------------------------------------------------------------
/lectures/res/viewgroup_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/viewgroup_2x.png
--------------------------------------------------------------------------------
/lectures/res/viewmodel-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/viewmodel-lifecycle.png
--------------------------------------------------------------------------------
/lectures/res/weak-gen-hypothesis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/weak-gen-hypothesis.png
--------------------------------------------------------------------------------
/lectures/res/x2eq25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/lectures/res/x2eq25.png
--------------------------------------------------------------------------------
/multithreading-demo.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/multithreading-demo.bundle
--------------------------------------------------------------------------------
/navigation-demo-2019.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrei-kuznetsov/android-lectures/1eb200723828d30706abb0f450956b4ab6795d80/navigation-demo-2019.bundle
--------------------------------------------------------------------------------