@@ -6,6 +6,7 @@ | |||
additional functionality it is fine to subclass or reimplement | |||
FlutterApplication and put your custom class here. --> | |||
<uses-permission android:name="android.permission.INTERNET" /> | |||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
<application | |||
android:name="${applicationName}" | |||
android:label="assetstock" | |||
@@ -9,6 +9,8 @@ import 'package:path_provider/path_provider.dart'; | |||
import 'main.dart'; | |||
import 'util/prefsKey.dart'; | |||
import 'util/dbHandler.dart'; | |||
import 'package:permission_handler/permission_handler.dart' as pHandler; | |||
class Home extends StatefulWidget { | |||
Home({Key key}) : super(key: key); | |||
@@ -43,12 +45,14 @@ class _HomeState extends State<Home> { | |||
super.initState(); | |||
WidgetsBinding.instance.addPostFrameCallback((_) async { | |||
// await loadMenu(); | |||
await util.permissionCheck(context,pHandler.Permission.storage,()async{print("storage permit granted!");},customMessage: " untuk menyimpan data backup"); | |||
}); | |||
} | |||
clearData(context)async{ | |||
String errMsg; | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File db = File(path); | |||
if(db.existsSync()){ | |||
@@ -120,7 +124,7 @@ class _HomeState extends State<Home> { | |||
padding: const EdgeInsets.only(bottom:45.0), | |||
child: FloatingActionButton( | |||
onPressed: ()async{ | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File db = File(path); | |||
if(db.existsSync()){ | |||
@@ -168,7 +172,27 @@ class _HomeState extends State<Home> { | |||
Text('Change Host Address',style: TextStyle(color: Colors.blueGrey,fontWeight: FontWeight.w500),) | |||
], | |||
), | |||
) | |||
), | |||
PopupMenuItem( | |||
value:'backup', | |||
child: Row( | |||
children: <Widget>[ | |||
Icon(Icons.save,color: Colors.black,), | |||
SizedBox(width: 10,), | |||
Text('Backup Data') | |||
], | |||
), | |||
), | |||
PopupMenuItem( | |||
value:'restore', | |||
child: Row( | |||
children: <Widget>[ | |||
Icon(Icons.sync,color: Colors.black,), | |||
SizedBox(width: 10,), | |||
Text('Restore Data') | |||
], | |||
), | |||
), | |||
], | |||
onSelected: (value)async{ | |||
if(value == "changeAddress"){ | |||
@@ -196,6 +220,108 @@ class _HomeState extends State<Home> { | |||
}); | |||
} | |||
if(value == 'backup'){ | |||
if(prefs.getString(keyClass.dbName) != null){ | |||
bool isBackup = await showDialog(context: context,builder: (context)=>AlertDialog( | |||
title: Text('Backup Data ?'), | |||
content: Text('Backup data akan menghapus dan mengganti data backup unit dan cabang sebelumnya.'), | |||
actions: <Widget>[ | |||
TextButton( | |||
child: Text('OK'), | |||
onPressed: ()async{ | |||
Navigator.pop(context,true); | |||
}, | |||
), | |||
TextButton( | |||
child: Text('Cancel'), | |||
onPressed: ()=>Navigator.pop(context,false), | |||
) | |||
], | |||
)); | |||
if(isBackup??false){ | |||
var result = await DBHelper.database.backupDb(context); | |||
util.showToast(result["STATUS"]==1?'NORMAL':'ERROR', result['MSG']); | |||
} | |||
} | |||
else{ | |||
util.showToast('ERROR', "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu."); | |||
} | |||
} | |||
if(value == 'restore'){ | |||
if(prefs.getString(keyClass.dbName) == null){ | |||
util.showToast('ERROR', "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu."); | |||
} | |||
else{ | |||
if(prefs.getString(keyClass.dbName) == prefs.getString(keyClass.backup_stock_id)){ | |||
String stock_taking_id = prefs.getString(keyClass.dbName); | |||
if(stock_taking_id!=null){ | |||
bool isRestore = await showDialog(context: context,builder: (context)=>AlertDialog( | |||
title: Text('Restore Data ?'), | |||
content: Text('Restore data akan menghapus dan mengganti data unit dan cabang yang ada dengan data backup.'), | |||
actions: <Widget>[ | |||
TextButton( | |||
child: Text('OK'), | |||
onPressed: ()async{ | |||
Navigator.pop(context,true); | |||
}, | |||
), | |||
TextButton( | |||
child: Text('Cancel'), | |||
onPressed: ()=>Navigator.pop(context,false), | |||
) | |||
], | |||
)); | |||
if(isRestore??false){ | |||
var response; | |||
bool isclear; | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File db = File(path); | |||
if(db.existsSync()){ | |||
isclear = await clearData(context); | |||
} | |||
else{ | |||
isclear = true; | |||
} | |||
if(isclear??false){ | |||
var result = await DBHelper.database.restoreDb(context); | |||
if(result["STATUS"]==1){ | |||
await prefs.remove(keyClass.dbName); | |||
// await prefs.remove(keyClass.lastDownload); | |||
// await prefs.remove(keyClass.lastUpload); | |||
// await prefs.remove(keyClass.targetProccess); | |||
// await prefs.remove(keyClass.submitProccess); | |||
setState(() { | |||
// lastUpload = ''; | |||
// lastDownload = ''; | |||
// timeString = ''; | |||
}); | |||
// valueTab value = await DBHelper.database.getValue(keyClass.tgl_start); | |||
// if(value != null)await prefs.setString(keyClass.lastDownload, DateFormat('dd-MM-yyyy HH:mm:ss').parse(value.value).toIso8601String()); | |||
// else { | |||
// await prefs.setString(keyClass.lastDownload, DateTime.now().toIso8601String()); | |||
// } | |||
// value = await DBHelper.database.getValue(keyClass.stock_id); | |||
// if(value != null) await prefs.setString(keyClass.stock_id,value.value); | |||
// else { | |||
await prefs.setString(keyClass.dbName,prefs.getString(keyClass.backup_stock_id)); | |||
// } | |||
// loadState(); | |||
setState(() { | |||
// lastDownload = prefs.getString(keyClass.lastDownload); | |||
}); | |||
} | |||
response = result["MSG"]; | |||
} | |||
if(response != null)util.showToast('GENERAL', response); | |||
} | |||
} | |||
} | |||
else { | |||
util.showToast("ERROR", "File Backup tidak ditemukan atau sudah selesai"); | |||
} | |||
} | |||
} | |||
}, | |||
child: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
@@ -322,6 +448,7 @@ class _HomeState extends State<Home> { | |||
// await DBHelper.database.closeDb(); | |||
// var allUnits = await DBHelper.database.getAllAsset(); | |||
// print('${allUnits.length} Units'); | |||
if(prefs.getString(keyClass.backup_stock_id) == null) prefs.setString(keyClass.backup_stock_id,selected); | |||
util.showToast('ALERT','Data Downloaded'); | |||
} | |||
if(value==-1.0){ | |||
@@ -379,7 +506,7 @@ class _HomeState extends State<Home> { | |||
child: InkWell( | |||
onTap: ()async{ | |||
await Future.delayed(Duration(milliseconds: 300)); | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File db = File(path); | |||
if(db.existsSync()) Navigator.pushNamed(context, '/stocking'); | |||
@@ -411,7 +538,7 @@ class _HomeState extends State<Home> { | |||
InkWell( | |||
onTap: ()async{ | |||
final file = File( | |||
"${(await getApplicationDocumentsDirectory()).path}/assets.db"); | |||
"${(await getExternalStorageDirectory()).path}/assets.db"); | |||
if(file.existsSync()){ | |||
TextEditingController sendingUser = new TextEditingController(); | |||
sendingUser.text = prefs.getString(keyClass.user)??''; | |||
@@ -497,7 +624,7 @@ class _HomeState extends State<Home> { | |||
), | |||
InkWell( | |||
onTap: ()async{ | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File db = File(path); | |||
if(db.existsSync()) await clearData(context); | |||
@@ -1,3 +1,5 @@ | |||
import 'dart:typed_data'; | |||
import 'package:assetstock/util/Models.dart'; | |||
import 'package:sqflite/sqflite.dart'; | |||
import 'package:path_provider/path_provider.dart'; | |||
@@ -6,6 +8,10 @@ import 'dart:io'; | |||
import 'dart:async'; | |||
import 'package:path/path.dart'; | |||
import 'package:intl/intl.dart'; | |||
import 'package:assetstock/main.dart'; | |||
import 'package:permission_handler/permission_handler.dart' as pHandler; | |||
class DBHelper{ | |||
DBHelper._(); | |||
@@ -19,8 +25,70 @@ class DBHelper{ | |||
return _db; | |||
} | |||
backupDb(context) async{ | |||
var result = {"STATUS":0,"MSG":"Backup gagal!"}; | |||
var stock_id = prefs.getString(keyClass.dbName)??''; | |||
if(stock_id != ''){ | |||
await util.permissionCheck(context,pHandler.Permission.storage,()async{ | |||
try{ | |||
// if(dbPath == null || dbPath == ''){ | |||
final database = await db; | |||
var dbPath = database.path; | |||
await DBHelper.database.closeDb(); | |||
// } | |||
await prefs.remove(keyClass.backup_stock_id); | |||
if(stock_id !='' && stock_id != null ) await prefs.setString(keyClass.backup_stock_id,stock_id); | |||
//backupDatabase | |||
print(["aaaaaa",dbPath]); | |||
String backupPath = join(dbPath.substring(0,dbPath.indexOf("/Android"))+"/Download", "${prefs.getString(keyClass.backup_stock_id)}_assets.db"); | |||
print("bbbbbb"); | |||
File backupFile = new File(backupPath); | |||
File dbFile = File(dbPath); | |||
if(dbFile.existsSync()){ | |||
// dbFile.copySync(backupPath); | |||
Uint8List byte = dbFile.readAsBytesSync(); | |||
backupFile.writeAsBytesSync(byte); | |||
result = {"STATUS":1,"MSG":"Backup Berhasil!"}; | |||
} | |||
else{ | |||
result = {"STATUS":0,"MSG":"Backup gagal data unit tidak ditemukan!"}; | |||
print('file backup dont exist tho'); | |||
} | |||
} | |||
catch(e){ | |||
print("backup gagal $e"); | |||
result = {"STATUS":0,"MSG":"Backup gagal!"}; | |||
} | |||
},customMessage: " untuk menyimpan data backup"); | |||
} | |||
else{ | |||
result = {"STATUS":0,"MSG":"Backup gagal data unit tidak ditemukan!"}; | |||
} | |||
return result; | |||
} | |||
restoreDb(context)async{ | |||
var result = {"STATUS":0,"MSG":"File Backup tidak ditemukan!"}; | |||
if(prefs.getString(keyClass.backup_stock_id)!=null){ | |||
await util.permissionCheck(context,pHandler.Permission.storage,()async{ | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String backupPath = join(documentsDirectory.path.substring(0,documentsDirectory.path.indexOf("/Android"))+"/Download", "${prefs.getString(keyClass.backup_stock_id)}_assets.db"); | |||
File backupdbFile = File(backupPath); | |||
if(backupdbFile.existsSync()){ | |||
File dbFile = new File(join(documentsDirectory.path, "assets.db")); | |||
Uint8List byte = backupdbFile.readAsBytesSync(); | |||
dbFile.writeAsBytesSync(byte); | |||
result = {"STATUS":1,"MSG":"File Back up successfull"}; | |||
await DBHelper.database.closeDb(); | |||
} | |||
else result = {"STATUS":0,"MSG":"File Backup tidak ditemukan!"}; | |||
},customMessage: " untuk menyimpan data backup"); | |||
} | |||
return result; | |||
} | |||
initDb() async { | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
var theDb = await openDatabase(path, version: 1,onCreate: _onCreate); | |||
return theDb; | |||
@@ -34,7 +102,7 @@ class DBHelper{ | |||
} | |||
void _onCreate(Database db, int version) async { | |||
Directory documentsDirectory = await getApplicationDocumentsDirectory(); | |||
Directory documentsDirectory = await getExternalStorageDirectory(); | |||
String path = join(documentsDirectory.path, "assets.db"); | |||
File file = File(path); | |||
print('Database created, ${file.lengthSync()}'); | |||
@@ -49,7 +49,7 @@ class file_Trans_Handler { | |||
_progress.add(0.0); | |||
print('Finish Download'); | |||
final file = File( | |||
"${(await getApplicationDocumentsDirectory()).path}/$fileName"); | |||
"${(await getExternalStorageDirectory()).path}/$fileName"); | |||
await file.writeAsBytes(_bytes); | |||
_path = file.path; | |||
}) | |||
@@ -72,7 +72,7 @@ class file_Trans_Handler { | |||
List<int> _bytes = []; | |||
_finish = false; | |||
final file = File( | |||
"${(await getApplicationDocumentsDirectory()).path}/$fileName"); | |||
"${(await getExternalStorageDirectory()).path}/$fileName"); | |||
_total = file.lengthSync(); | |||
print(_total/1024); | |||
try{ | |||
@@ -2,6 +2,7 @@ class keyClass{ | |||
static String hostAddress = "HOST_ADDRESS"; | |||
static String dbName = "dbName"; | |||
static String user ="user"; | |||
static String backup_stock_id ='backupDB'; | |||
} | |||
class tableName{ | |||
@@ -2,11 +2,41 @@ import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'dart:io'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter/services.dart'; | |||
import 'package:http/http.dart' as http; | |||
import 'package:barcode_scan2/barcode_scan2.dart'; | |||
import 'package:fluttertoast/fluttertoast.dart'; | |||
import 'package:permission_handler/permission_handler.dart' as pHandler; | |||
class Util{ | |||
permissionCheck(context,pHandler.Permission permissionType,ifGranted,{customMessage=''})async{ | |||
pHandler.PermissionStatus permission = await permissionType.status; | |||
if(permission!= pHandler.PermissionStatus.granted){ | |||
if(permission== pHandler.PermissionStatus.denied || permission== pHandler.PermissionStatus.restricted){ | |||
showToast('NORMAL', '${permissionType.toString().substring(permissionType.toString().lastIndexOf('.')+1)} permission is needed$customMessage. Please grant the permission!'); | |||
await Future.delayed(Duration(seconds: 3)); | |||
permission = await permissionType.request(); | |||
} | |||
if(permission== pHandler.PermissionStatus.permanentlyDenied) { | |||
showToast('ERROR', 'It seems, your system security explicitly denied access to your ${permissionType.toString().substring(permissionType.toString().lastIndexOf('.')+1)} permission. Please MANUALLY enable it in setings!'); | |||
await Future.delayed(Duration(seconds: 3)); | |||
pHandler.openAppSettings(); | |||
SystemChannels.platform.invokeMethod('SystemNavigator.pop'); | |||
} | |||
if(permission== pHandler.PermissionStatus.denied || permission== pHandler.PermissionStatus.restricted){ | |||
showToast('NORMAL', '${permissionType.toString().substring(permissionType.toString().lastIndexOf('.')+1)} permission is needed$customMessage. Please grant the permission!'); | |||
await Future.delayed(Duration(seconds: 3)); | |||
permission = await permissionType.request(); | |||
} | |||
await permissionCheck(context,permissionType,ifGranted); | |||
} | |||
else{ | |||
await ifGranted(); | |||
} | |||
} | |||
scan()async{ | |||
String BarcodeText =''; | |||
try{ | |||
@@ -303,6 +303,41 @@ packages: | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "2.1.0" | |||
permission_handler: | |||
dependency: "direct main" | |||
description: | |||
name: permission_handler | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "9.2.0" | |||
permission_handler_android: | |||
dependency: transitive | |||
description: | |||
name: permission_handler_android | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "9.0.2+1" | |||
permission_handler_apple: | |||
dependency: transitive | |||
description: | |||
name: permission_handler_apple | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "9.0.4" | |||
permission_handler_platform_interface: | |||
dependency: transitive | |||
description: | |||
name: permission_handler_platform_interface | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "3.7.0" | |||
permission_handler_windows: | |||
dependency: transitive | |||
description: | |||
name: permission_handler_windows | |||
url: "https://pub.dartlang.org" | |||
source: hosted | |||
version: "0.1.0" | |||
petitparser: | |||
dependency: transitive | |||
description: | |||
@@ -33,6 +33,7 @@ dependencies: | |||
# The following adds the Cupertino Icons font to your application. | |||
# Use with the CupertinoIcons class for iOS style icons. | |||
cupertino_icons: ^1.0.5 | |||
permission_handler: ^9.2.0 | |||
dev_dependencies: | |||
flutter_launcher_icons: | |||