diff --git a/packages/app_usage/CHANGELOG.md b/packages/app_usage/CHANGELOG.md index a55d13b08..b587a0d8f 100644 --- a/packages/app_usage/CHANGELOG.md +++ b/packages/app_usage/CHANGELOG.md @@ -1,58 +1,63 @@ +## 4.0.0 + +* upgrade of Android APK +* removing `AppUsageException` - instead and empty list is returned on iOS + ## 3.0.1 -- Updated pubsec.yaml description -- Fixed license file +* Updated `pubsec.yaml` description +* Fixed license file ## 3.0.0 -- Updates Kotlin plugin and AGP -- Upgrade of compileSdkVersion -- Upgrade to Dart 3 +* Updates Kotlin plugin and AGP +* Upgrade of compileSdkVersion +* Upgrade to Dart 3 ## 2.1.1 -- check of Android OS version added when getting `lastForeground`. +* check of Android OS version added when getting `lastForeground`. ## 2.1.0 -- Addition of `lastForeground` information - when was the app last time in the foreground. -- update of example app to AndroidX and new gradle build version. -- update of documentation. +* Addition of `lastForeground` information - when was the app last time in the foreground. +* update of example app to AndroidX and new gradle build version. +* update of documentation. ## 2.0.0 -- Migration to null safety +* Migration to null safety ## 1.2.0 -- Fixed the parsing of package names and app names. +* Fixed the parsing of package names and app names. ## 1.1.1 -- Updated example and README slightly to reflect the precision of the plugin. +* Updated example and README slightly to reflect the precision of the plugin. ## 1.1.0 -- Changed the behaviour of the plugin to delay asking for permission when app usage is requested, rather than when the app is started. +* Changed the behavior of the plugin to delay asking for permission when app usage is requested, rather than when the app is started. ## 1.0.2 -- Fixed an Android issue where the permission activity could not be spawned. +* Fixed an Android issue where the permission activity could not be spawned. ## 1.0.1 -- Made the project anew since the old project had an error somewhere. +* Made the project anew since the old project had an error somewhere. ## 1.0.0 -- Updated to the new Android API -- Changed Android source code to Kotlin rather than Java +* Updated to the new Android API +* Changed Android source code to Kotlin rather than Java ## 0.9.0 -- Update example app to support Android X -- Updated the README file to emphasize the need to use min SDK version 21 for Android +* Update example app to support Android X +* Updated the README file to emphasize the need to use min SDK version 21 for Android ## 0.0.1 -- Initial release +* Initial release diff --git a/packages/app_usage/LICENSE b/packages/app_usage/LICENSE index 67a247a2c..e730f503e 100644 --- a/packages/app_usage/LICENSE +++ b/packages/app_usage/LICENSE @@ -1,17 +1,9 @@ MIT License. -Copyright 2019 Copenhagen Center for Health Technology (CACHET) at the Technical University of Denmark (DTU). +Copyright 2018-2024 the Technical University of Denmark (DTU). -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the ”Software”), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ”Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED ”AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED ”AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/app_usage/android/build.gradle b/packages/app_usage/android/build.gradle index 31c2954b1..b49e133d9 100644 --- a/packages/app_usage/android/build.gradle +++ b/packages/app_usage/android/build.gradle @@ -1,44 +1,68 @@ -group 'dk.cachet.app_usage' -version '1.0-SNAPSHOT' +group = "dk.cachet.app_usage" +version = "1.0-SNAPSHOT" buildscript { -ext.kotlin_version = '1.7.10' + ext.kotlin_version = "1.8.22" repositories { google() -mavenCentral() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath("com.android.tools.build:gradle:8.1.0") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") } } -rootProject.allprojects { +allprojects { repositories { google() - jcenter() + mavenCentral() } } -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' +apply plugin: "com.android.library" +apply plugin: "kotlin-android" android { - compileSdkVersion 33 + namespace "dk.cachet.app_usage" + + compileSdk = 35 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11 + } sourceSets { - main.java.srcDirs += 'src/main/kotlin' + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" } + defaultConfig { - minSdkVersion 16 + minSdk = 21 } - lintOptions { - disable 'InvalidPackage' + + dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.mockito:mockito-core:5.0.0") } - namespace "dk.cachet.app_usage" -} -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testOptions { + unitTests.all { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true + } + } + } } + + diff --git a/packages/app_usage/android/gradle.properties b/packages/app_usage/android/gradle.properties deleted file mode 100644 index 38c8d4544..000000000 --- a/packages/app_usage/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.enableR8=true -android.useAndroidX=true -android.enableJetifier=true diff --git a/packages/app_usage/android/gradle/wrapper/gradle-wrapper.properties b/packages/app_usage/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 1412e4a0a..000000000 --- a/packages/app_usage/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/packages/app_usage/example/.flutter-plugins-dependencies b/packages/app_usage/example/.flutter-plugins-dependencies index 72bea7d1c..06489b3fd 100644 --- a/packages/app_usage/example/.flutter-plugins-dependencies +++ b/packages/app_usage/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[],"android":[{"name":"app_usage","path":"/Users/arata/Developer/carp/flutter-plugins/packages/app_usage/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"app_usage","dependencies":[]}],"date_created":"2024-10-30 13:38:21.146381","version":"3.24.3","swift_package_manager_enabled":false} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[],"android":[{"name":"app_usage","path":"/Users/bardram/dev/flutter-plugins/packages/app_usage/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"app_usage","dependencies":[]}],"date_created":"2025-02-11 15:03:37.052336","version":"3.27.1","swift_package_manager_enabled":false} \ No newline at end of file diff --git a/packages/app_usage/example/android/app/build.gradle b/packages/app_usage/example/android/app/build.gradle index 1b852926f..8fedfa1a7 100644 --- a/packages/app_usage/example/android/app/build.gradle +++ b/packages/app_usage/example/android/app/build.gradle @@ -1,64 +1,44 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" } -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - android { - compileSdkVersion flutter.compileSdkVersion - + namespace = "dk.cachet.app_usage_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion - sourceSets { - main.java.srcDirs += 'src/main/kotlin' + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } - lintOptions { - disable 'InvalidPackage' + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "dk.cachet.app_usage_example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig = signingConfigs.debug } } } flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + source = "../.." } diff --git a/packages/app_usage/example/android/app/src/debug/AndroidManifest.xml b/packages/app_usage/example/android/app/src/debug/AndroidManifest.xml index 843fb238c..f880684a6 100644 --- a/packages/app_usage/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/app_usage/example/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/packages/app_usage/example/android/app/src/main/AndroidManifest.xml b/packages/app_usage/example/android/app/src/main/AndroidManifest.xml index 4b22c33ba..e251790db 100644 --- a/packages/app_usage/example/android/app/src/main/AndroidManifest.xml +++ b/packages/app_usage/example/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ + diff --git a/packages/app_usage/example/android/build.gradle b/packages/app_usage/example/android/build.gradle index 7387be66c..d2ffbffa4 100644 --- a/packages/app_usage/example/android/build.gradle +++ b/packages/app_usage/example/android/build.gradle @@ -1,31 +1,18 @@ -buildscript { -ext.kotlin_version = '1.7.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() - jcenter() + mavenCentral() } } -rootProject.buildDir = '../build' +rootProject.buildDir = "../build" subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { - project.evaluationDependsOn(':app') + project.evaluationDependsOn(":app") } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/packages/app_usage/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/app_usage/example/android/gradle/wrapper/gradle-wrapper.properties index 873d15b32..7bb2df6ba 100644 --- a/packages/app_usage/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/app_usage/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip diff --git a/packages/app_usage/example/android/settings.gradle b/packages/app_usage/example/android/settings.gradle index d3b6a4013..b9e43bd37 100644 --- a/packages/app_usage/example/android/settings.gradle +++ b/packages/app_usage/example/android/settings.gradle @@ -1,15 +1,25 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -include ':app' + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.1.0" apply false + id "org.jetbrains.kotlin.android" version "1.8.22" apply false +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +include ":app" diff --git a/packages/app_usage/example/lib/main.dart b/packages/app_usage/example/lib/main.dart index 37ecca251..9556bbb08 100644 --- a/packages/app_usage/example/lib/main.dart +++ b/packages/app_usage/example/lib/main.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; import 'package:app_usage/app_usage.dart'; -void main() => runApp(MyApp()); +void main() => runApp(AppUsageApp()); -class MyApp extends StatefulWidget { +class AppUsageApp extends StatefulWidget { @override - _MyAppState createState() => _MyAppState(); + AppUsageAppState createState() => AppUsageAppState(); } -class _MyAppState extends State { +class AppUsageAppState extends State { List _infos = []; @override @@ -23,11 +23,7 @@ class _MyAppState extends State { List infoList = await AppUsage().getAppUsage(startDate, endDate); setState(() => _infos = infoList); - - for (var info in infoList) { - print(info.toString()); - } - } on AppUsageException catch (exception) { + } catch (exception) { print(exception); } } diff --git a/packages/app_usage/lib/app_usage.dart b/packages/app_usage/lib/app_usage.dart index 17f90f328..7e0d085af 100644 --- a/packages/app_usage/lib/app_usage.dart +++ b/packages/app_usage/lib/app_usage.dart @@ -3,17 +3,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'dart:io' show Platform; -/// Custom Exception for the plugin. -/// Thrown whenever the plugin is used on platforms other than Android. -class AppUsageException implements Exception { - String _cause; - - AppUsageException(this._cause); - - @override - String toString() => _cause; -} - +/// Information on app usage. class AppUsageInfo { late String _packageName, _appName; late Duration _usage; @@ -52,11 +42,11 @@ class AppUsageInfo { DateTime get lastForeground => _lastForeground; @override - String toString() { - return 'App Usage: $packageName - $appName, duration: $usage [$startDate, $endDate]'; - } + String toString() => + 'App Usage: $packageName - $appName, duration: $usage [$startDate, $endDate]'; } +/// Singleton class to get app usage statistics. class AppUsage { static const MethodChannel _methodChannel = const MethodChannel("app_usage.methodChannel"); @@ -65,37 +55,42 @@ class AppUsage { AppUsage._(); factory AppUsage() => _instance; + /// Get app usage statistics for the specified interval. Only works on Android. + /// Returns an empty list if called on iOS. Future> getAppUsage( DateTime startDate, DateTime endDate, ) async { - if (Platform.isAndroid) { - /// Convert dates to ms since epoch - int end = endDate.millisecondsSinceEpoch; - int start = startDate.millisecondsSinceEpoch; - - /// Set parameters - Map interval = {'start': start, 'end': end}; - - /// Get result and parse it as a Map of > - Map usage = await _methodChannel.invokeMethod('getUsage', interval); - - // Convert to list of AppUsageInfo - List result = []; - for (String key in usage.keys) { - List temp = List.from(usage[key]); - if (temp[0] > 0) { - result.add(AppUsageInfo( - key, - temp[0], - DateTime.fromMillisecondsSinceEpoch(temp[1].round() * 1000), - DateTime.fromMillisecondsSinceEpoch(temp[2].round() * 1000), - DateTime.fromMillisecondsSinceEpoch(temp[3].round() * 1000))); - } - } + if (!Platform.isAndroid) return []; - return result; + if (endDate.isBefore(startDate)) { + throw ArgumentError('End date must be after start date'); } - throw AppUsageException('AppUsage API is only available on Android'); + + // Convert dates to ms since epoch + int end = endDate.millisecondsSinceEpoch; + int start = startDate.millisecondsSinceEpoch; + + // Set parameters + Map interval = {'start': start, 'end': end}; + + // Get result and parse it as a Map of > + Map usage = await _methodChannel.invokeMethod('getUsage', interval); + + // Convert to list of AppUsageInfo + List result = []; + for (String key in usage.keys) { + List temp = List.from(usage[key]); + if (temp[0] > 0) { + result.add(AppUsageInfo( + key, + temp[0], + DateTime.fromMillisecondsSinceEpoch(temp[1].round() * 1000), + DateTime.fromMillisecondsSinceEpoch(temp[2].round() * 1000), + DateTime.fromMillisecondsSinceEpoch(temp[3].round() * 1000))); + } + } + + return result; } } diff --git a/packages/app_usage/pubspec.yaml b/packages/app_usage/pubspec.yaml index 39a6c3d31..a150896c2 100644 --- a/packages/app_usage/pubspec.yaml +++ b/packages/app_usage/pubspec.yaml @@ -1,6 +1,6 @@ name: app_usage description: App usage plugin for Android only, which can be used to get the time spent by the user in each app. -version: 3.0.1 +version: 4.0.0 homepage: https://github.com/cph-cachet/flutter-plugins/blob/master/packages/app_usage environment: diff --git a/packages/notifications/android/gradle/wrapper/gradle-wrapper.properties b/packages/notifications/android/gradle/wrapper/gradle-wrapper.properties index 3c9d0852b..0bf613799 100644 --- a/packages/notifications/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/notifications/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Tue Feb 11 14:46:23 CET 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/packages/screen_state/android/gradle/wrapper/gradle-wrapper.properties b/packages/screen_state/android/gradle/wrapper/gradle-wrapper.properties index 01a286e96..09523c0e5 100644 --- a/packages/screen_state/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/screen_state/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip