From 7ff4801d56f61da343d0484b802d44a69f5bd2f3 Mon Sep 17 00:00:00 2001 From: NLOG Date: Sat, 26 Dec 2020 19:07:36 +0900 Subject: [PATCH 01/10] =?UTF-8?q?Bump=20dependency,=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=AC=B4=EC=8B=9C=20=EC=98=B5=EC=85=98=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/type/JagaJindanData.dart | 6 +-- lib/ui/MainPage.dart | 5 +- lib/ui/component/JagaJindanForm.dart | 54 +-------------------- pubspec.lock | 70 ++++++++++++++-------------- pubspec.yaml | 14 +++--- 5 files changed, 47 insertions(+), 102 deletions(-) diff --git a/lib/type/JagaJindanData.dart b/lib/type/JagaJindanData.dart index 6bb7df0..a92cee0 100644 --- a/lib/type/JagaJindanData.dart +++ b/lib/type/JagaJindanData.dart @@ -1,6 +1,6 @@ class JagaJindanData { String name, birthday, school, edu, password; - bool force, agree = false, startup = false, useNotification = false, submitLimitation = false; + bool agree = false, startup = false, useNotification = false, submitLimitation = false; static JagaJindanData readFromJSON(dynamic json) { return new JagaJindanData( @@ -9,7 +9,6 @@ class JagaJindanData { json["school"] ?? "", json["edu"] ?? "", json["password"] ?? "", - json["force"] ?? false, json["agree"] ?? false, json["startup"] ?? false, json["noti"] ?? false, @@ -18,7 +17,7 @@ class JagaJindanData { } JagaJindanData(this.name, this.birthday, this.school, this.edu, this.password, - this.force, this.agree, this.startup, this.useNotification, this.submitLimitation); + this.agree, this.startup, this.useNotification, this.submitLimitation); dynamic toJSON() { return { @@ -27,7 +26,6 @@ class JagaJindanData { "school": this.school, "edu": this.edu, "password": this.password, - "force": this.force, "agree": this.agree, "startup": this.startup, "noti": this.useNotification, diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index 75dcb84..877d0f9 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -10,14 +10,13 @@ import 'component/agree.dart'; class MainPage extends StatefulWidget { JagaJindanData data = - JagaJindanData("", "", "", "", "", false, false, false, false, false); + JagaJindanData("", "", "", "", "", false, false, false, false); TextEditingController nameController = TextEditingController(), birthdayController = TextEditingController(), schoolController = TextEditingController(), eduController = TextEditingController(), - passwordController = TextEditingController(), - forceController = TextEditingController(); + passwordController = TextEditingController(); MainPageState pageState; diff --git a/lib/ui/component/JagaJindanForm.dart b/lib/ui/component/JagaJindanForm.dart index d89d94e..f22a212 100644 --- a/lib/ui/component/JagaJindanForm.dart +++ b/lib/ui/component/JagaJindanForm.dart @@ -85,59 +85,7 @@ JagaJindanForm(MainPageState state) { state.widget.writeJSON(); }, controller: state.widget.passwordController, - ), - visible: !state.widget.data.force, - ), - CheckboxListTile( - title: const Text('비밀번호 없이 설문 제출'), - value: state.widget.data.force, - onChanged: (bool value) { - state.setState(() { - if (value) { - showDialog( - context: state.context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - title: Text('경고'), - content: SingleChildScrollView( - child: ListBody( - children: [ - Text('비밀번호 없이 설문을 제출할 수 있습니다.'), - Text('위 기능을 사용함으로써 발생하는 모든 책임은 사용자에게 있습니다.'), - ], - ), - ), - actions: [ - FlatButton( - child: Text('계속하기'), - onPressed: () { - Navigator.of(context).pop(); - state.widget.data.password = ""; - state.widget.passwordController.text = ""; - - state.setState(() { - state.widget.data.force = true; - state.widget.writeJSON(); - }); - }, - ), - FlatButton( - child: Text('끄기'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - } else { - state.widget.data.force = false; - state.widget.writeJSON(); - } - }); - }, + ) ), CheckboxListTile( title: const Text('앱 시작 시 자가진단 제출'), diff --git a/pubspec.lock b/pubspec.lock index 3120b37..ebecb4c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,42 +21,42 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety.1" + version: "2.5.0-nullsafety.3" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0-nullsafety.3" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.1.0-nullsafety.5" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0-nullsafety.3" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0-nullsafety.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.3" + version: "1.15.0-nullsafety.5" convert: dependency: transitive description: @@ -77,7 +77,7 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.2" encrypt: dependency: "direct main" description: @@ -91,7 +91,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0-nullsafety.3" ffi: dependency: transitive description: @@ -117,14 +117,14 @@ packages: name: flutter_local_notifications url: "https://pub.dartlang.org" source: hosted - version: "3.0.0+1" + version: "3.0.2" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.0+1" flutter_test: dependency: "direct dev" description: flutter @@ -141,7 +141,7 @@ packages: name: fluttertoast url: "https://pub.dartlang.org" source: hosted - version: "7.1.1" + version: "7.1.6" http: dependency: "direct main" description: @@ -169,42 +169,42 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.1" + version: "0.6.3-nullsafety.3" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety.1" + version: "0.12.10-nullsafety.3" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.4" + version: "1.3.0-nullsafety.6" package_info: dependency: "direct main" description: name: package_info url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.3+2" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.1" + version: "1.8.0-nullsafety.3" path_provider: dependency: "direct main" description: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "1.6.21" + version: "1.6.24" path_provider_linux: dependency: transitive description: @@ -218,21 +218,21 @@ packages: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+4" + version: "0.0.4+6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+1" + version: "0.0.4+3" pedantic: dependency: transitive description: @@ -279,42 +279,42 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety.2" + version: "1.8.0-nullsafety.4" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety.2" + version: "1.10.0-nullsafety.6" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.1" + version: "2.1.0-nullsafety.3" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.1" + version: "1.1.0-nullsafety.3" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety.1" + version: "1.2.0-nullsafety.3" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety.2" + version: "0.2.19-nullsafety.6" timezone: dependency: transitive description: @@ -328,28 +328,28 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.3" + version: "1.3.0-nullsafety.5" url_launcher: dependency: "direct main" description: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "5.7.8" + version: "5.7.10" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+3" + version: "0.0.1+4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+8" + version: "0.0.1+9" url_launcher_platform_interface: dependency: transitive description: @@ -363,28 +363,28 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.5" + version: "0.1.5+1" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+1" + version: "0.0.1+3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.0-nullsafety.5" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "1.7.3" + version: "1.7.4" xdg_directories: dependency: transitive description: @@ -393,5 +393,5 @@ packages: source: hosted version: "0.1.2" sdks: - dart: ">=2.10.0-110 <=2.11.0-218.0.dev" + dart: ">=2.12.0-0.0 <3.0.0" flutter: ">=1.22.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 41ae00d..04b8ea7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: 자가진단 자동화 앱 publish_to: 'none' -version: 0.2.10 +version: 0.3.0 environment: sdk: ">=2.7.0 <3.0.0" @@ -12,14 +12,14 @@ dependencies: flutter: sdk: flutter - cupertino_icons: ^1.0.0 - path_provider: ^1.6.21 - fluttertoast: ^7.1.1 + cupertino_icons: ^1.0.2 + path_provider: ^1.6.24 + fluttertoast: ^7.1.6 http: ^0.12.2 encrypt: ^4.1.0 - flutter_local_notifications: ^3.0.0+1 - url_launcher: ^5.7.8 - package_info: ^0.4.3 + flutter_local_notifications: ^3.0.2 + url_launcher: ^5.7.10 + package_info: ^0.4.3+2 dev_dependencies: flutter_test: From 35fb8fff807b63eabba3d7d9f2acbf1b6709e3ed Mon Sep 17 00:00:00 2001 From: NLOG Date: Sat, 26 Dec 2020 20:06:56 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=EC=95=B1=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=95=8C=EB=A6=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/MainPageState.dart | 38 +++++++++++++++++++++++++++++++++-- lib/ui/component/setting.dart | 26 +----------------------- lib/util/notify.dart | 13 +++++++----- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/lib/ui/MainPageState.dart b/lib/ui/MainPageState.dart index b848a63..69c3533 100644 --- a/lib/ui/MainPageState.dart +++ b/lib/ui/MainPageState.dart @@ -1,10 +1,14 @@ +import 'dart:convert'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:jaga_jindan/ui/component/JagaJindanForm.dart'; import 'package:jaga_jindan/ui/component/setting.dart'; +import 'package:jaga_jindan/util/notify.dart'; import 'package:jaga_jindan/util/school.dart'; - import 'package:jaga_jindan/util/sendSurvey.dart'; +import 'package:package_info/package_info.dart'; import 'MainPage.dart'; @@ -12,6 +16,8 @@ class MainPageState extends State { final formKey = GlobalKey(); String edu = "서울특별시", school = "1", selectedSchoolCode = ""; List schools = []; + bool flag = false; + String appVer, newVer = "불러오는 중"; TextEditingController searchSchoolController; @@ -20,6 +26,34 @@ class MainPageState extends State { this.widget.pageState = this; searchSchoolController = TextEditingController(); + if (!flag) { + PackageInfo.fromPlatform().then((value) => setState(() { + appVer = value.version; + })); + + http + .get( + "https://api.github.com/repos/eduro-hcs/jaga_jindan/releases/latest") + .then((data) { + try { + setState(() { + newVer = jsonDecode(data.body)["tag_name"]; + newVer = newVer.substring(1); + if (newVer != appVer) { + noti("새로운 버전이 있습니다.", "현재 버전 : $appVer, 새 버전 : $newVer", + "https://github.com/eduro-hcs/jaga_jindan/releases/latest"); + } + }); + } catch (e) { + newVer = "(error)"; + } + }); + } + flag = true; + + //debugPrint(appVer); + //debugPrint(newVer); + return Scaffold( appBar: AppBar( title: Text('자가진단 자동 제출'), @@ -38,7 +72,7 @@ class MainPageState extends State { alignment: Alignment.bottomLeft, child: FloatingActionButton( onPressed: () async { - showCredit(this); + showCredit(this, appVer, newVer); }, child: Icon(Icons.settings), tooltip: "설정 및 정보", diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index 29ead51..be4e514 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -1,37 +1,13 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; import 'package:jaga_jindan/ui/MainPageState.dart'; -import 'package:package_info/package_info.dart'; import 'package:url_launcher/url_launcher.dart'; -showCredit(MainPageState state) async { - var appVer = (await PackageInfo.fromPlatform()).version, first = false; - var newVer = "불러오는 중"; - +showCredit(MainPageState state, String appVer, String newVer) async { showDialog( context: state.context, barrierDismissible: false, builder: (BuildContext context) { return StatefulBuilder(builder: (context, StateSetter _setState) { - if (!first) { - http - .get( - "https://api.github.com/repos/eduro-hcs/jaga_jindan/releases/latest") - .then((data) { - try { - _setState(() { - newVer = jsonDecode(data.body)["tag_name"]; - newVer = newVer.substring(1); - }); - } catch (e) { - newVer = "(error)"; - } - }); - first = true; - } - return AlertDialog( title: Text('설정 및 정보'), content: SingleChildScrollView( diff --git a/lib/util/notify.dart b/lib/util/notify.dart index 6e3b841..f9d61f6 100644 --- a/lib/util/notify.dart +++ b/lib/util/notify.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:url_launcher/url_launcher.dart'; void toast(String message) { Fluttertoast.showToast( @@ -14,12 +15,13 @@ void toast(String message) { } Future onDidReceiveLocalNotification( - int id, String title, String body, String payload) async { -} + int id, String title, String body, String payload) async {} Future selectNotification(String payload) async { if (payload != null) { - toast(payload); + if (payload.startsWith("https://") || payload.startsWith("http://")) { + launch(payload); + } else toast(payload); } } @@ -62,7 +64,8 @@ void initNotification() async { var notiId = 0; -void noti(String title, String desc) async { +void noti(String title, String desc, [String payload = ""]) async { + if (payload == "") payload = desc; await flutterLocalNotificationsPlugin - .show(notiId++, title, desc, platformChannelSpecifics, payload: desc); + .show(notiId++, title, desc, platformChannelSpecifics, payload: payload); } From 53978e192f3105002ee076deec10dc09914b2b0c Mon Sep 17 00:00:00 2001 From: NLOG Date: Mon, 28 Dec 2020 08:19:12 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=EB=B0=B1=EA=B7=B8=EB=9D=BC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=20=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 73 +++++++++++++----------- android/app/src/main/AndroidManifest.xml | 2 + android/build.gradle | 43 ++++++++------ lib/ui/MainPageState.dart | 36 ++++++++++-- lib/ui/component/setting.dart | 4 +- pubspec.lock | 7 +++ pubspec.yaml | 1 + 7 files changed, 110 insertions(+), 56 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e601354..bfac5fd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,24 +1,24 @@ def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } + 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.") + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { - flutterVersionCode = '1' + flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { - flutterVersionName = '1.0' + flutterVersionName = '1.0' } apply plugin: 'com.android.application' @@ -26,38 +26,43 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 28 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - lintOptions { - disable 'InvalidPackage' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.nlog.jaga_jindan" - minSdkVersion 16 - targetSdkVersion 28 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - 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 - } - } + compileSdkVersion 28 + compileSdkVersion rootProject.ext.compileSdkVersion + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.nlog.jaga_jindan" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + + targetSdkVersion rootProject.ext.targetSdkVersion + } + + 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 + } + } } flutter { - source '../..' + source '../..' } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + androidTestImplementation 'androidx.test:runner:1.3.0' // or higher + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' // or higher } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f0bcae7..b19e74b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ @@ -13,6 +14,7 @@ diff --git a/android/build.gradle b/android/build.gradle index 3100ad2..fa2a97e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,31 +1,42 @@ buildscript { - ext.kotlin_version = '1.3.50' - repositories { - google() - jcenter() - } + ext.kotlin_version = '1.3.0' // Must use 1.3.0 or higher. + ext { + compileSdkVersion = 28 // or higher + targetSdkVersion = 28 // or higher + appCompatVersion = "1.1.0" // or higher + } - dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } } allprojects { - repositories { - google() - jcenter() - } + repositories { + google() + jcenter() + maven { + // [required] background_fetch + url "${project(':background_fetch').projectDir}/libs" + } + } } rootProject.buildDir = '../build' subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" + project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { - project.evaluationDependsOn(':app') + project.evaluationDependsOn(':app') } task clean(type: Delete) { - delete rootProject.buildDir + delete rootProject.buildDir } diff --git a/lib/ui/MainPageState.dart b/lib/ui/MainPageState.dart index 69c3533..98b0cbf 100644 --- a/lib/ui/MainPageState.dart +++ b/lib/ui/MainPageState.dart @@ -1,5 +1,7 @@ +import 'dart:async'; import 'dart:convert'; +import 'package:background_fetch/background_fetch.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; @@ -12,19 +14,48 @@ import 'package:package_info/package_info.dart'; import 'MainPage.dart'; +survey() async { + +} + +void backgroundFetchHeadlessTask(String taskId) async { + survey(); + + BackgroundFetch.scheduleTask(TaskConfig( + enableHeadless: true, + startOnBoot: true, + stopOnTerminate: false, + taskId: 'com.nnnlog.survey', delay: 10000)); //TODO +} + class MainPageState extends State { final formKey = GlobalKey(); String edu = "서울특별시", school = "1", selectedSchoolCode = ""; List schools = []; - bool flag = false; + bool flag = false, initBackground = false; String appVer, newVer = "불러오는 중"; TextEditingController searchSchoolController; + Future initBackgroundService() async { + if (!initBackground) { + BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); + + BackgroundFetch.scheduleTask(TaskConfig( + enableHeadless: true, + startOnBoot: true, + stopOnTerminate: false, + taskId: 'com.nnnlog.survey', + delay: 1000)); + } + initBackground = true; + } + @override Widget build(BuildContext context) { this.widget.pageState = this; searchSchoolController = TextEditingController(); + initBackgroundService(); if (!flag) { PackageInfo.fromPlatform().then((value) => setState(() { @@ -51,9 +82,6 @@ class MainPageState extends State { } flag = true; - //debugPrint(appVer); - //debugPrint(newVer); - return Scaffold( appBar: AppBar( title: Text('자가진단 자동 제출'), diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index be4e514..ee2b96d 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -75,7 +75,7 @@ showCredit(MainPageState state, String appVer, String newVer) async { decoration: TextDecoration.underline), ), onTap: () => launch( - "https://github.com/eduro-hcs/jaga_jindan/releases/tag/v${appVer}"), + "https://github.com/eduro-hcs/jaga_jindan/releases/tag/v$appVer"), ) ]), Row(children: [ @@ -88,7 +88,7 @@ showCredit(MainPageState state, String appVer, String newVer) async { decoration: TextDecoration.underline), ), onTap: () => launch( - "https://github.com/eduro-hcs/jaga_jindan/releases/tag/v${newVer}"), + "https://github.com/eduro-hcs/jaga_jindan/releases/tag/v$newVer"), ) ]), ], diff --git a/pubspec.lock b/pubspec.lock index ebecb4c..5ff5ae3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.5.0-nullsafety.3" + background_fetch: + dependency: "direct main" + description: + name: background_fetch + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.0" boolean_selector: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 04b8ea7..83fb569 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: flutter_local_notifications: ^3.0.2 url_launcher: ^5.7.10 package_info: ^0.4.3+2 + background_fetch: ^0.6.0 dev_dependencies: flutter_test: From 3942f3961cfcba3d09f7d932a58c37aab3918ad5 Mon Sep 17 00:00:00 2001 From: NLOG Date: Mon, 28 Dec 2020 14:05:16 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=EB=B0=B1=EA=B7=B8=EB=9D=BC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=20=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EC=9E=90=EB=8F=99=20=EC=A0=9C=EC=B6=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 2 ++ lib/type/JagaJindanData.dart | 32 ++++++++++++++---- lib/ui/MainPage.dart | 12 +++++-- lib/ui/MainPageState.dart | 24 ++------------ lib/ui/component/JagaJindanForm.dart | 11 ++++--- lib/ui/component/searchSchool.dart | 7 ++-- lib/ui/component/setting.dart | 49 ++++++++++++++++++++++++++++ lib/util/RSAEncrypt.dart | 9 +++-- lib/util/school.dart | 2 +- lib/util/sendSurvey.dart | 47 +++++++++++++++++++++++++- pubspec.lock | 2 +- pubspec.yaml | 3 +- 12 files changed, 155 insertions(+), 45 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 7c18b6c..8ded18d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,9 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart' show timeDilation; import 'package:jaga_jindan/ui/MainPage.dart'; import 'package:jaga_jindan/util/notify.dart'; +import 'package:timezone/data/latest.dart' as tz; void main() { timeDilation = 2.0; + tz.initializeTimeZones(); runApp(MyApp()); } diff --git a/lib/type/JagaJindanData.dart b/lib/type/JagaJindanData.dart index a92cee0..d48613a 100644 --- a/lib/type/JagaJindanData.dart +++ b/lib/type/JagaJindanData.dart @@ -1,8 +1,18 @@ +import 'package:timezone/standalone.dart' as tz; + class JagaJindanData { String name, birthday, school, edu, password; - bool agree = false, startup = false, useNotification = false, submitLimitation = false; + bool agree = false, + startup = false, + useNotification = false, + submitLimitation = false; + tz.TZDateTime submitTime; static JagaJindanData readFromJSON(dynamic json) { + var tm; + try { + tm = tz.TZDateTime.parse(tz.getLocation('Asia/Seoul'), json["submitTime"]); + } catch (e) {} return new JagaJindanData( json["name"] ?? "", json["birthday"] ?? "", @@ -12,12 +22,21 @@ class JagaJindanData { json["agree"] ?? false, json["startup"] ?? false, json["noti"] ?? false, - json["submitLimitation"] ?? false - ); + json["submitLimitation"] ?? false, + tm); } - JagaJindanData(this.name, this.birthday, this.school, this.edu, this.password, - this.agree, this.startup, this.useNotification, this.submitLimitation); + JagaJindanData( + this.name, + this.birthday, + this.school, + this.edu, + this.password, + this.agree, + this.startup, + this.useNotification, + this.submitLimitation, + this.submitTime); dynamic toJSON() { return { @@ -29,7 +48,8 @@ class JagaJindanData { "agree": this.agree, "startup": this.startup, "noti": this.useNotification, - "submitLimitation": this.submitLimitation + "submitLimitation": this.submitLimitation, + "submitTime": this.submitTime?.toString() }; } } diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index 877d0f9..4b68564 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -10,13 +10,14 @@ import 'component/agree.dart'; class MainPage extends StatefulWidget { JagaJindanData data = - JagaJindanData("", "", "", "", "", false, false, false, false); + JagaJindanData("", "", "", "", "", false, false, false, false, null); TextEditingController nameController = TextEditingController(), birthdayController = TextEditingController(), schoolController = TextEditingController(), eduController = TextEditingController(), - passwordController = TextEditingController(); + passwordController = TextEditingController(), + timeController = TextEditingController(); MainPageState pageState; @@ -28,10 +29,15 @@ class MainPage extends StatefulWidget { this.eduController.text = this.data.edu; this.passwordController.text = this.data.password; + var tm = this.data.submitTime; + if (tm.minute != null && tm.hour != null) this.timeController.text = "${tm.hour}:${tm.hour}"; + + setBackgroundProcess(this.data); + if (this.data.startup) sendSurvey(this.data, true); agree(pageState); - await pageState.setState(() {}); + pageState.setState(() {}); } writeJSON() async { diff --git a/lib/ui/MainPageState.dart b/lib/ui/MainPageState.dart index 98b0cbf..065f7f8 100644 --- a/lib/ui/MainPageState.dart +++ b/lib/ui/MainPageState.dart @@ -5,6 +5,7 @@ import 'package:background_fetch/background_fetch.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; +import 'package:jaga_jindan/type/JagaJindanData.dart'; import 'package:jaga_jindan/ui/component/JagaJindanForm.dart'; import 'package:jaga_jindan/ui/component/setting.dart'; import 'package:jaga_jindan/util/notify.dart'; @@ -14,20 +15,6 @@ import 'package:package_info/package_info.dart'; import 'MainPage.dart'; -survey() async { - -} - -void backgroundFetchHeadlessTask(String taskId) async { - survey(); - - BackgroundFetch.scheduleTask(TaskConfig( - enableHeadless: true, - startOnBoot: true, - stopOnTerminate: false, - taskId: 'com.nnnlog.survey', delay: 10000)); //TODO -} - class MainPageState extends State { final formKey = GlobalKey(); String edu = "서울특별시", school = "1", selectedSchoolCode = ""; @@ -40,13 +27,6 @@ class MainPageState extends State { Future initBackgroundService() async { if (!initBackground) { BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); - - BackgroundFetch.scheduleTask(TaskConfig( - enableHeadless: true, - startOnBoot: true, - stopOnTerminate: false, - taskId: 'com.nnnlog.survey', - delay: 1000)); } initBackground = true; } @@ -110,7 +90,7 @@ class MainPageState extends State { alignment: Alignment.bottomRight, child: FloatingActionButton( onPressed: () { - if (formKey.currentState.validate()) { + if (formKey.currentState?.validate() == true) { sendSurvey(this.widget.data); } }, diff --git a/lib/ui/component/JagaJindanForm.dart b/lib/ui/component/JagaJindanForm.dart index f22a212..079571d 100644 --- a/lib/ui/component/JagaJindanForm.dart +++ b/lib/ui/component/JagaJindanForm.dart @@ -13,12 +13,12 @@ JagaJindanForm(MainPageState state) { style: TextStyle( //color: Colors.black, fontSize: - Theme.of(state.context).textTheme.headline4.fontSize)), + Theme.of(state.context).textTheme.headline4?.fontSize)), new Padding(padding: EdgeInsets.only(bottom: 50)), TextFormField( decoration: const InputDecoration(hintText: "이름을 입력하세요."), - validator: (value) { - if (value.isEmpty) { + validator: (String value) { + if (value?.isEmpty == true) { return "이름을 입력하세요."; } return null; @@ -38,7 +38,7 @@ JagaJindanForm(MainPageState state) { decoration: const InputDecoration(hintText: "생년월일을 입력하세요. (YYMMDD)"), validator: (value) { - if (value.length != 6) { + if (value?.length != 6) { return "생년월일을 올바르게 입력하세요."; } return null; @@ -75,7 +75,7 @@ JagaJindanForm(MainPageState state) { decoration: const InputDecoration(hintText: "비밀번호를 입력하세요."), obscureText: true, validator: (value) { - if (value.length != 4) { + if (value?.length != 4) { return "비밀번호 4자리를 입력하세요."; } return null; @@ -91,6 +91,7 @@ JagaJindanForm(MainPageState state) { title: const Text('앱 시작 시 자가진단 제출'), value: state.widget.data.startup, onChanged: (bool value) { + if (!(value is bool)) return; state.setState(() { if (value) { showDialog( diff --git a/lib/ui/component/searchSchool.dart b/lib/ui/component/searchSchool.dart index 9a6e9ab..dee6a70 100644 --- a/lib/ui/component/searchSchool.dart +++ b/lib/ui/component/searchSchool.dart @@ -25,6 +25,7 @@ searchSchool(MainPageState state) { DropdownMenuItem(child: Text(e.key), value: e.key)) .toList(), onChanged: (String value) { + if (!(value is String)) return; _setState(() { state.edu = value; }); @@ -54,6 +55,7 @@ searchSchool(MainPageState state) { )) .toList(), onChanged: (String value) { + if (!(value is String)) return; _setState(() { state.school = value; }); @@ -79,7 +81,7 @@ searchSchool(MainPageState state) { state.searchSchoolController.text, state.edu, state.school); - //for (var s in tmp) toast(s.code); + //tmp = []; _setState(() { state.schools = tmp; @@ -115,6 +117,7 @@ searchSchool(MainPageState state) { )) .toList(), onChanged: (String value) { + if (!(value is String)) return; _setState(() { state.selectedSchoolCode = value; }); @@ -140,7 +143,7 @@ searchSchool(MainPageState state) { return; } state.widget.data.school = state.selectedSchoolCode; - state.widget.data.edu = URL_LIST[state.edu]; + state.widget.data.edu = URL_LIST[state.edu].toString(); state.widget.writeJSON(); state.setState(() { state.widget.schoolController.text = state.selectedSchoolCode; diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index ee2b96d..f9e3987 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:jaga_jindan/ui/MainPageState.dart'; +import 'package:jaga_jindan/util/sendSurvey.dart'; +import 'package:timezone/standalone.dart' as tz; import 'package:url_launcher/url_launcher.dart'; showCredit(MainPageState state, String appVer, String newVer) async { @@ -18,6 +20,7 @@ showCredit(MainPageState state, String appVer, String newVer) async { title: const Text('자가진단 결과 알림으로 받기'), value: state.widget.data.useNotification, onChanged: (bool value) { + if (!(value is bool)) return; _setState(() { state.widget.data.useNotification = value; state.widget.writeJSON(); @@ -28,11 +31,57 @@ showCredit(MainPageState state, String appVer, String newVer) async { title: const Text('매일 한 번만 자동 제출'), value: state.widget.data.submitLimitation, onChanged: (bool value) { + if (!(value is bool)) return; _setState(() { state.widget.data.submitLimitation = value; state.widget.writeJSON(); }); }), + Row(children: [ + new Flexible( + child: new FocusScope( + node: new FocusScopeNode(), + canRequestFocus: false, + child: TextFormField( + decoration: const InputDecoration( + hintText: "자가진단 자동 제출 시간"), + controller: state.widget.timeController, + ))), + FlatButton( + child: Icon(Icons.alarm), + onPressed: () async { + final TimeOfDay picked = await showTimePicker( + context: context, + initialTime: TimeOfDay.fromDateTime( + tz.TZDateTime.now(tz.getLocation('Asia/Seoul'))), + ); + + _setState(() { + var today = + tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); + + state.widget.data.submitTime = tz.TZDateTime.from( + new tz.TZDateTime( + tz.getLocation('Asia/Seoul'), + today.year, + today.month, + today.day, + picked.hour, + picked.minute), + tz.getLocation('Asia/Seoul')); + state.widget.timeController.text = + "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.hour}"; + state.widget.writeJSON(); + + setBackgroundProcess(state.widget.data); + }); + }, + minWidth: 0, + height: 0, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: EdgeInsets.all(3), + ), + ]), Divider( color: Colors.black38, height: 50, diff --git a/lib/util/RSAEncrypt.dart b/lib/util/RSAEncrypt.dart index 4e5b392..658cc0a 100644 --- a/lib/util/RSAEncrypt.dart +++ b/lib/util/RSAEncrypt.dart @@ -1,9 +1,9 @@ import 'package:encrypt/encrypt.dart'; +import 'package:pointycastle/asymmetric/api.dart'; String encrypt(String plain) { final parser = RSAKeyParser(); - final encrypter = - Encrypter(RSA(publicKey: parser.parse('''-----BEGIN PUBLIC KEY----- + var parsed = parser.parse('''-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA81dCnCKt0NVH7j5Oh2+S GgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8 jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nC @@ -11,6 +11,9 @@ wmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8a vvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdu tJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMW tQIDAQAB ------END PUBLIC KEY-----'''))); +-----END PUBLIC KEY-----'''); + RSAPublicKey key = new RSAPublicKey(parsed.modulus, parsed.exponent); + final encrypter = + Encrypter(RSA(publicKey: key)); return encrypter.encrypt(plain).base64; } diff --git a/lib/util/school.dart b/lib/util/school.dart index eb80bae..2fef23b 100644 --- a/lib/util/school.dart +++ b/lib/util/school.dart @@ -29,7 +29,7 @@ Future> getSchoolList( try { var res = jsonDecode( (await http.get(Uri.https("hcs.eduro.go.kr", "/v2/searchSchool", { - 'lctnScCode': EDU_LIST[region], + 'lctnScCode': EDU_LIST[region].toString(), 'schulCrseScCode': schulCrseScCode, 'orgName': name, 'loginType': 'school' diff --git a/lib/util/sendSurvey.dart b/lib/util/sendSurvey.dart index ca17e5e..e9529a2 100644 --- a/lib/util/sendSurvey.dart +++ b/lib/util/sendSurvey.dart @@ -1,10 +1,56 @@ import 'dart:convert'; +import 'package:background_fetch/background_fetch.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; import 'package:jaga_jindan/type/JagaJindanData.dart'; import 'package:jaga_jindan/util/RSAEncrypt.dart'; +import 'package:jaga_jindan/util/internalIO.dart'; import 'package:jaga_jindan/util/notify.dart'; +import 'package:timezone/standalone.dart' as tz; + +void backgroundFetchHeadlessTask(String taskId) async { + BackgroundFetch.stop(taskId); + try { + JagaJindanData dat = JagaJindanData.readFromJSON(await readInternal()); + if (dat != null && taskId == 'com.nnnlog.survey') sendSurvey(dat, true); + } catch (e) {} finally { + BackgroundFetch.scheduleTask(TaskConfig( + enableHeadless: true, + startOnBoot: true, + stopOnTerminate: false, + requiresStorageNotLow: true, + requiredNetworkType: NetworkType.ANY, + taskId: 'com.nnnlog.survey', + delay: (3600 * 24) * 1000)); + } +} + +void setBackgroundProcess(JagaJindanData dat) { + var tm = dat.submitTime; + if (tm == null || tm.minute == null || tm.hour == null) return; + + BackgroundFetch.stop("com.nnnlog.survey"); + + DateTime currTime = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')), target = tm.add(Duration()); + + if (target.isBefore(currTime)) { + target = target.add(Duration(days: 1)); + } + + var diff = target.difference(currTime); + + BackgroundFetch.scheduleTask(TaskConfig( + enableHeadless: true, + startOnBoot: true, + stopOnTerminate: false, + requiresStorageNotLow: true, + requiredNetworkType: NetworkType.ANY, + taskId: 'com.nnnlog.survey', + delay: + (diff.inHours * 3600 + diff.inMinutes * 60 + diff.inSeconds) * 1000)); +} void showSurveyResult( bool success, String message, JagaJindanData credentials) { @@ -124,7 +170,6 @@ void sendSurvey(JagaJindanData credentials, [bool byAutomatic = false]) async { "자가진단 설문이 ${DateTime.now().toString().substring(0, 19)}에 제출되었습니다.", credentials); } catch (e, s) { - debugPrint(e.toString()); showSurveyResult( false, "인증 정보를 한번 더 확인해주세요.\n오류가 계속 발생하는 경우 개발자에게 알려주세요.", credentials); } diff --git a/pubspec.lock b/pubspec.lock index 5ff5ae3..de3baf0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -323,7 +323,7 @@ packages: source: hosted version: "0.2.19-nullsafety.6" timezone: - dependency: transitive + dependency: "direct main" description: name: timezone url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 83fb569..5befc91 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: 'none' version: 0.3.0 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.11.0 <3.0.0" dependencies: flutter: @@ -21,6 +21,7 @@ dependencies: url_launcher: ^5.7.10 package_info: ^0.4.3+2 background_fetch: ^0.6.0 + timezone: ^0.5.9 dev_dependencies: flutter_test: From 64ae8982d469ee9c814a8b96a769a767e3e61b8a Mon Sep 17 00:00:00 2001 From: NLOG Date: Mon, 28 Dec 2020 14:32:30 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=EC=95=B1=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9E=90=EA=B0=80=EC=A7=84=EB=8B=A8=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94,=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EC=A0=9C=EC=B6=9C=20=EC=98=B5=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/type/JagaJindanData.dart | 5 +- lib/ui/MainPage.dart | 4 +- lib/ui/component/JagaJindanForm.dart | 4 +- lib/ui/component/setting.dart | 104 ++++++++++++++++----------- 4 files changed, 72 insertions(+), 45 deletions(-) diff --git a/lib/type/JagaJindanData.dart b/lib/type/JagaJindanData.dart index d48613a..5328539 100644 --- a/lib/type/JagaJindanData.dart +++ b/lib/type/JagaJindanData.dart @@ -5,7 +5,7 @@ class JagaJindanData { bool agree = false, startup = false, useNotification = false, - submitLimitation = false; + submitLimitation = false, autoSubmit = false; tz.TZDateTime submitTime; static JagaJindanData readFromJSON(dynamic json) { @@ -23,6 +23,7 @@ class JagaJindanData { json["startup"] ?? false, json["noti"] ?? false, json["submitLimitation"] ?? false, + json["autoSubmit"] ?? false, tm); } @@ -36,6 +37,7 @@ class JagaJindanData { this.startup, this.useNotification, this.submitLimitation, + this.autoSubmit, this.submitTime); dynamic toJSON() { @@ -49,6 +51,7 @@ class JagaJindanData { "startup": this.startup, "noti": this.useNotification, "submitLimitation": this.submitLimitation, + "autoSubmit": this.autoSubmit, "submitTime": this.submitTime?.toString() }; } diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index 4b68564..86cd948 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -10,7 +10,7 @@ import 'component/agree.dart'; class MainPage extends StatefulWidget { JagaJindanData data = - JagaJindanData("", "", "", "", "", false, false, false, false, null); + JagaJindanData("", "", "", "", "", false, false, false, false, false, null); TextEditingController nameController = TextEditingController(), birthdayController = TextEditingController(), @@ -34,7 +34,7 @@ class MainPage extends StatefulWidget { setBackgroundProcess(this.data); - if (this.data.startup) sendSurvey(this.data, true); + //if (this.data.startup) sendSurvey(this.data, true); agree(pageState); pageState.setState(() {}); diff --git a/lib/ui/component/JagaJindanForm.dart b/lib/ui/component/JagaJindanForm.dart index 079571d..e7f7bb2 100644 --- a/lib/ui/component/JagaJindanForm.dart +++ b/lib/ui/component/JagaJindanForm.dart @@ -87,7 +87,7 @@ JagaJindanForm(MainPageState state) { controller: state.widget.passwordController, ) ), - CheckboxListTile( + /*CheckboxListTile( title: const Text('앱 시작 시 자가진단 제출'), value: state.widget.data.startup, onChanged: (bool value) { @@ -137,7 +137,7 @@ JagaJindanForm(MainPageState state) { } }); }, - ), + ),*/ ], )); } diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index f9e3987..c0d59a4 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -1,3 +1,4 @@ +import 'package:background_fetch/background_fetch.dart'; import 'package:flutter/material.dart'; import 'package:jaga_jindan/ui/MainPageState.dart'; import 'package:jaga_jindan/util/sendSurvey.dart'; @@ -37,51 +38,74 @@ showCredit(MainPageState state, String appVer, String newVer) async { state.widget.writeJSON(); }); }), - Row(children: [ - new Flexible( - child: new FocusScope( - node: new FocusScopeNode(), - canRequestFocus: false, - child: TextFormField( - decoration: const InputDecoration( - hintText: "자가진단 자동 제출 시간"), - controller: state.widget.timeController, - ))), - FlatButton( - child: Icon(Icons.alarm), - onPressed: () async { - final TimeOfDay picked = await showTimePicker( - context: context, - initialTime: TimeOfDay.fromDateTime( - tz.TZDateTime.now(tz.getLocation('Asia/Seoul'))), - ); - + CheckboxListTile( + contentPadding: EdgeInsets.zero, + title: const Text('자동 제출 활성화'), + value: state.widget.data.autoSubmit, + onChanged: (bool value) { + if (!(value is bool)) return; _setState(() { - var today = + state.widget.data.autoSubmit = value; + state.widget.data.submitTime = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); - - state.widget.data.submitTime = tz.TZDateTime.from( - new tz.TZDateTime( - tz.getLocation('Asia/Seoul'), - today.year, - today.month, - today.day, - picked.hour, - picked.minute), - tz.getLocation('Asia/Seoul')); state.widget.timeController.text = - "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.hour}"; - state.widget.writeJSON(); + "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.minute}"; - setBackgroundProcess(state.widget.data); + print(state.widget.timeController.text); + state.widget.writeJSON(); }); - }, - minWidth: 0, - height: 0, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: EdgeInsets.all(3), - ), - ]), + + if (value) setBackgroundProcess(state.widget.data); + else BackgroundFetch.stop("com.nnnlog.survey"); + }), + Visibility( + child: Row(children: [ + new Flexible( + child: new FocusScope( + node: new FocusScopeNode(), + canRequestFocus: false, + child: TextFormField( + decoration: const InputDecoration( + hintText: "자가진단 자동 제출 시간"), + controller: state.widget.timeController, + ))), + FlatButton( + child: Icon(Icons.alarm), + onPressed: () async { + final TimeOfDay picked = await showTimePicker( + context: context, + initialTime: TimeOfDay.fromDateTime( + state.widget.data.submitTime), + ); + + _setState(() { + var today = + tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); + + state.widget.data.submitTime = tz.TZDateTime.from( + new tz.TZDateTime( + tz.getLocation('Asia/Seoul'), + today.year, + today.month, + today.day, + picked.hour, + picked.minute), + tz.getLocation('Asia/Seoul')); + state.widget.timeController.text = + "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.minute}"; + state.widget.writeJSON(); + + setBackgroundProcess(state.widget.data); + }); + }, + minWidth: 0, + height: 0, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: EdgeInsets.all(3), + ), + ]), + visible: state.widget.data.autoSubmit, + ), Divider( color: Colors.black38, height: 50, From ef4f8f45eb79d576f88e547234899e41581c3bcb Mon Sep 17 00:00:00 2001 From: NLOG Date: Tue, 29 Dec 2020 08:58:23 +0900 Subject: [PATCH 06/10] =?UTF-8?q?=EB=B0=B1=EA=B7=B8=EB=9D=BC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=20=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/MainPage.dart | 2 +- lib/ui/MainPageState.dart | 8 +++- lib/ui/component/setting.dart | 32 +++++++------- lib/util/notify.dart | 78 ++++++++++++++++++++--------------- lib/util/sendSurvey.dart | 45 +++++++++++++------- 5 files changed, 98 insertions(+), 67 deletions(-) diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index 86cd948..a742056 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -30,7 +30,7 @@ class MainPage extends StatefulWidget { this.passwordController.text = this.data.password; var tm = this.data.submitTime; - if (tm.minute != null && tm.hour != null) this.timeController.text = "${tm.hour}:${tm.hour}"; + if (tm.minute != null && tm.hour != null) this.timeController.text = "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; setBackgroundProcess(this.data); diff --git a/lib/ui/MainPageState.dart b/lib/ui/MainPageState.dart index 065f7f8..a11e797 100644 --- a/lib/ui/MainPageState.dart +++ b/lib/ui/MainPageState.dart @@ -5,7 +5,6 @@ import 'package:background_fetch/background_fetch.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; -import 'package:jaga_jindan/type/JagaJindanData.dart'; import 'package:jaga_jindan/ui/component/JagaJindanForm.dart'; import 'package:jaga_jindan/ui/component/setting.dart'; import 'package:jaga_jindan/util/notify.dart'; @@ -27,6 +26,13 @@ class MainPageState extends State { Future initBackgroundService() async { if (!initBackground) { BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); + BackgroundFetch.configure( + BackgroundFetchConfig( + minimumFetchInterval: 15, + stopOnTerminate: false, + enableHeadless: true, + forceAlarmManager: true, + startOnBoot: true), backgroundFetchHeadlessTask); } initBackground = true; } diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index c0d59a4..5380853 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -46,17 +46,18 @@ showCredit(MainPageState state, String appVer, String newVer) async { if (!(value is bool)) return; _setState(() { state.widget.data.autoSubmit = value; - state.widget.data.submitTime = + var tm = state.widget.data.submitTime = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); state.widget.timeController.text = - "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.minute}"; + "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; - print(state.widget.timeController.text); state.widget.writeJSON(); }); - if (value) setBackgroundProcess(state.widget.data); - else BackgroundFetch.stop("com.nnnlog.survey"); + if (value) + setBackgroundProcess(state.widget.data); + else + BackgroundFetch.stop("com.nnnlog.survey"); }), Visibility( child: Row(children: [ @@ -82,17 +83,18 @@ showCredit(MainPageState state, String appVer, String newVer) async { var today = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); - state.widget.data.submitTime = tz.TZDateTime.from( - new tz.TZDateTime( - tz.getLocation('Asia/Seoul'), - today.year, - today.month, - today.day, - picked.hour, - picked.minute), - tz.getLocation('Asia/Seoul')); + var tm = state.widget.data.submitTime = + tz.TZDateTime.from( + new tz.TZDateTime( + tz.getLocation('Asia/Seoul'), + today.year, + today.month, + today.day, + picked.hour, + picked.minute), + tz.getLocation('Asia/Seoul')); state.widget.timeController.text = - "${state.widget.data.submitTime.hour}:${state.widget.data.submitTime.minute}"; + "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; state.widget.writeJSON(); setBackgroundProcess(state.widget.data); diff --git a/lib/util/notify.dart b/lib/util/notify.dart index f9d61f6..f439c1d 100644 --- a/lib/util/notify.dart +++ b/lib/util/notify.dart @@ -21,43 +21,53 @@ Future selectNotification(String payload) async { if (payload != null) { if (payload.startsWith("https://") || payload.startsWith("http://")) { launch(payload); - } else toast(payload); + } else + toast(payload); } } -FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); -const AndroidInitializationSettings initializationSettingsAndroid = - AndroidInitializationSettings('app_icon'); -final IOSInitializationSettings initializationSettingsIOS = - IOSInitializationSettings( - requestSoundPermission: false, - requestBadgePermission: false, - requestAlertPermission: false, - onDidReceiveLocalNotification: onDidReceiveLocalNotification, -); -final MacOSInitializationSettings initializationSettingsMacOS = - MacOSInitializationSettings( - requestAlertPermission: false, - requestBadgePermission: false, - requestSoundPermission: false); -final InitializationSettings initializationSettings = InitializationSettings( - android: initializationSettingsAndroid, - iOS: initializationSettingsIOS, - macOS: initializationSettingsMacOS); - -const AndroidNotificationDetails androidPlatformChannelSpecifics = - AndroidNotificationDetails( - 'com.nlog.flutterlocalnotifications.ScheduledNotificationBootReceiver', - '자가진단 자동화', - '자동으로 자가진단 설문을 제출합니다.', - importance: Importance.max, - priority: Priority.high, - showWhen: false); -const NotificationDetails platformChannelSpecifics = - NotificationDetails(android: androidPlatformChannelSpecifics); - -void initNotification() async { +FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; + +MacOSInitializationSettings initializationSettingsMacOS; + +AndroidNotificationDetails androidPlatformChannelSpecifics; + +NotificationDetails platformChannelSpecifics; + +Future initNotification() async { + flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + + AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('app_icon'); + IOSInitializationSettings initializationSettingsIOS = + IOSInitializationSettings( + requestSoundPermission: false, + requestBadgePermission: false, + requestAlertPermission: false, + onDidReceiveLocalNotification: onDidReceiveLocalNotification, + ); + + initializationSettingsMacOS = MacOSInitializationSettings( + requestAlertPermission: false, + requestBadgePermission: false, + requestSoundPermission: false); + + InitializationSettings initializationSettings = InitializationSettings( + android: initializationSettingsAndroid, + iOS: initializationSettingsIOS, + macOS: initializationSettingsMacOS); + + androidPlatformChannelSpecifics = AndroidNotificationDetails( + 'com.nlog.flutterlocalnotifications.ScheduledNotificationBootReceiver', + '자가진단 자동화', + '자동으로 자가진단 설문을 제출합니다.', + importance: Importance.max, + priority: Priority.high, + showWhen: false); + + platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + await flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: selectNotification); } diff --git a/lib/util/sendSurvey.dart b/lib/util/sendSurvey.dart index e9529a2..6d9706f 100644 --- a/lib/util/sendSurvey.dart +++ b/lib/util/sendSurvey.dart @@ -1,39 +1,53 @@ import 'dart:convert'; import 'package:background_fetch/background_fetch.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; import 'package:jaga_jindan/type/JagaJindanData.dart'; import 'package:jaga_jindan/util/RSAEncrypt.dart'; import 'package:jaga_jindan/util/internalIO.dart'; import 'package:jaga_jindan/util/notify.dart'; import 'package:timezone/standalone.dart' as tz; +import 'package:timezone/data/latest.dart' as tzInit; + +const SURVEY_TASK_ID = "com.nlog.jaga_jindan.survey"; +const FB_TASK_ID = "com.nlog.jaga_jindan.fb"; void backgroundFetchHeadlessTask(String taskId) async { - BackgroundFetch.stop(taskId); try { + await Future.any([ + initNotification(), + Future.delayed(const Duration(seconds: 5)) + ]); + + tzInit.initializeTimeZones(); + + BackgroundFetch.stop(taskId); JagaJindanData dat = JagaJindanData.readFromJSON(await readInternal()); - if (dat != null && taskId == 'com.nnnlog.survey') sendSurvey(dat, true); - } catch (e) {} finally { + if (dat != null) { + if (taskId == SURVEY_TASK_ID) sendSurvey(dat, true); + setBackgroundProcess(dat); + } + } catch (e) { + noti("오류가 발생했습니다.", "자동 제출을 활성화하려면 앱을 켜주세요."); + } finally { BackgroundFetch.scheduleTask(TaskConfig( enableHeadless: true, startOnBoot: true, stopOnTerminate: false, - requiresStorageNotLow: true, - requiredNetworkType: NetworkType.ANY, - taskId: 'com.nnnlog.survey', - delay: (3600 * 24) * 1000)); + taskId: FB_TASK_ID, + forceAlarmManager: true, + delay: (30 * 1000))); } } void setBackgroundProcess(JagaJindanData dat) { + BackgroundFetch.stop(SURVEY_TASK_ID); + var tm = dat.submitTime; if (tm == null || tm.minute == null || tm.hour == null) return; - BackgroundFetch.stop("com.nnnlog.survey"); - - DateTime currTime = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')), target = tm.add(Duration()); + DateTime currTime = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')), + target = tm.add(Duration()); if (target.isBefore(currTime)) { target = target.add(Duration(days: 1)); @@ -45,11 +59,10 @@ void setBackgroundProcess(JagaJindanData dat) { enableHeadless: true, startOnBoot: true, stopOnTerminate: false, - requiresStorageNotLow: true, - requiredNetworkType: NetworkType.ANY, - taskId: 'com.nnnlog.survey', + taskId: SURVEY_TASK_ID, + forceAlarmManager: true, delay: - (diff.inHours * 3600 + diff.inMinutes * 60 + diff.inSeconds) * 1000)); + diff.inSeconds * 1000)); } void showSurveyResult( From e92844fccb009263e94db87334cd09742be6a868 Mon Sep 17 00:00:00 2001 From: NLOG Date: Tue, 29 Dec 2020 15:10:27 +0900 Subject: [PATCH 07/10] =?UTF-8?q?=EB=B0=B1=EA=B7=B8=EB=9D=BC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=20=EA=B4=80=EB=A0=A8=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=95=84=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/MainPage.dart | 3 ++- lib/ui/component/setting.dart | 7 ++++--- lib/util/sendSurvey.dart | 11 +++++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index a742056..cd2e213 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -32,7 +32,8 @@ class MainPage extends StatefulWidget { var tm = this.data.submitTime; if (tm.minute != null && tm.hour != null) this.timeController.text = "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; - setBackgroundProcess(this.data); + //setBackgroundProcess(this.data); + backgroundFetchHeadlessTask(FB_TASK_ID); //if (this.data.startup) sendSurvey(this.data, true); diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index 5380853..2dcee66 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -79,7 +79,7 @@ showCredit(MainPageState state, String appVer, String newVer) async { state.widget.data.submitTime), ); - _setState(() { + _setState(() async { var today = tz.TZDateTime.now(tz.getLocation('Asia/Seoul')); @@ -95,9 +95,10 @@ showCredit(MainPageState state, String appVer, String newVer) async { tz.getLocation('Asia/Seoul')); state.widget.timeController.text = "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; - state.widget.writeJSON(); + await state.widget.writeJSON(); - setBackgroundProcess(state.widget.data); + //setBackgroundProcess(state.widget.data); + backgroundFetchHeadlessTask(FB_TASK_ID); }); }, minWidth: 0, diff --git a/lib/util/sendSurvey.dart b/lib/util/sendSurvey.dart index 6d9706f..3030a38 100644 --- a/lib/util/sendSurvey.dart +++ b/lib/util/sendSurvey.dart @@ -13,6 +13,8 @@ const SURVEY_TASK_ID = "com.nlog.jaga_jindan.survey"; const FB_TASK_ID = "com.nlog.jaga_jindan.fb"; void backgroundFetchHeadlessTask(String taskId) async { + BackgroundFetch.stop(SURVEY_TASK_ID); + try { await Future.any([ initNotification(), @@ -23,6 +25,7 @@ void backgroundFetchHeadlessTask(String taskId) async { BackgroundFetch.stop(taskId); JagaJindanData dat = JagaJindanData.readFromJSON(await readInternal()); + if (dat != null) { if (taskId == SURVEY_TASK_ID) sendSurvey(dat, true); setBackgroundProcess(dat); @@ -34,9 +37,9 @@ void backgroundFetchHeadlessTask(String taskId) async { enableHeadless: true, startOnBoot: true, stopOnTerminate: false, - taskId: FB_TASK_ID, forceAlarmManager: true, - delay: (30 * 1000))); + taskId: FB_TASK_ID, + delay: (10 * 60 * 1000))); } } @@ -59,10 +62,10 @@ void setBackgroundProcess(JagaJindanData dat) { enableHeadless: true, startOnBoot: true, stopOnTerminate: false, - taskId: SURVEY_TASK_ID, forceAlarmManager: true, + taskId: SURVEY_TASK_ID, delay: - diff.inSeconds * 1000)); + (diff.inSeconds + 1) * 1000)); } void showSurveyResult( From ed9a14662ee31f6dd0c51845f4b708ea6a5a8846 Mon Sep 17 00:00:00 2001 From: NLOG Date: Tue, 29 Dec 2020 15:10:47 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=ED=95=99=EA=B5=90=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20UI=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/component/searchSchool.dart | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/ui/component/searchSchool.dart b/lib/ui/component/searchSchool.dart index dee6a70..f6bfdf8 100644 --- a/lib/ui/component/searchSchool.dart +++ b/lib/ui/component/searchSchool.dart @@ -82,7 +82,6 @@ searchSchool(MainPageState state) { state.edu, state.school); - //tmp = []; _setState(() { state.schools = tmp; if (tmp.isEmpty) { @@ -99,14 +98,7 @@ searchSchool(MainPageState state) { padding: EdgeInsets.all(3), ) ]), - Divider( - color: Colors.black38, - height: 50, - thickness: 1, - indent: 0, - endIndent: 0, - ), - //Text("검색 결과") + Container(margin: EdgeInsets.all(5),), DropdownButton( icon: Icon(Icons.keyboard_arrow_down), items: state.schools From 994e180d3335f958ff729d459b7de170f89b6289 Mon Sep 17 00:00:00 2001 From: nnnlog Date: Thu, 31 Dec 2020 09:32:48 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=EB=88=88=EC=97=90=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ui/MainPage.dart | 8 +++++--- lib/ui/component/setting.dart | 2 +- lib/util/sendSurvey.dart | 31 +++++++++++++++++-------------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/ui/MainPage.dart b/lib/ui/MainPage.dart index cd2e213..cb704de 100644 --- a/lib/ui/MainPage.dart +++ b/lib/ui/MainPage.dart @@ -9,8 +9,8 @@ import 'MainPageState.dart'; import 'component/agree.dart'; class MainPage extends StatefulWidget { - JagaJindanData data = - JagaJindanData("", "", "", "", "", false, false, false, false, false, null); + JagaJindanData data = JagaJindanData( + "", "", "", "", "", false, false, false, false, false, null); TextEditingController nameController = TextEditingController(), birthdayController = TextEditingController(), @@ -30,7 +30,9 @@ class MainPage extends StatefulWidget { this.passwordController.text = this.data.password; var tm = this.data.submitTime; - if (tm.minute != null && tm.hour != null) this.timeController.text = "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; + if (tm != null && tm.minute != null && tm.hour != null) + this.timeController.text = + "${tm.hour < 10 ? '0' : ''}${tm.hour}:${tm.minute < 10 ? '0' : ''}${tm.minute}"; //setBackgroundProcess(this.data); backgroundFetchHeadlessTask(FB_TASK_ID); diff --git a/lib/ui/component/setting.dart b/lib/ui/component/setting.dart index 2dcee66..ec34d7b 100644 --- a/lib/ui/component/setting.dart +++ b/lib/ui/component/setting.dart @@ -57,7 +57,7 @@ showCredit(MainPageState state, String appVer, String newVer) async { if (value) setBackgroundProcess(state.widget.data); else - BackgroundFetch.stop("com.nnnlog.survey"); + BackgroundFetch.stop(SURVEY_TASK_ID); }), Visibility( child: Row(children: [ diff --git a/lib/util/sendSurvey.dart b/lib/util/sendSurvey.dart index 3030a38..cdf63cf 100644 --- a/lib/util/sendSurvey.dart +++ b/lib/util/sendSurvey.dart @@ -13,7 +13,7 @@ const SURVEY_TASK_ID = "com.nlog.jaga_jindan.survey"; const FB_TASK_ID = "com.nlog.jaga_jindan.fb"; void backgroundFetchHeadlessTask(String taskId) async { - BackgroundFetch.stop(SURVEY_TASK_ID); + await BackgroundFetch.stop(SURVEY_TASK_ID); try { await Future.any([ @@ -23,17 +23,22 @@ void backgroundFetchHeadlessTask(String taskId) async { tzInit.initializeTimeZones(); - BackgroundFetch.stop(taskId); - JagaJindanData dat = JagaJindanData.readFromJSON(await readInternal()); + var json = await readInternal(); + if (jsonEncode(json) == "{}") { + throw new Error(); + } + JagaJindanData dat = JagaJindanData.readFromJSON(json); if (dat != null) { - if (taskId == SURVEY_TASK_ID) sendSurvey(dat, true); - setBackgroundProcess(dat); + if (taskId == SURVEY_TASK_ID) await sendSurvey(dat, true); + await setBackgroundProcess(dat); } } catch (e) { - noti("오류가 발생했습니다.", "자동 제출을 활성화하려면 앱을 켜주세요."); + noti("오류가 발생했습니다.", e.toString()); } finally { - BackgroundFetch.scheduleTask(TaskConfig( + BackgroundFetch.finish(taskId); + await BackgroundFetch.stop(taskId); + await BackgroundFetch.scheduleTask(TaskConfig( enableHeadless: true, startOnBoot: true, stopOnTerminate: false, @@ -43,9 +48,7 @@ void backgroundFetchHeadlessTask(String taskId) async { } } -void setBackgroundProcess(JagaJindanData dat) { - BackgroundFetch.stop(SURVEY_TASK_ID); - +Future setBackgroundProcess(JagaJindanData dat) async { var tm = dat.submitTime; if (tm == null || tm.minute == null || tm.hour == null) return; @@ -58,14 +61,14 @@ void setBackgroundProcess(JagaJindanData dat) { var diff = target.difference(currTime); - BackgroundFetch.scheduleTask(TaskConfig( + await BackgroundFetch.stop(SURVEY_TASK_ID); + await BackgroundFetch.scheduleTask(TaskConfig( enableHeadless: true, startOnBoot: true, stopOnTerminate: false, forceAlarmManager: true, taskId: SURVEY_TASK_ID, - delay: - (diff.inSeconds + 1) * 1000)); + delay: diff.inMilliseconds)); } void showSurveyResult( @@ -76,7 +79,7 @@ void showSurveyResult( toast(message); } -void sendSurvey(JagaJindanData credentials, [bool byAutomatic = false]) async { +Future sendSurvey(JagaJindanData credentials, [bool byAutomatic = false]) async { try { String jwt = jsonDecode((await http.post( 'https://${credentials.edu}hcs.eduro.go.kr/v2/findUser', From 1fc2d0b9e98ea5bbb33ef768ddbb23eb3c3e5bac Mon Sep 17 00:00:00 2001 From: nnnlog Date: Wed, 6 Jan 2021 21:40:52 +0900 Subject: [PATCH 10/10] =?UTF-8?q?Fix=20#8,=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C=20=EA=BB=90=EC=9D=84=20=EB=95=8C=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=EB=90=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/util/sendSurvey.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/util/sendSurvey.dart b/lib/util/sendSurvey.dart index cdf63cf..9a6efdb 100644 --- a/lib/util/sendSurvey.dart +++ b/lib/util/sendSurvey.dart @@ -30,7 +30,7 @@ void backgroundFetchHeadlessTask(String taskId) async { JagaJindanData dat = JagaJindanData.readFromJSON(json); if (dat != null) { - if (taskId == SURVEY_TASK_ID) await sendSurvey(dat, true); + if (dat.autoSubmit && taskId == SURVEY_TASK_ID) await sendSurvey(dat, true); await setBackgroundProcess(dat); } } catch (e) { @@ -61,6 +61,7 @@ Future setBackgroundProcess(JagaJindanData dat) async { var diff = target.difference(currTime); + //TODO: Task Id에 목표 시간 넣어서 중복 제출 방지, 현재로썬 최선인듯 await BackgroundFetch.stop(SURVEY_TASK_ID); await BackgroundFetch.scheduleTask(TaskConfig( enableHeadless: true,