diff --git a/.gitignore b/.gitignore index 059f8bc15..a642eb42e 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,7 @@ tests/test_cases/local.properties # fastlane /vendor/bundle fastlane/report.xml +fastlane/Fastfile +fastlane/ruby /gradle/verification-keyring.gpg diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 114331356..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Nextcloud Notes - Android Client - * - * SPDX-FileCopyrightText: 2015-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2015-2024 Stefan Niedermann - * SPDX-FileCopyrightText: 2020 Hui-Ouyang16 <11710106@mail.sustech.edu.cn> - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -apply plugin: 'com.android.application' - -android { - namespace = 'it.niedermann.owncloud.notes' - - defaultConfig { - applicationId "it.niedermann.owncloud.notes" - minSdk 28 - compileSdk = 37 - targetSdk 36 - versionCode 350100050 - versionName "35.1.0 Alpha 1" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - javaCompileOptions { - annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] - } - } - } - - compileOptions { - coreLibraryDesugaringEnabled = true - sourceCompatibility JavaVersion.VERSION_21 - targetCompatibility JavaVersion.VERSION_21 - } - - kotlin { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } - } - - buildFeatures { - viewBinding = true - buildConfig = true - } - - buildTypes { - - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - debug { - enableUnitTestCoverage true - enableAndroidTestCoverage true - } - } - - testCoverage.jacocoVersion = "0.8.13" - - flavorDimensions = ["version"] - - productFlavors { - fdroid { - dimension "version" - } - dev { - dimension "version" - applicationIdSuffix ".dev" - } - play { - dimension "version" - } - qa { - applicationIdSuffix ".qa" - dimension "version" - versionCode 11 - versionName "1" - } - } - - testOptions { - unitTests { - includeAndroidResources = true - all { - jvmArgs += [ - "--add-opens=java.base/java.lang=ALL-UNNAMED", - "--add-opens=java.base/java.util=ALL-UNNAMED", - "--add-opens=java.base/java.io=ALL-UNNAMED", - "--add-opens=java.base/java.net=ALL-UNNAMED", - "--add-opens=java.base/java.security=ALL-UNNAMED", - "--add-opens=java.base/java.text=ALL-UNNAMED", - "--add-opens=java.base/jdk.internal.access=ALL-UNNAMED", - "--add-opens=java.desktop/java.awt.font=ALL-UNNAMED", - "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - ] - } - } - } - - - androidResources { - generateLocaleConfig = true - } - - packagingOptions { - resources { - excludes += "META-INF/LICENSE*" - excludes += "META-INF/versions/9/OSGI-INF/MANIFEST*" - pickFirst "MANIFEST.MF" // workaround for duplicated manifest on some dependencies - } - } - lint { - abortOnError false - disable 'MissingTranslation' - } -} - -ext { - glideVersion = '5.0.9' - roomVersion = "2.8.5" -} - -dependencies { - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' - - implementation 'com.google.guava:guava:33.7.1-jre' - implementation ('commons-httpclient:commons-httpclient:3.1') { - exclude group: 'commons-logging', module: 'commons-logging' - } - - implementation("com.github.nextcloud:android-library:2.26.0") { - exclude group: 'org.ogce', module: 'xpp3' - } - - implementation("com.github.nextcloud.android-common:ui:$nextcloudAndroidCommonLib") - implementation("com.github.nextcloud.android-common:core:$nextcloudAndroidCommonLib") - - // Nextcloud SSO - implementation("com.github.nextcloud:Android-SingleSignOn:$singleSignOnVersion") { - version { - strictly(singleSignOnVersion) - } - } - implementation "com.github.stefan-niedermann.android-commons:shared-preferences:$androidCommonsVersion" - implementation "com.github.stefan-niedermann.android-commons:reactive-livedata:$androidCommonsVersion" - implementation "com.github.stefan-niedermann.android-commons:util:$androidCommonsVersion" - implementation "com.github.stefan-niedermann.nextcloud-commons:sso-glide:$commonsVersion" - implementation "com.github.stefan-niedermann.nextcloud-commons:exception:$commonsVersion" - implementation("com.github.stefan-niedermann.nextcloud-commons:markdown:$commonsVersion") { - exclude group: 'org.jetbrains', module: 'annotations-java5' - } - - // Glide - implementation "com.github.bumptech.glide:glide:$glideVersion" - annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion" - - // Android X - implementation 'androidx.appcompat:appcompat:1.8.0' - implementation 'androidx.core:core-ktx:1.19.1' - implementation 'androidx.core:core-splashscreen:1.2.0' - implementation 'androidx.fragment:fragment:1.9.1' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0' - implementation 'androidx.preference:preference:1.2.1' - implementation 'androidx.recyclerview:recyclerview-selection:1.2.0' - implementation 'androidx.recyclerview:recyclerview:1.4.0' - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0' - implementation 'androidx.work:work-runtime:2.11.2' - implementation 'com.google.android.material:material:1.14.0' - - // Vanitech - implementation 'com.vanniktech:emoji-google:0.24.1' - - // Database - implementation "androidx.room:room-runtime:${roomVersion}" - annotationProcessor "androidx.room:room-compiler:${roomVersion}" - annotationProcessor "org.jetbrains.kotlin:kotlin-metadata-jvm:$kotlinVersion" - - // Retrofit - implementation 'com.squareup.retrofit2:retrofit:3.0.0' - - // Gson - implementation 'com.google.code.gson:gson:2.14.0' - - // ReactiveX - implementation 'io.reactivex.rxjava2:rxjava:2.2.21' - implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' - - // Testing - testImplementation 'androidx.test:core:1.7.0' - testImplementation 'androidx.arch.core:core-testing:2.2.0' - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.mockito:mockito-core:5.23.0' - testImplementation 'org.robolectric:robolectric:4.17' -} - -configurations.configureEach { - resolutionStrategy.eachDependency { details -> - if (details.requested.group == "com.github.nextcloud.android-common") { - details.useVersion(nextcloudAndroidCommonLib) - } - } -} - -// Run the compiler as a separate process -tasks.withType(JavaCompile).configureEach { - options.fork = true - - // Enable Incremental Compilation - options.incremental = true -} - -tasks.withType(Test).configureEach { - // Run tests in parallel - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..ffe6a0769 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,220 @@ +/* + * Nextcloud Notes - Android Client + * + * SPDX-FileCopyrightText: 2015-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2015-2024 Stefan Niedermann + * SPDX-FileCopyrightText: 2020 Hui-Ouyang16 <11710106@mail.sustech.edu.cn> + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + id("com.android.application") +} + +val kotlinVersion = rootProject.extra["kotlinVersion"] as String +val commonsVersion = rootProject.extra["commonsVersion"] as String +val androidCommonsVersion = rootProject.extra["androidCommonsVersion"] as String +val nextcloudAndroidCommonLib = rootProject.extra["nextcloudAndroidCommonLib"] as String +val singleSignOnVersion = rootProject.extra["singleSignOnVersion"] as String + +android { + namespace = "it.niedermann.owncloud.notes" + + defaultConfig { + applicationId = "it.niedermann.owncloud.notes" + minSdk = 28 + compileSdk = 37 + targetSdk = 36 + versionCode = 350100050 + versionName = "35.1.0 Alpha 1" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + javaCompileOptions { + annotationProcessorOptions { + arguments(mapOf("room.schemaLocation" to "$projectDir/schemas")) + } + } + } + + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + + kotlin { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + debug { + enableUnitTestCoverage = true + enableAndroidTestCoverage = true + } + } + + testCoverage.jacocoVersion = "0.8.13" + + flavorDimensions += "version" + + productFlavors { + create("generic") { + dimension = "version" + } + create("gplay") { + dimension = "version" + } + create("dev") { + dimension = "version" + applicationIdSuffix = ".dev" + } + + create("qa") { + applicationIdSuffix = ".qa" + dimension = "version" + versionCode = 11 + versionName = "1" + } + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + all { + it.jvmArgs( + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.io=ALL-UNNAMED", + "--add-opens=java.base/java.net=ALL-UNNAMED", + "--add-opens=java.base/java.security=ALL-UNNAMED", + "--add-opens=java.base/java.text=ALL-UNNAMED", + "--add-opens=java.base/jdk.internal.access=ALL-UNNAMED", + "--add-opens=java.desktop/java.awt.font=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + ) + } + } + } + + androidResources { + generateLocaleConfig = true + } + + packaging { + resources { + excludes += "META-INF/LICENSE*" + excludes += "META-INF/versions/9/OSGI-INF/MANIFEST*" + pickFirsts += "MANIFEST.MF" // workaround for duplicated manifest on some dependencies + } + } + lintOptions { + isAbortOnError = false + disable("MissingTranslation") + } +} + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") + + implementation("com.google.guava:guava:33.7.1-jre") + implementation("commons-httpclient:commons-httpclient:3.1") { + exclude(group = "commons-logging", module = "commons-logging") + } + + implementation("com.github.nextcloud:android-library:2.26.0") { + exclude(group = "org.ogce", module = "xpp3") + } + + implementation("com.github.nextcloud.android-common:ui:$nextcloudAndroidCommonLib") + implementation("com.github.nextcloud.android-common:core:$nextcloudAndroidCommonLib") + + // Nextcloud SSO + implementation("com.github.nextcloud:Android-SingleSignOn:$singleSignOnVersion") { + version { + strictly(singleSignOnVersion) + } + } + implementation("com.github.stefan-niedermann.android-commons:shared-preferences:$androidCommonsVersion") + implementation("com.github.stefan-niedermann.android-commons:reactive-livedata:$androidCommonsVersion") + implementation("com.github.stefan-niedermann.android-commons:util:$androidCommonsVersion") + implementation("com.github.stefan-niedermann.nextcloud-commons:sso-glide:$commonsVersion") + implementation("com.github.stefan-niedermann.nextcloud-commons:exception:$commonsVersion") + implementation("com.github.stefan-niedermann.nextcloud-commons:markdown:$commonsVersion") { + exclude(group = "org.jetbrains", module = "annotations-java5") + } + + // Glide + val glideVersion = "5.0.9" + implementation("com.github.bumptech.glide:glide:$glideVersion") + annotationProcessor("com.github.bumptech.glide:compiler:$glideVersion") + + // Android X + implementation("androidx.appcompat:appcompat:1.8.0") + implementation("androidx.core:core-ktx:1.19.1") + implementation("androidx.core:core-splashscreen:1.2.0") + implementation("androidx.fragment:fragment:1.9.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.11.0") + implementation("androidx.preference:preference:1.2.1") + implementation("androidx.recyclerview:recyclerview-selection:1.2.0") + implementation("androidx.recyclerview:recyclerview:1.4.0") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0") + implementation("androidx.work:work-runtime:2.11.2") + implementation("com.google.android.material:material:1.14.0") + + // Vanitech + implementation("com.vanniktech:emoji-google:0.24.1") + + // Database + val roomVersion = "2.8.5" + implementation("androidx.room:room-runtime:$roomVersion") + annotationProcessor("androidx.room:room-compiler:$roomVersion") + annotationProcessor("org.jetbrains.kotlin:kotlin-metadata-jvm:$kotlinVersion") + + // Retrofit + implementation("com.squareup.retrofit2:retrofit:3.0.0") + + // Gson + implementation("com.google.code.gson:gson:2.14.0") + + // ReactiveX + implementation("io.reactivex.rxjava2:rxjava:2.2.21") + implementation("io.reactivex.rxjava2:rxandroid:2.1.1") + + // Testing + testImplementation("androidx.test:core:1.7.0") + testImplementation("androidx.arch.core:core-testing:2.2.0") + testImplementation("junit:junit:4.13.2") + testImplementation("org.mockito:mockito-core:5.23.0") + testImplementation("org.robolectric:robolectric:4.17") +} + +configurations.configureEach { + resolutionStrategy.eachDependency { + if (requested.group == "com.github.nextcloud.android-common") { + useVersion(nextcloudAndroidCommonLib) + } + } +} + +// Run the compiler as a separate process +tasks.withType().configureEach { + options.isFork = true + + // Enable Incremental Compilation + options.isIncremental = true +} + +tasks.withType().configureEach { + // Run tests in parallel + maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1 +} diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 7a45c20c9..99d7d088c 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,22 +1,7 @@ -# This file contains the fastlane.tools configuration -# You can find the documentation at https://docs.fastlane.tools -# -# For a list of all available actions, check out -# -# https://docs.fastlane.tools/actions -# -# For a list of all available plugins, check out -# -# https://docs.fastlane.tools/plugins/available-plugins -# - # SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors # SPDX-FileCopyrightText: 2023 Álvaro Brey # SPDX-License-Identifier: GPL-3.0-or-later -# Uncomment the line if you want fastlane to automatically update itself -# update_fastlane - ## config # add following to your shell rc: # export FASTLANE_NOTES_UPLOAD_STORE_FILE="" @@ -26,26 +11,23 @@ # export FASTLANE_NEXTCLOUD_GITHUB_API_TOKEN="" + + skip_docs -default_platform(:android) +APP="notes" +REPO="nextcloud/notes-android" -BUNDLE_PATH = "app/build/outputs/bundle/playRelease/app-play-release.aab" -ENV['SUPPLY_UPLOAD_MAX_RETRIES']='10' +GRADLE_SIGNING_PROPERTIES = { + "android.injected.signing.store.file" => ENV["FASTLANE_NOTES_UPLOAD_STORE_FILE"], + "android.injected.signing.store.password" => ENV["FASTLANE_NOTES_UPLOAD_STORE_PASSWORD"], + "android.injected.signing.key.alias" => ENV["FASTLANE_NOTES_UPLOAD_KEY_ALIAS"], + "android.injected.signing.key.password" => ENV["FASTLANE_NOTES_UPLOAD_KEY_PASSWORD"], +}.freeze import("./common.Fastfile") platform :android do -desc "Build app bundle" - - desc "Run tests and build app" - lane :releasePhase1 do - test() - buildBundle() - versionInfo = getVersionInfo() - buildSignedAPK(versionCode: versionInfo["versionCode"]) - end - desc "Release previously built app to Google Play and create tag" lane :releasePhase2 do versionInfo = getVersionInfo() @@ -60,45 +42,6 @@ desc "Build app bundle" uploadToPlayStore(track: storeTrack) end - desc "Run tests" - lane :test do - gradle(task: "clean testPlayDebugUnitTest testFdroidDebugUnitTest testDevDebugUnitTest testQaDebugUnitTest") - end - - desc "Build app bundle" - lane :buildBundle do - gradle( - task: 'bundle', - flavor: 'play', - build_type: 'Release', - print_command: false, - properties: { - "android.injected.signing.store.file" => ENV["FASTLANE_NOTES_UPLOAD_STORE_FILE"], - "android.injected.signing.store.password" => ENV["FASTLANE_NOTES_UPLOAD_STORE_PASSWORD"], - "android.injected.signing.key.alias" => ENV["FASTLANE_NOTES_UPLOAD_KEY_ALIAS"], - "android.injected.signing.key.password" => ENV["FASTLANE_NOTES_UPLOAD_KEY_PASSWORD"], - } - ) - end - - desc "Build APK" - lane :buildSignedAPK do |options| - gradle( - task: 'assemble', - flavor: 'play', - build_type: 'Release', - print_command: false, - properties: { - "android.injected.signing.store.file" => ENV["FASTLANE_NOTES_UPLOAD_STORE_FILE"], - "android.injected.signing.store.password" => ENV["FASTLANE_NOTES_UPLOAD_STORE_PASSWORD"], - "android.injected.signing.key.alias" => ENV["FASTLANE_NOTES_UPLOAD_KEY_ALIAS"], - "android.injected.signing.key.password" => ENV["FASTLANE_NOTES_UPLOAD_KEY_PASSWORD"], - } - ) - sh("mkdir -p ../release/") - sh("mv ../app/build/outputs/apk/play/release/app-play-release.apk ../release/nextcloud-notes-#{options[:versionCode]}.apk") - end - desc "Show versions and prompt for confirmation" private_lane :preReleaseChecks do |options| versionInfo = options[:versionInfo] @@ -113,56 +56,15 @@ desc "Build app bundle" promptYesNo(text: text) end - desc "Check if release artifacts exist" - private_lane :checkArtifactsExist do - if !File.exist?("../#{BUNDLE_PATH}") - UI.user_error!("Bundle not found at #{BUNDLE_PATH}") - end - end - - - desc "Create release tag" - private_lane :tag do |options| - tagName = options[:name] - add_git_tag( - tag: tagName, - sign: true - ) - push_git_tags(tag: tagName) - end - - desc "Upload release artifacts to Google Play" - private_lane :uploadToPlayStore do |options| - upload_to_play_store( - skip_upload_images: true, - skip_upload_apk: true, - track: options[:track], - aab: BUNDLE_PATH - ) - end - private_lane :createGithubRelease do |options| set_github_release( - repository_name: "nextcloud/notes-android", + repository_name: REPO, api_token: ENV["FASTLANE_NEXTCLOUD_GITHUB_API_TOKEN"], name: options[:name], tag_name: options[:tag], description: (File.read("metadata/android/en-US/changelogs/" + options[:versionCode] + ".txt") rescue "No changelog provided"), - upload_assets: [ "release/nextcloud-notes-" + options[:versionCode].to_s + ".apk" ] + upload_assets: Dir.glob("release/*.apk") ) end - desc "Upload Alpha version to play store" - lane :uploadAlphaToPlayStore do |options| - upload_to_play_store( - skip_upload_images: true, - skip_upload_aab: true, - skip_upload_changelogs: true, - skip_upload_metadata: true, - skip_upload_screenshots: true, - track: 'alpha', - apk: "/home/androiddaily/apks-notes/android-notes-" + options[:version] + ".apk", - ) - end - end