From 41c96a9e8d999136f87322f8b75e8cd33acd301b Mon Sep 17 00:00:00 2001 From: Jeremy Walker Date: Mon, 23 Oct 2017 15:41:14 -0700 Subject: [PATCH 01/11] Update versions of wear support library (and others) for 27.0.0 launch. Bug: 67751763 Test: Manually tested wear app samples. Change-Id: I4874f0a44698f9ceb1776737b6f478e73db49a24 --- templates/include/common.ftl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/include/common.ftl b/templates/include/common.ftl index 0467ed41..820ec0fa 100644 --- a/templates/include/common.ftl +++ b/templates/include/common.ftl @@ -80,11 +80,11 @@ <#-- Set the global build tools version --> <#assign build_tools_version='"26.0.1"'/> -<#assign play_services_version="11.4.0"/> +<#assign play_services_version="11.4.2"/> <#assign play_services_wearable_dependency="'com.google.android.gms:play-services-wearable:${play_services_version}'"/> -<#assign android_support_v13_dependency="'com.android.support:support-v13:26.1.0'"/> +<#assign android_support_v13_dependency="'com.android.support:support-v13:27.0.0'"/> -<#assign wearable_support_dependency="'com.google.android.support:wearable:2.0.5'"/> +<#assign wearable_support_dependency="'com.google.android.support:wearable:2.1.0'"/> -<#assign wearable_support_provided_dependency="'com.google.android.wearable:wearable:2.0.5'"/> +<#assign wearable_support_provided_dependency="'com.google.android.wearable:wearable:2.1.0'"/> -- GitLab From 14d387787557296021d1c15f0c39506c81813702 Mon Sep 17 00:00:00 2001 From: Jeremy Walker Date: Mon, 6 Nov 2017 14:00:10 -0800 Subject: [PATCH 02/11] Updates build script for Android 3.0. Bug: 68863906 Test: Manually tested Wear devices. Change-Id: I4c875a6d5faaac0180d9876999de54b701cf1d5e --- templates/Wear/Wearable/build.gradle.ftl | 5 +++- .../WearPlusShared/Shared/build.gradle.ftl | 5 +++- .../WearPlusShared/Wearable/build.gradle.ftl | 5 +++- .../WearPlusShared/_MODULE_/build.gradle.ftl | 5 +++- .../_MODULE_/build.gradle.ftl | 16 ++++++------ templates/base/_MODULE_/build.gradle.ftl | 25 +++++++++++-------- templates/create/_MODULE_/build.gradle.ftl | 5 +++- templates/include/common.ftl | 6 ++--- 8 files changed, 45 insertions(+), 27 deletions(-) diff --git a/templates/Wear/Wearable/build.gradle.ftl b/templates/Wear/Wearable/build.gradle.ftl index 6f8161a3..8fd1c1d1 100644 --- a/templates/Wear/Wearable/build.gradle.ftl +++ b/templates/Wear/Wearable/build.gradle.ftl @@ -15,11 +15,14 @@ --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } diff --git a/templates/WearPlusShared/Shared/build.gradle.ftl b/templates/WearPlusShared/Shared/build.gradle.ftl index 4fd221b9..45ac84f6 100644 --- a/templates/WearPlusShared/Shared/build.gradle.ftl +++ b/templates/WearPlusShared/Shared/build.gradle.ftl @@ -15,11 +15,14 @@ --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } diff --git a/templates/WearPlusShared/Wearable/build.gradle.ftl b/templates/WearPlusShared/Wearable/build.gradle.ftl index 21556857..cfef1ecc 100644 --- a/templates/WearPlusShared/Wearable/build.gradle.ftl +++ b/templates/WearPlusShared/Wearable/build.gradle.ftl @@ -15,11 +15,14 @@ --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } diff --git a/templates/WearPlusShared/_MODULE_/build.gradle.ftl b/templates/WearPlusShared/_MODULE_/build.gradle.ftl index 73ba9f2e..e02ee2ca 100644 --- a/templates/WearPlusShared/_MODULE_/build.gradle.ftl +++ b/templates/WearPlusShared/_MODULE_/build.gradle.ftl @@ -15,11 +15,14 @@ --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } diff --git a/templates/base-application/_MODULE_/build.gradle.ftl b/templates/base-application/_MODULE_/build.gradle.ftl index cb45485b..70027d60 100644 --- a/templates/base-application/_MODULE_/build.gradle.ftl +++ b/templates/base-application/_MODULE_/build.gradle.ftl @@ -22,7 +22,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } @@ -44,15 +44,15 @@ dependencies { <#if !sample.auto_add_support_lib?has_content || sample.auto_add_support_lib == "true"> <#if sample.minSdk?matches(r'^\d+$') && sample.minSdk?number < 7> - compile "com.android.support:support-v4:26.1.0" + compile "com.android.support:support-v4:27.0.0" <#elseif sample.minSdk?matches(r'^\d+$') && sample.minSdk?number < 13> - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:gridlayout-v7:26.1.0" - compile "com.android.support:cardview-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:gridlayout-v7:27.0.0" + compile "com.android.support:cardview-v7:27.0.0" <#else> - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:support-v13:26.1.0" - compile "com.android.support:cardview-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:support-v13:27.0.0" + compile "com.android.support:cardview-v7:27.0.0" diff --git a/templates/base/_MODULE_/build.gradle.ftl b/templates/base/_MODULE_/build.gradle.ftl index 175dabd6..dbc4670f 100644 --- a/templates/base/_MODULE_/build.gradle.ftl +++ b/templates/base/_MODULE_/build.gradle.ftl @@ -15,11 +15,14 @@ --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } @@ -40,18 +43,18 @@ repositories { dependencies { <#if !sample.auto_add_support_lib?has_content || sample.auto_add_support_lib == "true"> <#if sample.minSdk?matches(r'^\d+$') && sample.minSdk?number < 7> - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:appcompat-v7:27.0.0" <#elseif sample.minSdk?matches(r'^\d+$') && sample.minSdk?number < 13> - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:gridlayout-v7:26.1.0" - compile "com.android.support:cardview-v7:26.1.0" - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:gridlayout-v7:27.0.0" + compile "com.android.support:cardview-v7:27.0.0" + compile "com.android.support:appcompat-v7:27.0.0" <#else> - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:support-v13:26.1.0" - compile "com.android.support:cardview-v7:26.1.0" - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:support-v13:27.0.0" + compile "com.android.support:cardview-v7:27.0.0" + compile "com.android.support:appcompat-v7:27.0.0" <#list sample.dependency as dep> diff --git a/templates/create/_MODULE_/build.gradle.ftl b/templates/create/_MODULE_/build.gradle.ftl index 25f1e1cf..84acd3e5 100644 --- a/templates/create/_MODULE_/build.gradle.ftl +++ b/templates/create/_MODULE_/build.gradle.ftl @@ -21,11 +21,14 @@ to recognize this as an Android project and start the template engine. --> buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } diff --git a/templates/include/common.ftl b/templates/include/common.ftl index 820ec0fa..dd60cbdf 100644 --- a/templates/include/common.ftl +++ b/templates/include/common.ftl @@ -39,7 +39,7 @@ <#elseif (sample.compileSdkVersion)?has_content> <#assign compile_sdk = sample.compileSdkVersion/> <#else> - <#assign compile_sdk = "26"/> + <#assign compile_sdk = "27"/> <#-- Set the MinSDK version. This is more complicated than it should be, because the version can be either a number or a string (e.g. KeyLimePie) so we need to test @@ -78,9 +78,9 @@ <#-- Set the global build tools version --> -<#assign build_tools_version='"26.0.1"'/> +<#assign build_tools_version='"26.0.2"'/> -<#assign play_services_version="11.4.2"/> +<#assign play_services_version="11.6.0"/> <#assign play_services_wearable_dependency="'com.google.android.gms:play-services-wearable:${play_services_version}'"/> <#assign android_support_v13_dependency="'com.android.support:support-v13:27.0.0'"/> -- GitLab From 5fb44b77faf726cee7118d17b9f046216f771c22 Mon Sep 17 00:00:00 2001 From: Trevor Johns Date: Fri, 8 Dec 2017 00:34:38 -0800 Subject: [PATCH 03/11] Update presubmits for 2017-12 samples release. Bug: 70385284 Test: N/A, prebuilts Change-Id: I2a37c8753beb32bed48a7bc198723653d3597ab2 --- .../Camera2Basic/Application/build.gradle | 19 +- prebuilts/gradle/Camera2Basic/README.md | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlinApp/Application/build.gradle | 28 + .../Application/src/main/AndroidManifest.xml | 40 + .../camera2basic/ActivityExtensions.kt | 34 + .../camera2basic/AutoFitTextureView.kt | 68 ++ .../camera2basic/Camera2BasicFragment.kt | 817 ++++++++++++++++++ .../android/camera2basic/CameraActivity.kt | 32 + .../camera2basic/CompareSizesByArea.kt | 17 + .../camera2basic/ConfirmationDialog.kt | 41 + .../example/android/camera2basic/Constants.kt | 22 + .../android/camera2basic/ErrorDialog.kt | 44 + .../android/camera2basic/ImageSaver.kt | 55 ++ .../main/res/drawable-hdpi/ic_action_info.png | Bin 0 -> 1025 bytes .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 4251 bytes .../main/res/drawable-mdpi/ic_action_info.png | Bin 0 -> 665 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2622 bytes .../res/drawable-xhdpi/ic_action_info.png | Bin 0 -> 1355 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 5911 bytes .../res/drawable-xxhdpi/ic_action_info.png | Bin 0 -> 2265 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 10488 bytes .../layout-land/fragment_camera2_basic.xml | 58 ++ .../src/main/res/layout/activity_camera.xml | 22 + .../res/layout/fragment_camera2_basic.xml | 54 ++ .../src/main/res/values/colors.xml | 19 + .../src/main/res/values/dimens.xml | 5 + .../src/main/res/values/strings.xml | 32 + .../src/main/res/values/styles.xml | 20 + .../gradle/Camera2Basic/kotlinApp/CONTRIB.md | 35 + .../gradle/Camera2Basic/kotlinApp/README.md | 89 ++ .../Camera2Basic/kotlinApp/build.gradle | 22 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + .../gradle/Camera2Basic/kotlinApp/gradlew | 164 ++++ .../gradle/Camera2Basic/kotlinApp/gradlew.bat | 90 ++ .../Camera2Basic/kotlinApp/packaging.yaml | 14 + .../kotlinApp/screenshots/icon-web.png | Bin 0 -> 64937 bytes .../kotlinApp/screenshots/main.png | Bin 0 -> 1212538 bytes .../Camera2Basic/kotlinApp/settings.gradle | 1 + .../gradle/DataLayer/Application/build.gradle | 21 +- prebuilts/gradle/DataLayer/README.md | 4 +- .../gradle/DataLayer/Wearable/build.gradle | 17 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../Application/build.gradle | 19 +- .../Application/src/main/AndroidManifest.xml | 6 +- .../fingerprintdialog/MainActivity.java | 20 +- .../fingerprintdialog/SettingsActivity.java | 4 +- .../src/main/res/layout/activity_main.xml | 147 ++-- prebuilts/gradle/FingerprintDialog/README.md | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../FingerprintDialog/kotlinApp/README.md | 86 ++ .../kotlinApp/app/build.gradle | 25 + .../app/src/main/AndroidManifest.xml | 48 + .../fingerprintdialog/ActivityExtensions.kt | 24 + .../android/fingerprintdialog/Constants.kt | 26 + ...FingerprintAuthenticationDialogFragment.kt | 238 +++++ .../fingerprintdialog/FingerprintUiHelper.kt | 112 +++ .../android/fingerprintdialog/MainActivity.kt | 332 +++++++ .../fingerprintdialog/SettingsActivity.kt | 31 + .../fingerprintdialog/SettingsFragment.kt | 29 + .../src/main/res/drawable-hdpi/ic_fp_40px.png | Bin 0 -> 7011 bytes .../src/main/res/drawable-mdpi/ic_fp_40px.png | Bin 0 -> 4001 bytes .../main/res/drawable-nodpi/android_robot.png | Bin 0 -> 8288 bytes .../main/res/drawable-xhdpi/ic_fp_40px.png | Bin 0 -> 10524 bytes .../main/res/drawable-xxhdpi/ic_fp_40px.png | Bin 0 -> 18565 bytes .../main/res/drawable-xxxhdpi/ic_fp_40px.png | Bin 0 -> 16535 bytes .../app/src/main/res/drawable/card.xml | 24 + .../res/drawable/ic_fingerprint_error.xml | 28 + .../res/drawable/ic_fingerprint_success.xml | 28 + .../app/src/main/res/layout/activity_main.xml | 138 +++ .../res/layout/fingerprint_dialog_backup.xml | 78 ++ .../layout/fingerprint_dialog_container.xml | 65 ++ .../res/layout/fingerprint_dialog_content.xml | 59 ++ .../app/src/main/res/menu/menu_main.xml | 26 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3266 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2059 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4145 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6681 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9444 bytes .../app/src/main/res/values/colors.xml | 25 + .../app/src/main/res/values/dimens.xml | 35 + .../app/src/main/res/values/strings.xml | 59 ++ .../app/src/main/res/xml/preferences.xml | 23 + .../FingerprintDialog/kotlinApp/build.gradle | 22 + .../kotlinApp/gradle.properties | 18 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + .../FingerprintDialog/kotlinApp/gradlew | 164 ++++ .../FingerprintDialog/kotlinApp/gradlew.bat | 90 ++ .../kotlinApp/packaging.yaml | 23 + .../screenshots/1-purchase-screen.png | Bin 0 -> 99587 bytes .../screenshots/2-fingerprint-dialog.png | Bin 0 -> 104965 bytes .../3-fingerprint-authenticated.png | Bin 0 -> 92101 bytes .../4-new-fingerprint-enrolled.png | Bin 0 -> 103821 bytes .../kotlinApp/screenshots/big-icon.png | Bin 0 -> 35296 bytes .../kotlinApp/settings.gradle | 1 + .../JobScheduler/Application/build.gradle | 19 +- prebuilts/gradle/JobScheduler/README.md | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/JobScheduler/kotlinApp/CONTRIB.md | 35 + .../gradle/JobScheduler/kotlinApp/README.md | 60 ++ .../JobScheduler/kotlinApp/app/build.gradle | 27 + .../app/src/main/AndroidManifest.xml | 45 + .../jobscheduler/ActivityExtensions.kt | 27 + .../example/android/jobscheduler/Constants.kt | 28 + .../jobscheduler/IncomingMessageHandler.kt | 89 ++ .../android/jobscheduler/MainActivity.kt | 162 ++++ .../android/jobscheduler/MyJobService.kt | 95 ++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 4623 bytes .../app/src/main/res/drawable-hdpi/tile.9.png | Bin 0 -> 196 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2782 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 6701 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 11995 bytes .../app/src/main/res/layout/sample_main.xml | 244 ++++++ .../res/values-sw600dp/template-dimens.xml | 25 + .../res/values-sw600dp/template-styles.xml | 26 + .../app/src/main/res/values-v11/styles.xml | 28 + .../main/res/values-v11/template-styles.xml | 23 + .../app/src/main/res/values-v14/styles.xml | 29 + .../res/values-v21/base-template-styles.xml | 24 + .../app/src/main/res/values/base-strings.xml | 30 + .../app/src/main/res/values/color.xml | 22 + .../app/src/main/res/values/dimens.xml | 31 + .../app/src/main/res/values/strings.xml | 43 + .../app/src/main/res/values/styles.xml | 32 + .../src/main/res/values/template-dimens.xml | 33 + .../src/main/res/values/template-styles.xml | 43 + .../JobScheduler/kotlinApp/build.gradle | 22 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + .../gradle/JobScheduler/kotlinApp/gradlew | 164 ++++ .../gradle/JobScheduler/kotlinApp/gradlew.bat | 90 ++ .../JobScheduler/kotlinApp/packaging.yaml | 15 + .../JobScheduler/kotlinApp/settings.gradle | 1 + prebuilts/gradle/PictureInPicture/README.md | 4 +- prebuilts/gradle/PictureInPicture/app/app.iml | 116 --- .../gradle/PictureInPicture/app/build.gradle | 9 +- .../MediaSessionPlaybackActivity.java | 6 + .../pictureinpicture/widget/MovieView.java | 32 +- .../app/src/main/res/layout/activity_main.xml | 3 +- .../app/src/main/res/values/attrs.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + .../gradle/PictureInPicture/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlinApp/app/build.gradle | 9 +- .../MediaSessionPlaybackActivity.kt | 6 + .../pictureinpicture/widget/MovieView.kt | 3 + .../app/src/main/res/layout/activity_main.xml | 3 +- .../app/src/main/res/values/attrs.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + .../PictureInPicture/kotlinApp/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/WatchFace/Application/build.gradle | 25 +- prebuilts/gradle/WatchFace/README.md | 4 +- .../gradle/WatchFace/Wearable/build.gradle | 24 +- .../AnalogComplicationWatchFaceService.java | 88 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../.google/packaging.yaml | 17 + .../WearAccessibilityApp/CONTRIBUTING.md | 35 + prebuilts/gradle/WearAccessibilityApp/LICENSE | 647 ++++++++++++++ prebuilts/gradle/WearAccessibilityApp/NOTICE | 16 + .../gradle/WearAccessibilityApp/README.md | 68 ++ .../Wearable/build.gradle | 84 ++ .../Wearable/src/main/AndroidManifest.xml | 108 +++ .../AccessibilityActivity.java | 49 ++ .../wear/wearaccessibilityapp/AppItem.java | 58 ++ .../AppItemListViewAdapter.java | 64 ++ .../CircledImageViewPreference.java | 106 +++ .../ControlsActivity.java | 43 + .../wearaccessibilityapp/DialogsActivity.java | 181 ++++ .../wearaccessibilityapp/DialogsItem.java | 38 + .../FullScreenActivity.java | 28 + .../GlobalNotificationBuilder.java | 60 ++ .../wearaccessibilityapp/ImagesActivity.java | 64 ++ .../wearaccessibilityapp/InLineActivity.java | 84 ++ .../wear/wearaccessibilityapp/Item.java | 20 + .../ListOfGraphicsActivity.java | 76 ++ .../wearaccessibilityapp/ListViewAdapter.java | 61 ++ .../wearaccessibilityapp/ListsActivity.java | 68 ++ .../wear/wearaccessibilityapp/ListsItem.java | 38 + .../LongListActivity.java | 180 ++++ .../LongListRecyclerViewAdapter.java | 168 ++++ .../wearaccessibilityapp/MainActivity.java | 70 ++ .../MenuRecyclerViewAdapter.java | 99 +++ .../MessagingIntentService.java | 239 +++++ .../MessagingMainActivity.java | 40 + .../wearaccessibilityapp/MockDatabase.java | 141 +++ .../MyLauncherChildLayoutManager.java | 49 ++ .../NotificationsActivity.java | 253 ++++++ .../OpenOnPhoneAnimationActivity.java | 56 ++ .../PhotoCarouselActivity.java | 56 ++ .../ProgressActivity.java | 68 ++ .../ProgressBarPreference.java | 42 + .../RadioListActivity.java | 32 + .../SampleAppConstants.java | 39 + .../ZoomImageActivity.java | 40 + ...e_left_long_g_animation_interpolator_0.xml | 19 + ...e_left_long_g_animation_interpolator_1.xml | 19 + ..._left_long_g_animation_interpolator_10.xml | 19 + ..._left_long_g_animation_interpolator_11.xml | 19 + ..._left_long_g_animation_interpolator_12.xml | 19 + ...e_left_long_g_animation_interpolator_2.xml | 19 + ...e_left_long_g_animation_interpolator_3.xml | 19 + ...e_left_long_g_animation_interpolator_4.xml | 19 + ...e_left_long_g_animation_interpolator_5.xml | 19 + ...e_left_long_g_animation_interpolator_6.xml | 19 + ...e_left_long_g_animation_interpolator_7.xml | 19 + ...e_left_long_g_animation_interpolator_8.xml | 19 + ...e_left_long_g_animation_interpolator_9.xml | 19 + ..._swipe_left_long_g_ellipse_7_animation.xml | 67 ++ ..._swipe_left_long_g_ellipse_8_animation.xml | 67 ++ ...obe_swipe_left_long_g_path_7_animation.xml | 81 ++ ...obe_swipe_left_long_g_path_8_animation.xml | 88 ++ ...t_long_g_swipeupbluecircle_2_animation.xml | 36 + ...e_left_long_g_swipeuptrace_2_animation.xml | 36 + .../oobe_tap_animation_interpolator_0.xml | 19 + .../oobe_tap_animation_interpolator_1.xml | 19 + .../oobe_tap_animation_interpolator_2.xml | 19 + .../oobe_tap_animation_interpolator_3.xml | 19 + .../oobe_tap_animation_interpolator_4.xml | 19 + .../oobe_tap_animation_interpolator_5.xml | 19 + .../oobe_tap_animation_interpolator_6.xml | 19 + .../anim/oobe_tap_ellipse_21_animation.xml | 67 ++ .../anim/oobe_tap_ellipse_22_animation.xml | 67 ++ .../res/anim/oobe_tap_path_23_animation.xml | 43 + .../res/anim/oobe_tap_path_24_animation.xml | 43 + .../oobe_tap_rectangle_path_3_animation.xml | 60 ++ .../src/main/res/drawable/accept_circle.xml | 38 + .../res/drawable/accessibility_circle.xml | 40 + .../Wearable/src/main/res/drawable/arrow.xml | 25 + .../src/main/res/drawable/arrow_circle.xml | 38 + .../Wearable/src/main/res/drawable/avatar.png | Bin 0 -> 65340 bytes .../Wearable/src/main/res/drawable/birds.png | Bin 0 -> 121238 bytes .../Wearable/src/main/res/drawable/bow.png | Bin 0 -> 128450 bytes .../Wearable/src/main/res/drawable/cats.png | Bin 0 -> 119730 bytes .../Wearable/src/main/res/drawable/circle.xml | 24 + .../src/main/res/drawable/controls_circle.xml | 39 + .../src/main/res/drawable/deny_circle.xml | 39 + .../src/main/res/drawable/dialogs_circle.xml | 39 + .../Wearable/src/main/res/drawable/dog.png | Bin 0 -> 95637 bytes .../src/main/res/drawable/hamster.png | Bin 0 -> 99954 bytes .../Wearable/src/main/res/drawable/heart.xml | 27 + .../src/main/res/drawable/heart_circle.xml | 30 + .../ic_view_list_white_1x_web_48dp.png | Bin 0 -> 94 bytes .../src/main/res/drawable/launcher_image.xml | 41 + .../src/main/res/drawable/list_arrow.xml | 25 + .../src/main/res/drawable/lists_circle.xml | 56 ++ .../res/drawable/notifications_circle.xml | 41 + .../res/drawable/oobe_swipe_left_long.xml | 72 ++ .../oobe_swipe_left_long_animation.xml | 38 + .../src/main/res/drawable/oobe_tap.xml | 105 +++ .../main/res/drawable/oobe_tap_animation.xml | 35 + .../res/drawable/open_in_phone_circle.xml | 43 + .../src/main/res/drawable/open_on_phone.xml | 77 ++ .../src/main/res/drawable/progress_circle.xml | 39 + .../Wearable/src/main/res/drawable/reply.xml | 26 + .../src/main/res/drawable/settings_circle.xml | 50 ++ .../Wearable/src/main/res/drawable/start.xml | 25 + .../Wearable/src/main/res/drawable/stop.xml | 26 + .../Wearable/src/main/res/drawable/watch.png | Bin 0 -> 781 bytes .../res/layout/activity_accessibility.xml | 60 ++ .../src/main/res/layout/activity_dialogs.xml | 24 + .../layout/activity_fullscreen_progress.xml | 36 + .../src/main/res/layout/activity_images.xml | 108 +++ .../res/layout/activity_list_of_graphics.xml | 27 + .../src/main/res/layout/activity_lists.xml | 24 + .../main/res/layout/activity_long_list.xml | 41 + .../src/main/res/layout/activity_main.xml | 24 + .../res/layout/activity_messaging_main.xml | 26 + .../res/layout/activity_notifications.xml | 53 ++ .../activity_open_on_phone_animation.xml | 43 + .../res/layout/activity_photo_carousel.xml | 75 ++ .../main/res/layout/activity_radio_list.xml | 62 ++ .../main/res/layout/activity_zoom_image.xml | 24 + .../src/main/res/layout/app_item_layout.xml | 36 + .../main/res/layout/circled_image_layout.xml | 39 + .../main/res/layout/header_footer_layout.xml | 19 + .../src/main/res/layout/list_item_layout.xml | 37 + .../layout/long_list_switch_widget_layout.xml | 43 + .../main/res/layout/progress_bar_layout.xml | 23 + .../layout/progress_bar_with_text_layout.xml | 36 + .../res/layout/shifted_app_item_layout.xml | 37 + .../src/main/res/layout/switch_layout.xml | 40 + .../src/main/res/layout/title_layout.xml | 25 + .../src/main/res/menu/action_drawer_menu.xml | 32 + .../Wearable/src/main/res/values/colors.xml | 22 + .../Wearable/src/main/res/values/strings.xml | 118 +++ .../Wearable/src/main/res/values/styles.xml | 35 + .../src/main/res/xml/prefs_controls.xml | 34 + .../main/res/xml/prefs_in_line_progress.xml | 27 + .../src/main/res/xml/prefs_notifications.xml | 30 + .../gradle/WearAccessibilityApp/build.gradle | 12 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + prebuilts/gradle/WearAccessibilityApp/gradlew | 164 ++++ .../gradle/WearAccessibilityApp/gradlew.bat | 90 ++ .../WearAccessibilityApp/settings.gradle | 2 + .../Application/build.gradle | 22 +- .../gradle/WearVerifyRemoteApp/README.md | 4 +- .../WearVerifyRemoteApp/Wearable/build.gradle | 20 +- .../wearverifyremoteapp/MainWearActivity.java | 67 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 303 files changed, 12723 insertions(+), 420 deletions(-) create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/build.gradle create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/AndroidManifest.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ActivityExtensions.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/AutoFitTextureView.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CameraActivity.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CompareSizesByArea.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ConfirmationDialog.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Constants.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ErrorDialog.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ImageSaver.kt create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-hdpi/ic_action_info.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-mdpi/ic_action_info.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-xhdpi/ic_action_info.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-xxhdpi/ic_action_info.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/layout-land/fragment_camera2_basic.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/layout/activity_camera.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/layout/fragment_camera2_basic.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/values/colors.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/values/dimens.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/values/strings.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/values/styles.xml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/CONTRIB.md create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/README.md create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/build.gradle create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/gradle/wrapper/gradle-wrapper.jar create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/gradle/wrapper/gradle-wrapper.properties create mode 100755 prebuilts/gradle/Camera2Basic/kotlinApp/gradlew create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/gradlew.bat create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/packaging.yaml create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/screenshots/icon-web.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/screenshots/main.png create mode 100644 prebuilts/gradle/Camera2Basic/kotlinApp/settings.gradle create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/README.md create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/build.gradle create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/AndroidManifest.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/ActivityExtensions.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/Constants.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/FingerprintAuthenticationDialogFragment.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/MainActivity.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/SettingsActivity.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/java/com/example/android/fingerprintdialog/SettingsFragment.kt create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-hdpi/ic_fp_40px.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-mdpi/ic_fp_40px.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-nodpi/android_robot.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-xhdpi/ic_fp_40px.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable/card.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable/ic_fingerprint_error.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/drawable/ic_fingerprint_success.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/layout/activity_main.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/layout/fingerprint_dialog_backup.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/layout/fingerprint_dialog_container.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/layout/fingerprint_dialog_content.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/menu/menu_main.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/values/colors.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/values/dimens.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/values/strings.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/app/src/main/res/xml/preferences.xml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/build.gradle create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/gradle.properties create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/gradle/wrapper/gradle-wrapper.jar create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/gradle/wrapper/gradle-wrapper.properties create mode 100755 prebuilts/gradle/FingerprintDialog/kotlinApp/gradlew create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/gradlew.bat create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/packaging.yaml create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/screenshots/1-purchase-screen.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/screenshots/2-fingerprint-dialog.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/screenshots/3-fingerprint-authenticated.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/screenshots/4-new-fingerprint-enrolled.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/screenshots/big-icon.png create mode 100644 prebuilts/gradle/FingerprintDialog/kotlinApp/settings.gradle create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/CONTRIB.md create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/README.md create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/build.gradle create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/AndroidManifest.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/java/com/example/android/jobscheduler/ActivityExtensions.kt create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/java/com/example/android/jobscheduler/Constants.kt create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/java/com/example/android/jobscheduler/IncomingMessageHandler.kt create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/java/com/example/android/jobscheduler/MainActivity.kt create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/java/com/example/android/jobscheduler/MyJobService.kt create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/drawable-hdpi/tile.9.png create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/layout/sample_main.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-sw600dp/template-dimens.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-sw600dp/template-styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-v11/styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-v11/template-styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-v14/styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values-v21/base-template-styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/base-strings.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/color.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/dimens.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/strings.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/template-dimens.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/app/src/main/res/values/template-styles.xml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/build.gradle create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/gradle/wrapper/gradle-wrapper.jar create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/gradle/wrapper/gradle-wrapper.properties create mode 100755 prebuilts/gradle/JobScheduler/kotlinApp/gradlew create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/gradlew.bat create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/packaging.yaml create mode 100644 prebuilts/gradle/JobScheduler/kotlinApp/settings.gradle delete mode 100644 prebuilts/gradle/PictureInPicture/app/app.iml create mode 100644 prebuilts/gradle/WearAccessibilityApp/.google/packaging.yaml create mode 100644 prebuilts/gradle/WearAccessibilityApp/CONTRIBUTING.md create mode 100644 prebuilts/gradle/WearAccessibilityApp/LICENSE create mode 100644 prebuilts/gradle/WearAccessibilityApp/NOTICE create mode 100644 prebuilts/gradle/WearAccessibilityApp/README.md create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/build.gradle create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/AndroidManifest.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/AccessibilityActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/AppItem.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/AppItemListViewAdapter.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/CircledImageViewPreference.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ControlsActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/DialogsActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/DialogsItem.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/FullScreenActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/GlobalNotificationBuilder.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ImagesActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/InLineActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/Item.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ListOfGraphicsActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ListViewAdapter.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ListsActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ListsItem.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/LongListActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/LongListRecyclerViewAdapter.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MainActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MenuRecyclerViewAdapter.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MessagingIntentService.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MessagingMainActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MockDatabase.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/MyLauncherChildLayoutManager.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/NotificationsActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/OpenOnPhoneAnimationActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/PhotoCarouselActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ProgressActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ProgressBarPreference.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/RadioListActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/SampleAppConstants.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/java/com/example/android/wearable/wear/wearaccessibilityapp/ZoomImageActivity.java create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_0.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_1.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_10.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_11.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_12.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_2.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_3.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_4.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_5.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_6.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_7.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_8.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_animation_interpolator_9.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_ellipse_7_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_ellipse_8_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_path_7_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_path_8_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_swipeupbluecircle_2_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_swipe_left_long_g_swipeuptrace_2_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_0.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_1.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_2.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_3.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_4.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_5.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_animation_interpolator_6.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_ellipse_21_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_ellipse_22_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_path_23_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_path_24_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/anim/oobe_tap_rectangle_path_3_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/accept_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/accessibility_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/arrow.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/arrow_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/avatar.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/birds.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/bow.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/cats.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/controls_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/deny_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/dialogs_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/dog.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/hamster.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/heart.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/heart_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/ic_view_list_white_1x_web_48dp.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/launcher_image.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/list_arrow.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/lists_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/notifications_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/oobe_swipe_left_long.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/oobe_swipe_left_long_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/oobe_tap.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/oobe_tap_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/open_in_phone_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/open_on_phone.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/progress_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/reply.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/settings_circle.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/start.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/stop.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/drawable/watch.png create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_accessibility.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_dialogs.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_fullscreen_progress.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_images.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_list_of_graphics.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_lists.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_long_list.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_main.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_messaging_main.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_notifications.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_open_on_phone_animation.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_photo_carousel.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_radio_list.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/activity_zoom_image.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/app_item_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/circled_image_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/header_footer_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/list_item_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/long_list_switch_widget_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/progress_bar_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/progress_bar_with_text_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/shifted_app_item_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/switch_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/layout/title_layout.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/menu/action_drawer_menu.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/values/colors.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/values/strings.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/values/styles.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/xml/prefs_controls.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/xml/prefs_in_line_progress.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/Wearable/src/main/res/xml/prefs_notifications.xml create mode 100644 prebuilts/gradle/WearAccessibilityApp/build.gradle create mode 100644 prebuilts/gradle/WearAccessibilityApp/gradle/wrapper/gradle-wrapper.jar create mode 100644 prebuilts/gradle/WearAccessibilityApp/gradle/wrapper/gradle-wrapper.properties create mode 100755 prebuilts/gradle/WearAccessibilityApp/gradlew create mode 100644 prebuilts/gradle/WearAccessibilityApp/gradlew.bat create mode 100644 prebuilts/gradle/WearAccessibilityApp/settings.gradle diff --git a/prebuilts/gradle/Camera2Basic/Application/build.gradle b/prebuilts/gradle/Camera2Basic/Application/build.gradle index e5ed7ff9..2438762a 100644 --- a/prebuilts/gradle/Camera2Basic/Application/build.gradle +++ b/prebuilts/gradle/Camera2Basic/Application/build.gradle @@ -1,11 +1,14 @@ buildscript { repositories { + maven { + url 'https://maven.google.com' + } jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' } } @@ -19,10 +22,10 @@ repositories { } dependencies { - compile "com.android.support:support-v4:26.1.0" - compile "com.android.support:support-v13:26.1.0" - compile "com.android.support:cardview-v7:26.1.0" - compile "com.android.support:appcompat-v7:26.1.0" + compile "com.android.support:support-v4:27.0.0" + compile "com.android.support:support-v13:27.0.0" + compile "com.android.support:cardview-v7:27.0.0" + compile "com.android.support:appcompat-v7:27.0.0" } // The sample build uses multiple directories to @@ -35,13 +38,13 @@ List dirs = [ android { - compileSdkVersion 26 + compileSdkVersion 27 - buildToolsVersion "26.0.1" + buildToolsVersion "26.0.2" defaultConfig { minSdkVersion 21 - targetSdkVersion 26 + targetSdkVersion 27 } compileOptions { diff --git a/prebuilts/gradle/Camera2Basic/README.md b/prebuilts/gradle/Camera2Basic/README.md index 0dc75294..2293c93e 100644 --- a/prebuilts/gradle/Camera2Basic/README.md +++ b/prebuilts/gradle/Camera2Basic/README.md @@ -42,8 +42,8 @@ when you are done. Pre-requisites -------------- -- Android SDK 26 -- Android Build Tools v26.0.1 +- Android SDK 27 +- Android Build Tools v26.0.2 - Android Support Repository Screenshots diff --git a/prebuilts/gradle/Camera2Basic/gradle/wrapper/gradle-wrapper.properties b/prebuilts/gradle/Camera2Basic/gradle/wrapper/gradle-wrapper.properties index 4da4a580..86fc139a 100644 --- a/prebuilts/gradle/Camera2Basic/gradle/wrapper/gradle-wrapper.properties +++ b/prebuilts/gradle/Camera2Basic/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip \ No newline at end of file +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip \ No newline at end of file diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/build.gradle b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/build.gradle new file mode 100644 index 00000000..c30a09af --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 26 + buildToolsVersion '26.0.2' + defaultConfig { + applicationId "com.example.android.camera2basic" + minSdkVersion 21 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation "com.android.support:appcompat-v7:26.1.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/AndroidManifest.xml b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/AndroidManifest.xml new file mode 100644 index 00000000..5b0b5b04 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ActivityExtensions.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ActivityExtensions.kt new file mode 100644 index 00000000..14dcfa70 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ActivityExtensions.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.support.v4.app.FragmentActivity +import android.support.v4.content.ContextCompat +import android.widget.Toast + +/** + * This file illustrates Kotlin's Extension Functions by extending FragmentActivity. + */ + +/** + * Shows a [Toast] on the UI thread. + * + * @param text The message to show + */ +fun FragmentActivity.showToast(text: String) { + runOnUiThread { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() } +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/AutoFitTextureView.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/AutoFitTextureView.kt new file mode 100644 index 00000000..8214557f --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/AutoFitTextureView.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.content.Context +import android.util.AttributeSet +import android.view.TextureView +import android.view.View + +/** + * A [TextureView] that can be adjusted to a specified aspect ratio. + */ +class AutoFitTextureView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0 +) : TextureView(context, attrs, defStyle) { + + private var ratioWidth = 0 + private var ratioHeight = 0 + + /** + * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio + * calculated from the parameters. Note that the actual sizes of parameters don't matter, that + * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. + * + * @param width Relative horizontal size + * @param height Relative vertical size + */ + fun setAspectRatio(width: Int, height: Int) { + if (width < 0 || height < 0) { + throw IllegalArgumentException("Size cannot be negative.") + } + ratioWidth = width + ratioHeight = height + requestLayout() + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val width = View.MeasureSpec.getSize(widthMeasureSpec) + val height = View.MeasureSpec.getSize(heightMeasureSpec) + if (ratioWidth == 0 || ratioHeight == 0) { + setMeasuredDimension(width, height) + } else { + if (width < height * ratioWidth / ratioHeight) { + setMeasuredDimension(width, width * ratioHeight / ratioWidth) + } else { + setMeasuredDimension(height * ratioWidth / ratioHeight, height) + } + } + } + +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.kt new file mode 100644 index 00000000..c55df1b9 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.kt @@ -0,0 +1,817 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.Manifest +import android.app.AlertDialog +import android.content.Context +import android.content.pm.PackageManager +import android.content.res.Configuration +import android.graphics.ImageFormat +import android.graphics.Matrix +import android.graphics.Point +import android.graphics.RectF +import android.graphics.SurfaceTexture +import android.hardware.camera2.CameraAccessException +import android.hardware.camera2.CameraCaptureSession +import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraDevice +import android.hardware.camera2.CameraManager +import android.hardware.camera2.CameraMetadata +import android.hardware.camera2.CaptureRequest +import android.hardware.camera2.CaptureResult +import android.hardware.camera2.TotalCaptureResult +import android.media.ImageReader +import android.os.Bundle +import android.os.Handler +import android.os.HandlerThread +import android.support.v4.app.ActivityCompat +import android.support.v4.app.Fragment +import android.support.v4.content.ContextCompat +import android.util.Log +import android.util.Size +import android.util.SparseIntArray +import android.view.LayoutInflater +import android.view.Surface +import android.view.TextureView +import android.view.View +import android.view.ViewGroup +import java.io.File +import java.util.Arrays +import java.util.Collections +import java.util.concurrent.Semaphore +import java.util.concurrent.TimeUnit +import kotlin.collections.ArrayList + +class Camera2BasicFragment : Fragment(), View.OnClickListener, + ActivityCompat.OnRequestPermissionsResultCallback { + + /** + * [TextureView.SurfaceTextureListener] handles several lifecycle events on a + * [TextureView]. + */ + private val surfaceTextureListener = object : TextureView.SurfaceTextureListener { + + override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { + openCamera(width, height) + } + + override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) { + configureTransform(width, height) + } + + override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) = true + + override fun onSurfaceTextureUpdated(texture: SurfaceTexture) = Unit + + } + + /** + * ID of the current [CameraDevice]. + */ + private lateinit var cameraId: String + + /** + * An [AutoFitTextureView] for camera preview. + */ + private lateinit var textureView: AutoFitTextureView + + /** + * A [CameraCaptureSession] for camera preview. + */ + private var captureSession: CameraCaptureSession? = null + + /** + * A reference to the opened [CameraDevice]. + */ + private var cameraDevice: CameraDevice? = null + + /** + * The [android.util.Size] of camera preview. + */ + private lateinit var previewSize: Size + + /** + * [CameraDevice.StateCallback] is called when [CameraDevice] changes its state. + */ + private val stateCallback = object : CameraDevice.StateCallback() { + + override fun onOpened(cameraDevice: CameraDevice) { + cameraOpenCloseLock.release() + this@Camera2BasicFragment.cameraDevice = cameraDevice + createCameraPreviewSession() + } + + override fun onDisconnected(cameraDevice: CameraDevice) { + cameraOpenCloseLock.release() + cameraDevice.close() + this@Camera2BasicFragment.cameraDevice = null + } + + override fun onError(cameraDevice: CameraDevice, error: Int) { + onDisconnected(cameraDevice) + this@Camera2BasicFragment.activity?.finish() + } + + } + + /** + * An additional thread for running tasks that shouldn't block the UI. + */ + private var backgroundThread: HandlerThread? = null + + /** + * A [Handler] for running tasks in the background. + */ + private var backgroundHandler: Handler? = null + + /** + * An [ImageReader] that handles still image capture. + */ + private var imageReader: ImageReader? = null + + /** + * This is the output file for our picture. + */ + private lateinit var file: File + + /** + * This a callback object for the [ImageReader]. "onImageAvailable" will be called when a + * still image is ready to be saved. + */ + private val onImageAvailableListener = ImageReader.OnImageAvailableListener { + backgroundHandler?.post(ImageSaver(it.acquireNextImage(), file)) + } + + /** + * [CaptureRequest.Builder] for the camera preview + */ + private lateinit var previewRequestBuilder: CaptureRequest.Builder + + /** + * [CaptureRequest] generated by [.previewRequestBuilder] + */ + private lateinit var previewRequest: CaptureRequest + + /** + * The current state of camera state for taking pictures. + * + * @see .captureCallback + */ + private var state = STATE_PREVIEW + + /** + * A [Semaphore] to prevent the app from exiting before closing the camera. + */ + private val cameraOpenCloseLock = Semaphore(1) + + /** + * Whether the current camera device supports Flash or not. + */ + private var flashSupported = false + + /** + * Orientation of the camera sensor + */ + private var sensorOrientation = 0 + + /** + * A [CameraCaptureSession.CaptureCallback] that handles events related to JPEG capture. + */ + private val captureCallback = object : CameraCaptureSession.CaptureCallback() { + + private fun process(result: CaptureResult) { + when (state) { + STATE_PREVIEW -> Unit // Do nothing when the camera preview is working normally. + STATE_WAITING_LOCK -> capturePicture(result) + STATE_WAITING_PRECAPTURE -> { + // CONTROL_AE_STATE can be null on some devices + val aeState = result.get(CaptureResult.CONTROL_AE_STATE) + if (aeState == null || + aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || + aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) { + state = STATE_WAITING_NON_PRECAPTURE + } + } + STATE_WAITING_NON_PRECAPTURE -> { + // CONTROL_AE_STATE can be null on some devices + val aeState = result.get(CaptureResult.CONTROL_AE_STATE) + if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { + state = STATE_PICTURE_TAKEN + captureStillPicture() + } + } + } + } + + private fun capturePicture(result: CaptureResult) { + val afState = result.get(CaptureResult.CONTROL_AF_STATE) + if (afState == null) { + captureStillPicture() + } else if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED + || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) { + // CONTROL_AE_STATE can be null on some devices + val aeState = result.get(CaptureResult.CONTROL_AE_STATE) + if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) { + state = STATE_PICTURE_TAKEN + captureStillPicture() + } else { + runPrecaptureSequence() + } + } + } + + override fun onCaptureProgressed(session: CameraCaptureSession, + request: CaptureRequest, + partialResult: CaptureResult) { + process(partialResult) + } + + override fun onCaptureCompleted(session: CameraCaptureSession, + request: CaptureRequest, + result: TotalCaptureResult) { + process(result) + } + + } + + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? = inflater.inflate(R.layout.fragment_camera2_basic, container, false) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + view.findViewById(R.id.picture).setOnClickListener(this) + view.findViewById(R.id.info).setOnClickListener(this) + textureView = view.findViewById(R.id.texture) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + file = File(activity.getExternalFilesDir(null), PIC_FILE_NAME) + } + + override fun onResume() { + super.onResume() + startBackgroundThread() + + // When the screen is turned off and turned back on, the SurfaceTexture is already + // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open + // a camera and start preview from here (otherwise, we wait until the surface is ready in + // the SurfaceTextureListener). + if (textureView.isAvailable) { + openCamera(textureView.width, textureView.height) + } else { + textureView.surfaceTextureListener = surfaceTextureListener + } + } + + override fun onPause() { + closeCamera() + stopBackgroundThread() + super.onPause() + } + + private fun requestCameraPermission() { + if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { + ConfirmationDialog().show(childFragmentManager, FRAGMENT_DIALOG) + } else { + requestPermissions(arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION) + } + } + + override fun onRequestPermissionsResult(requestCode: Int, + permissions: Array, + grantResults: IntArray) { + if (requestCode == REQUEST_CAMERA_PERMISSION) { + if (grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { + ErrorDialog.newInstance(getString(R.string.request_permission)) + .show(childFragmentManager, FRAGMENT_DIALOG) + } + } else { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + } + + /** + * Sets up member variables related to camera. + * + * @param width The width of available size for camera preview + * @param height The height of available size for camera preview + */ + private fun setUpCameraOutputs(width: Int, height: Int) { + val manager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager + try { + for (cameraId in manager.cameraIdList) { + val characteristics = manager.getCameraCharacteristics(cameraId) + + // We don't use a front facing camera in this sample. + val cameraDirection = characteristics.get(CameraCharacteristics.LENS_FACING) + if (cameraDirection != null && + cameraDirection == CameraCharacteristics.LENS_FACING_FRONT) { + continue + } + + val map = characteristics.get( + CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue + + // For still image captures, we use the largest available size. + val largest = Collections.max( + Arrays.asList(*map.getOutputSizes(ImageFormat.JPEG)), + CompareSizesByArea()) + imageReader = ImageReader.newInstance(largest.width, largest.height, + ImageFormat.JPEG, /*maxImages*/ 2).apply { + setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) + } + + // Find out if we need to swap dimension to get the preview size relative to sensor + // coordinate. + val displayRotation = activity.windowManager.defaultDisplay.rotation + + sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION) + val swappedDimensions = areDimensionsSwapped(displayRotation) + + val displaySize = Point() + activity.windowManager.defaultDisplay.getSize(displaySize) + val rotatedPreviewWidth = if (swappedDimensions) height else width + val rotatedPreviewHeight = if (swappedDimensions) width else height + var maxPreviewWidth = if (swappedDimensions) displaySize.y else displaySize.x + var maxPreviewHeight = if (swappedDimensions) displaySize.x else displaySize.y + + if (maxPreviewWidth > MAX_PREVIEW_WIDTH) maxPreviewWidth = MAX_PREVIEW_WIDTH + if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) maxPreviewHeight = MAX_PREVIEW_HEIGHT + + // Danger, W.R.! Attempting to use too large a preview size could exceed the camera + // bus' bandwidth limitation, resulting in gorgeous previews but the storage of + // garbage capture data. + previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture::class.java), + rotatedPreviewWidth, rotatedPreviewHeight, + maxPreviewWidth, maxPreviewHeight, + largest) + + // We fit the aspect ratio of TextureView to the size of preview we picked. + if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + textureView.setAspectRatio(previewSize.width, previewSize.height) + } else { + textureView.setAspectRatio(previewSize.height, previewSize.width) + } + + // Check if the flash is supported. + flashSupported = + characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE) == true + + this.cameraId = cameraId + + // We've found a viable camera and finished setting up member variables, + // so we don't need to iterate through other available cameras. + return + } + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } catch (e: NullPointerException) { + // Currently an NPE is thrown when the Camera2API is used but not supported on the + // device this code runs. + ErrorDialog.newInstance(getString(R.string.camera_error)) + .show(childFragmentManager, FRAGMENT_DIALOG) + } + + } + + /** + * Determines if the dimensions are swapped given the phone's current rotation. + * + * @param displayRotation The current rotation of the display + * + * @return true if the dimensions are swapped, false otherwise. + */ + private fun areDimensionsSwapped(displayRotation: Int): Boolean { + var swappedDimensions = false + when (displayRotation) { + Surface.ROTATION_0, Surface.ROTATION_180 -> { + if (sensorOrientation == 90 || sensorOrientation == 270) { + swappedDimensions = true + } + } + Surface.ROTATION_90, Surface.ROTATION_270 -> { + if (sensorOrientation == 0 || sensorOrientation == 180) { + swappedDimensions = true + } + } + else -> { + Log.e(TAG, "Display rotation is invalid: $displayRotation") + } + } + return swappedDimensions + } + + /** + * Opens the camera specified by [Camera2BasicFragment.cameraId]. + */ + private fun openCamera(width: Int, height: Int) { + val permission = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) + if (permission != PackageManager.PERMISSION_GRANTED) { + requestCameraPermission() + return + } + setUpCameraOutputs(width, height) + configureTransform(width, height) + val manager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager + try { + // Wait for camera to open - 2.5 seconds is sufficient + if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { + throw RuntimeException("Time out waiting to lock camera opening.") + } + manager.openCamera(cameraId, stateCallback, backgroundHandler) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } catch (e: InterruptedException) { + throw RuntimeException("Interrupted while trying to lock camera opening.", e) + } + + } + + /** + * Closes the current [CameraDevice]. + */ + private fun closeCamera() { + try { + cameraOpenCloseLock.acquire() + captureSession?.close() + captureSession = null + cameraDevice?.close() + cameraDevice = null + imageReader?.close() + imageReader = null + } catch (e: InterruptedException) { + throw RuntimeException("Interrupted while trying to lock camera closing.", e) + } finally { + cameraOpenCloseLock.release() + } + } + + /** + * Starts a background thread and its [Handler]. + */ + private fun startBackgroundThread() { + backgroundThread = HandlerThread("CameraBackground").also { it.start() } + backgroundHandler = Handler(backgroundThread?.looper) + } + + /** + * Stops the background thread and its [Handler]. + */ + private fun stopBackgroundThread() { + backgroundThread?.quitSafely() + try { + backgroundThread?.join() + backgroundThread = null + backgroundHandler = null + } catch (e: InterruptedException) { + Log.e(TAG, e.toString()) + } + + } + + /** + * Creates a new [CameraCaptureSession] for camera preview. + */ + private fun createCameraPreviewSession() { + try { + val texture = textureView.surfaceTexture + + // We configure the size of default buffer to be the size of camera preview we want. + texture.setDefaultBufferSize(previewSize.width, previewSize.height) + + // This is the output Surface we need to start preview. + val surface = Surface(texture) + + // We set up a CaptureRequest.Builder with the output Surface. + previewRequestBuilder = cameraDevice!!.createCaptureRequest( + CameraDevice.TEMPLATE_PREVIEW + ) + previewRequestBuilder.addTarget(surface) + + // Here, we create a CameraCaptureSession for camera preview. + cameraDevice?.createCaptureSession(Arrays.asList(surface, imageReader?.surface), + object : CameraCaptureSession.StateCallback() { + + override fun onConfigured(cameraCaptureSession: CameraCaptureSession) { + // The camera is already closed + if (cameraDevice == null) return + + // When the session is ready, we start displaying the preview. + captureSession = cameraCaptureSession + try { + // Auto focus should be continuous for camera preview. + previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, + CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) + // Flash is automatically enabled when necessary. + setAutoFlash(previewRequestBuilder) + + // Finally, we start displaying the camera preview. + previewRequest = previewRequestBuilder.build() + captureSession?.setRepeatingRequest(previewRequest, + captureCallback, backgroundHandler) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + override fun onConfigureFailed(session: CameraCaptureSession) { + activity.showToast("Failed") + } + }, null) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + /** + * Configures the necessary [android.graphics.Matrix] transformation to `textureView`. + * This method should be called after the camera preview size is determined in + * setUpCameraOutputs and also the size of `textureView` is fixed. + * + * @param viewWidth The width of `textureView` + * @param viewHeight The height of `textureView` + */ + private fun configureTransform(viewWidth: Int, viewHeight: Int) { + activity ?: return + val rotation = activity.windowManager.defaultDisplay.rotation + val matrix = Matrix() + val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat()) + val bufferRect = RectF(0f, 0f, previewSize.height.toFloat(), previewSize.width.toFloat()) + val centerX = viewRect.centerX() + val centerY = viewRect.centerY() + + if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { + bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()) + val scale = Math.max( + viewHeight.toFloat() / previewSize.height, + viewWidth.toFloat() / previewSize.width) + with(matrix) { + setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL) + postScale(scale, scale, centerX, centerY) + postRotate((90 * (rotation - 2)).toFloat(), centerX, centerY) + } + } else if (Surface.ROTATION_180 == rotation) { + matrix.postRotate(180f, centerX, centerY) + } + textureView.setTransform(matrix) + } + + /** + * Lock the focus as the first step for a still image capture. + */ + private fun lockFocus() { + try { + // This is how to tell the camera to lock focus. + previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, + CameraMetadata.CONTROL_AF_TRIGGER_START) + // Tell #captureCallback to wait for the lock. + state = STATE_WAITING_LOCK + captureSession?.capture(previewRequestBuilder.build(), captureCallback, + backgroundHandler) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + /** + * Run the precapture sequence for capturing a still image. This method should be called when + * we get a response in [.captureCallback] from [.lockFocus]. + */ + private fun runPrecaptureSequence() { + try { + // This is how to tell the camera to trigger. + previewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, + CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START) + // Tell #captureCallback to wait for the precapture sequence to be set. + state = STATE_WAITING_PRECAPTURE + captureSession?.capture(previewRequestBuilder.build(), captureCallback, + backgroundHandler) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + /** + * Capture a still picture. This method should be called when we get a response in + * [.captureCallback] from both [.lockFocus]. + */ + private fun captureStillPicture() { + try { + if (activity == null || cameraDevice == null) return + val rotation = activity.windowManager.defaultDisplay.rotation + + // This is the CaptureRequest.Builder that we use to take a picture. + val captureBuilder = cameraDevice?.createCaptureRequest( + CameraDevice.TEMPLATE_STILL_CAPTURE)?.apply { + addTarget(imageReader?.surface) + + // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X) + // We have to take that into account and rotate JPEG properly. + // For devices with orientation of 90, we return our mapping from ORIENTATIONS. + // For devices with orientation of 270, we need to rotate the JPEG 180 degrees. + set(CaptureRequest.JPEG_ORIENTATION, + (ORIENTATIONS.get(rotation) + sensorOrientation + 270) % 360) + + // Use the same AE and AF modes as the preview. + set(CaptureRequest.CONTROL_AF_MODE, + CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) + }?.also { setAutoFlash(it) } + + val captureCallback = object : CameraCaptureSession.CaptureCallback() { + + override fun onCaptureCompleted(session: CameraCaptureSession, + request: CaptureRequest, + result: TotalCaptureResult) { + activity.showToast("Saved: $file") + Log.d(TAG, file.toString()) + unlockFocus() + } + } + + captureSession?.apply { + stopRepeating() + abortCaptures() + capture(captureBuilder?.build(), captureCallback, null) + } + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + /** + * Unlock the focus. This method should be called when still image capture sequence is + * finished. + */ + private fun unlockFocus() { + try { + // Reset the auto-focus trigger + previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, + CameraMetadata.CONTROL_AF_TRIGGER_CANCEL) + setAutoFlash(previewRequestBuilder) + captureSession?.capture(previewRequestBuilder.build(), captureCallback, + backgroundHandler) + // After this, the camera will go back to the normal state of preview. + state = STATE_PREVIEW + captureSession?.setRepeatingRequest(previewRequest, captureCallback, + backgroundHandler) + } catch (e: CameraAccessException) { + Log.e(TAG, e.toString()) + } + + } + + override fun onClick(view: View) { + when (view.id) { + R.id.picture -> lockFocus() + R.id.info -> { + if (activity != null) { + AlertDialog.Builder(activity) + .setMessage(R.string.intro_message) + .setPositiveButton(android.R.string.ok, null) + .show() + } + } + } + } + + private fun setAutoFlash(requestBuilder: CaptureRequest.Builder) { + if (flashSupported) { + requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, + CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH) + } + } + + companion object { + + /** + * Conversion from screen rotation to JPEG orientation. + */ + private val ORIENTATIONS = SparseIntArray() + private val FRAGMENT_DIALOG = "dialog" + + init { + ORIENTATIONS.append(Surface.ROTATION_0, 90) + ORIENTATIONS.append(Surface.ROTATION_90, 0) + ORIENTATIONS.append(Surface.ROTATION_180, 270) + ORIENTATIONS.append(Surface.ROTATION_270, 180) + } + + /** + * Tag for the [Log]. + */ + private val TAG = "Camera2BasicFragment" + + /** + * Camera state: Showing camera preview. + */ + private val STATE_PREVIEW = 0 + + /** + * Camera state: Waiting for the focus to be locked. + */ + private val STATE_WAITING_LOCK = 1 + + /** + * Camera state: Waiting for the exposure to be precapture state. + */ + private val STATE_WAITING_PRECAPTURE = 2 + + /** + * Camera state: Waiting for the exposure state to be something other than precapture. + */ + private val STATE_WAITING_NON_PRECAPTURE = 3 + + /** + * Camera state: Picture was taken. + */ + private val STATE_PICTURE_TAKEN = 4 + + /** + * Max preview width that is guaranteed by Camera2 API + */ + private val MAX_PREVIEW_WIDTH = 1920 + + /** + * Max preview height that is guaranteed by Camera2 API + */ + private val MAX_PREVIEW_HEIGHT = 1080 + + /** + * Given `choices` of `Size`s supported by a camera, choose the smallest one that + * is at least as large as the respective texture view size, and that is at most as large as + * the respective max size, and whose aspect ratio matches with the specified value. If such + * size doesn't exist, choose the largest one that is at most as large as the respective max + * size, and whose aspect ratio matches with the specified value. + * + * @param choices The list of sizes that the camera supports for the intended + * output class + * @param textureViewWidth The width of the texture view relative to sensor coordinate + * @param textureViewHeight The height of the texture view relative to sensor coordinate + * @param maxWidth The maximum width that can be chosen + * @param maxHeight The maximum height that can be chosen + * @param aspectRatio The aspect ratio + * @return The optimal `Size`, or an arbitrary one if none were big enough + */ + @JvmStatic private fun chooseOptimalSize( + choices: Array, + textureViewWidth: Int, + textureViewHeight: Int, + maxWidth: Int, + maxHeight: Int, + aspectRatio: Size + ): Size { + + // Collect the supported resolutions that are at least as big as the preview Surface + val bigEnough = ArrayList() + // Collect the supported resolutions that are smaller than the preview Surface + val notBigEnough = ArrayList() + val w = aspectRatio.width + val h = aspectRatio.height + for (option in choices) { + if (option.width <= maxWidth && option.height <= maxHeight && + option.height == option.width * h / w) { + if (option.width >= textureViewWidth && option.height >= textureViewHeight) { + bigEnough.add(option) + } else { + notBigEnough.add(option) + } + } + } + + // Pick the smallest of those big enough. If there is no one big enough, pick the + // largest of those not big enough. + if (bigEnough.size > 0) { + return Collections.min(bigEnough, CompareSizesByArea()) + } else if (notBigEnough.size > 0) { + return Collections.max(notBigEnough, CompareSizesByArea()) + } else { + Log.e(TAG, "Couldn't find any suitable preview size") + return choices[0] + } + } + + @JvmStatic fun newInstance(): Camera2BasicFragment = Camera2BasicFragment() + } +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CameraActivity.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CameraActivity.kt new file mode 100644 index 00000000..e0e85fb0 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CameraActivity.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.os.Bundle +import android.support.v7.app.AppCompatActivity + +class CameraActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_camera) + savedInstanceState ?: supportFragmentManager.beginTransaction() + .replace(R.id.container, Camera2BasicFragment.newInstance()) + .commit() + } + +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CompareSizesByArea.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CompareSizesByArea.kt new file mode 100644 index 00000000..83cc2f11 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/CompareSizesByArea.kt @@ -0,0 +1,17 @@ +package com.example.android.camera2basic + +import android.util.Size +import java.lang.Long.signum + +import java.util.Comparator + +/** + * Compares two `Size`s based on their areas. + */ +internal class CompareSizesByArea : Comparator { + + // We cast here to ensure the multiplications won't overflow + override fun compare(lhs: Size, rhs: Size) = + signum(lhs.width.toLong() * lhs.height - rhs.width.toLong() * rhs.height) + +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ConfirmationDialog.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ConfirmationDialog.kt new file mode 100644 index 00000000..f276c737 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ConfirmationDialog.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.Manifest +import android.app.AlertDialog +import android.app.Dialog +import android.os.Bundle +import android.support.v4.app.DialogFragment + +/** + * Shows OK/Cancel confirmation dialog about camera permission. + */ +class ConfirmationDialog : DialogFragment() { + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = + AlertDialog.Builder(activity) + .setMessage(R.string.request_permission) + .setPositiveButton(android.R.string.ok) { _, _ -> + parentFragment.requestPermissions(arrayOf(Manifest.permission.CAMERA), + REQUEST_CAMERA_PERMISSION) + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + parentFragment.activity?.finish() + } + .create() +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Constants.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Constants.kt new file mode 100644 index 00000000..0febbd94 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/Constants.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:JvmName("Constants") + +package com.example.android.camera2basic + +@JvmField val REQUEST_CAMERA_PERMISSION = 1 +@JvmField val PIC_FILE_NAME = "pic.jpg" diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ErrorDialog.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ErrorDialog.kt new file mode 100644 index 00000000..16ecceb7 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ErrorDialog.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.camera2basic + +import android.app.AlertDialog +import android.app.Dialog +import android.os.Bundle +import android.support.v4.app.DialogFragment + +/** + * Shows an error message dialog. + */ +class ErrorDialog : DialogFragment() { + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = + AlertDialog.Builder(activity) + .setMessage(arguments.getString(ARG_MESSAGE)) + .setPositiveButton(android.R.string.ok) { _, _ -> activity.finish() } + .create() + + companion object { + + @JvmStatic private val ARG_MESSAGE = "message" + + @JvmStatic fun newInstance(message: String): ErrorDialog = ErrorDialog().apply { + arguments = Bundle().apply { putString(ARG_MESSAGE, message) } + } + } + +} \ No newline at end of file diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ImageSaver.kt b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ImageSaver.kt new file mode 100644 index 00000000..bf33d4b3 --- /dev/null +++ b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/java/com/example/android/camera2basic/ImageSaver.kt @@ -0,0 +1,55 @@ +package com.example.android.camera2basic + +import android.media.Image +import android.util.Log + +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.nio.ByteBuffer + +/** + * Saves a JPEG [Image] into the specified [File]. + */ +internal class ImageSaver( + /** + * The JPEG image + */ + private val image: Image, + + /** + * The file we save the image into. + */ + private val file: File +) : Runnable { + + override fun run() { + val buffer = image.planes[0].buffer + val bytes = ByteArray(buffer.remaining()) + buffer.get(bytes) + var output: FileOutputStream? = null + try { + output = FileOutputStream(file).apply { + write(bytes) + } + } catch (e: IOException) { + Log.e(TAG, e.toString()) + } finally { + image.close() + output?.let { + try { + it.close() + } catch (e: IOException) { + Log.e(TAG, e.toString()) + } + } + } + } + + companion object { + /** + * Tag for the [Log]. + */ + private val TAG = "ImageSaver" + } +} diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-hdpi/ic_action_info.png b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-hdpi/ic_action_info.png new file mode 100644 index 0000000000000000000000000000000000000000..32bd1aabcabb85ded957230533c00e735183a323 GIT binary patch literal 1025 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 literal 0 HcmV?d00001 diff --git a/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-mdpi/ic_launcher.png b/prebuilts/gradle/Camera2Basic/kotlinApp/Application/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..65f92a5227de9da5da0eb504606e85934bc9b94c GIT binary patch literal 2622 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 + + + + + + +