diff --git a/android/app/build.gradle b/android/app/build.gradle index 1a626d0..144136c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,7 +44,7 @@ android { targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -64,8 +64,8 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.google.firebase:firebase-analytics:17.2.0' testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c2c7103..687ca3f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -12,11 +12,11 @@ + android:value="@string/api_key" /> + + Geo Smart App + AIzaSyCjhBV5aq1gsTCYsr6QCCxYusFlBa3DEMs + \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties index 1441b1d..2324ab5 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000..f525c15 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/lib/bloc/setting.dart b/lib/bloc/setting.dart index 91b69fb..523e24b 100644 --- a/lib/bloc/setting.dart +++ b/lib/bloc/setting.dart @@ -27,6 +27,7 @@ class SettingBloc { SharedPreferences sharedPreferences = await this.getSharedPreferences(); _subject.sink.add(new SettingModel( sharedPreferences.getString(_host), + sharedPreferences.getString(_id), )); } diff --git a/lib/config.dart b/lib/config.dart index 9abac73..6dac79f 100644 --- a/lib/config.dart +++ b/lib/config.dart @@ -1,3 +1,4 @@ class Config { - static const String api = "http://192.168.1.6:8080"; + static const String api = "http://192.168.1.7:8080"; + static const bool dynamicHostSetting = false; } diff --git a/lib/main.dart b/lib/main.dart index ba7053b..b68c3ed 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:geo_app/page/startup.dart'; void main() => runApp(MyApp()); @@ -6,6 +7,7 @@ void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + SystemChrome.setEnabledSystemUIOverlays([]); return MaterialApp( title: 'Geo Smart App', theme: ThemeData( diff --git a/lib/model/response.dart b/lib/model/response.dart index 8e85890..0e151a6 100644 --- a/lib/model/response.dart +++ b/lib/model/response.dart @@ -7,6 +7,10 @@ class ResponseModel { status = json['status']; } + ResponseModel.fromNull() { + status = "Error"; + } + Map toJson() { final Map data = new Map(); data['status'] = this.status; diff --git a/lib/model/setting.dart b/lib/model/setting.dart index 3875178..1c4a1a7 100644 --- a/lib/model/setting.dart +++ b/lib/model/setting.dart @@ -2,5 +2,19 @@ class SettingModel { String host = ""; String id = ""; - SettingModel(this.host); + SettingModel(this.host, this.id); + + bool isNullHost() { + return (this.host == "" || this.host == null); + } + + bool isNullId() { + return (this.id == "" || this.id == null); + } + + bool isNullHostId(String operator) { + return (operator == "and") + ? isNullHost() && isNullId() + : isNullHost() || isNullId(); + } } diff --git a/lib/page/map.dart b/lib/page/map.dart index 6104806..59ec18f 100644 --- a/lib/page/map.dart +++ b/lib/page/map.dart @@ -5,9 +5,8 @@ import 'package:flutter/material.dart'; import 'package:geo_app/bloc/position_bloc.dart'; import 'package:geo_app/bloc/setting.dart'; import 'package:geo_app/model/position.dart'; +import 'package:geo_app/page/setting.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; -import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' - as bg; class Map extends StatefulWidget { Map({Key key, this.title}) : super(key: key); @@ -33,10 +32,23 @@ class _MapState extends State { String id; String host; + bool isGranted = false; + bool isTracking = false; + @override void initState() { - BackgroundLocation.startLocationService(); super.initState(); + BackgroundLocation.checkPermissions(); + BackgroundLocation.getPermissions( + onDenied: () { + isGranted = false; + print("Denied"); + }, + onGranted: () { + isGranted = true; + print("Granted"); + }, + ); _settingBloc = new SettingBloc(); _settingBloc.getSetting(); @@ -45,51 +57,65 @@ class _MapState extends State { this.id = settingModel.id; this.host = settingModel.host; + if (settingModel.isNullId()) { + Navigator.of(context).pushReplacement(new MaterialPageRoute( + builder: (BuildContext context) => Setting(), + )); + } + if (this.host != null && this.host != "") { setState(() { _positionBloc = new PositionBloc(settingModel); }); } }); - bg.BackgroundGeolocation.onLocation((bg.Location location) { - print('[location] - $location'); - }); - bg.BackgroundGeolocation.ready( - bg.Config( - desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH, - distanceFilter: 10.0, - stopOnTerminate: false, - startOnBoot: true, - debug: true, - logLevel: bg.Config.LOG_LEVEL_VERBOSE), - ).then((bg.State state) { - if (!state.enabled) { - bg.BackgroundGeolocation.start(); - } - }); - BackgroundLocation.getLocationUpdates((location) async { - print("Location Update"); - setState(() { - this.latitude = location.latitude; - this.longitude = location.longitude; - this.accuracy = location.accuracy; - this.altitude = location.altitude; - this.bearing = location.bearing; - this.speed = location.speed; - if (this._position != null) { - if (this._position.isValid()) { - print("VALID"); - if (_positionBloc != null) { - print("SEND"); - _positionBloc.sendPosition( - this._position.lat.toString(), - this._position.lng.toString(), - ); - } + BackgroundLocation.getLocationUpdates((location) async { + if (!isTracking) { + this.isTracking = true; + } + if (!isGranted) { + this.isGranted = true; + } + print("Location Updated"); + this.latitude = location.latitude; + this.longitude = location.longitude; + this.accuracy = location.accuracy; + this.altitude = location.altitude; + this.bearing = location.bearing; + this.speed = location.speed; + + if (this.id != null) { + this._position = Position( + id: this.id, + lat: this.latitude.toString(), + lng: this.longitude.toString(), + type: "user", + ); + } else { + BackgroundLocation.stopLocationService(); + Navigator.of(context).pushReplacement(new MaterialPageRoute( + builder: (BuildContext context) => Setting(), + )); + } + + if (this._position != null) { + if (this._position.isValid()) { + print("Valid Position"); + if (_positionBloc != null) { + print("Send Position " + + this._position.lat.toString() + + ", " + + this._position.lng.toString()); + _positionBloc.sendPosition( + this._position.lat.toString(), + this._position.lng.toString(), + ); } + } else { + print("Invalid Position"); } - }); + } }); } @@ -110,17 +136,51 @@ class _MapState extends State { myLocationButtonEnabled: true, onMapCreated: (GoogleMapController controller) { _controller.complete(controller); - print("Map Created"); }, ), + Container( + child: Image.asset("assets/images/logo.png"), + width: 70, + height: 70, + alignment: Alignment.topLeft, + margin: EdgeInsets.only(left: 10.0), + ), + Container( + child: FlatButton( + color: (isTracking) ? Colors.redAccent : Colors.green, + onPressed: toggleTracking, + child: Text( + (isTracking) ? "Stop Tracking" : "Start Tracking", + style: TextStyle(color: Colors.white), + ), + ), + margin: EdgeInsets.only(bottom: 50.0), + alignment: Alignment.bottomCenter, + ) ], ), ); } + toggleTracking() { + if (isGranted) { + if (isTracking) { + BackgroundLocation.stopLocationService(); + } else { + BackgroundLocation.startLocationService(); + } + setState(() { + isTracking = !isTracking; + }); + } else { + print("Access Denied"); + } + } + @override void dispose() { - BackgroundLocation.stopLocationService(); + print("Disposed"); super.dispose(); + BackgroundLocation.stopLocationService(); } } diff --git a/lib/page/setting.dart b/lib/page/setting.dart index d2ebf58..9830066 100644 --- a/lib/page/setting.dart +++ b/lib/page/setting.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:geo_app/bloc/setting.dart'; import 'package:geo_app/bloc/unique_id_bloc.dart'; +import 'package:geo_app/config.dart'; import 'package:geo_app/model/setting.dart'; import 'package:geo_app/page/map.dart'; @@ -25,23 +26,39 @@ class _SettingState extends State { _settingBloc.getSetting(); + if (!Config.dynamicHostSetting) { + _settingBloc.setSetting(new SettingModel(Config.api, null)); + } + _settingBloc.subject.listen((settingModel) { - this.id = settingModel.id; - this.host = settingModel.host; + if (!settingModel.isNullId()) { + this.id = settingModel.id; + } + if (!settingModel.isNullHost()) { + this.host = settingModel.host; + } _hostController.text = this.host; - if (this.host != null && this.host != "") { + if (settingModel.isNullId()) { + print("Requesting Unique ID"); _uniqueIDBloc = new UniqueIDBloc(settingModel); _uniqueIDBloc.getUniqueID(); } if (_uniqueIDBloc != null) { this._uniqueIDBloc.subject.listen((uniqueId) { + print("Your Unique ID " + uniqueId.id.toString()); if (uniqueId.id != null && uniqueId.id != "") { - Navigator.of(context).pushReplacement(new MaterialPageRoute( - builder: (BuildContext context) => Map(), - )); + if (!settingModel.isNullId()) { + Navigator.of(context).pushReplacement(new MaterialPageRoute( + builder: (BuildContext context) => Map(), + )); + } else { + this._settingBloc.setSetting( + new SettingModel(this._hostController.text, uniqueId.id), + ); + } } }); } @@ -78,7 +95,7 @@ class _SettingState extends State { FlatButton( onPressed: () { this._settingBloc.setSetting( - new SettingModel(this._hostController.text), + new SettingModel(this._hostController.text, null), ); }, child: Text("Save"), diff --git a/lib/page/startup.dart b/lib/page/startup.dart index ec2ddb2..e4ff4c5 100644 --- a/lib/page/startup.dart +++ b/lib/page/startup.dart @@ -2,8 +2,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:geo_app/bloc/setting.dart'; import 'package:geo_app/component/loader.dart'; -import 'package:geo_app/page/setting.dart'; import 'package:geo_app/page/map.dart'; +import 'package:geo_app/page/setting.dart'; class Startup extends StatefulWidget { @override @@ -22,8 +22,7 @@ class _StartupState extends State { _settingBloc.getSetting(); _settingBloc.subject.listen((settingModel) { - if ((settingModel.host == "" || settingModel.host == null) && - (settingModel.id == "" || settingModel.id == null)) { + if (settingModel.isNullHost() && settingModel.isNullId()) { Navigator.of(context).pushReplacement(new MaterialPageRoute( builder: (BuildContext context) => Setting(), )); diff --git a/lib/provider/position_provider.dart b/lib/provider/position_provider.dart index f9dd1a5..8be6737 100644 --- a/lib/provider/position_provider.dart +++ b/lib/provider/position_provider.dart @@ -23,6 +23,7 @@ class PositionProvider { ); return ResponseModel.fromJson(response.data); } on DioError catch (e) { + print(e); return ResponseModel.fromJson(e.response.data); } } diff --git a/pubspec.lock b/pubspec.lock index 118a21c..67e8050 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" adhara_socket_io: dependency: "direct main" description: @@ -14,7 +21,7 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.38.5" + version: "0.39.2+1" archive: dependency: transitive description: @@ -36,13 +43,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.4.0" - background_fetch: - dependency: transitive - description: - name: background_fetch - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.2" background_location: dependency: "direct main" description: @@ -133,19 +133,12 @@ packages: name: dio url: "https://pub.dartlang.org" source: hosted - version: "3.0.7" + version: "3.0.8" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" - flutter_background_geolocation: - dependency: "direct main" - description: - name: flutter_background_geolocation - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.5" flutter_test: dependency: "direct dev" description: flutter @@ -156,13 +149,6 @@ packages: description: flutter source: sdk version: "0.0.0" - front_end: - dependency: transitive - description: - name: front_end - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.27" glob: dependency: transitive description: @@ -190,7 +176,7 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.0+2" + version: "0.12.0+3" http_parser: dependency: transitive description: @@ -218,21 +204,14 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" json_serializable: dependency: "direct main" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "3.2.3" - kernel: - dependency: transitive - description: - name: kernel - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.27" + version: "3.2.5" logging: dependency: transitive description: @@ -370,7 +349,7 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "0.9.4+6" + version: "0.9.4+7" source_span: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b45659a..a3b18fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,15 +23,14 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 - google_maps_flutter: ^0.5.21+8 - background_location: ^0.0.9+1 + google_maps_flutter: ^0.5.21+15 + background_location: ^0.0.9 adhara_socket_io: ^0.4.1 http: ^0.12.0+2 json_serializable: ^3.2.3 - shared_preferences: ^0.5.4+3 + shared_preferences: ^0.5.6 rxdart: ^0.23.1 dio: ^3.0.7 - flutter_background_geolocation: ^1.4.5 dev_dependencies: flutter_test: @@ -52,6 +51,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - assets/images/server.png + - assets/images/logo.png # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware.