diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 38d3d62..9d660df 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
+
{
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 {
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 {
Text('Change Host Address',style: TextStyle(color: Colors.blueGrey,fontWeight: FontWeight.w500),)
],
),
- )
+ ),
+ PopupMenuItem(
+ value:'backup',
+ child: Row(
+ children: [
+ Icon(Icons.save,color: Colors.black,),
+ SizedBox(width: 10,),
+ Text('Backup Data')
+ ],
+ ),
+ ),
+ PopupMenuItem(
+ value:'restore',
+ child: Row(
+ children: [
+ 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 {
});
}
+ 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: [
+ 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: [
+ 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 {
// 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 {
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 {
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 {
),
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);
diff --git a/lib/util/dbHandler.dart b/lib/util/dbHandler.dart
index 6f9a481..5220c5f 100644
--- a/lib/util/dbHandler.dart
+++ b/lib/util/dbHandler.dart
@@ -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()}');
diff --git a/lib/util/download_Upload_Handler.dart b/lib/util/download_Upload_Handler.dart
index 3f9c432..88495d9 100644
--- a/lib/util/download_Upload_Handler.dart
+++ b/lib/util/download_Upload_Handler.dart
@@ -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 _bytes = [];
_finish = false;
final file = File(
- "${(await getApplicationDocumentsDirectory()).path}/$fileName");
+ "${(await getExternalStorageDirectory()).path}/$fileName");
_total = file.lengthSync();
print(_total/1024);
try{
diff --git a/lib/util/prefsKey.dart b/lib/util/prefsKey.dart
index 230ccee..cbfe676 100644
--- a/lib/util/prefsKey.dart
+++ b/lib/util/prefsKey.dart
@@ -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{
diff --git a/lib/util/utils.dart b/lib/util/utils.dart
index 68592cb..939dc2d 100644
--- a/lib/util/utils.dart
+++ b/lib/util/utils.dart
@@ -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{
diff --git a/pubspec.lock b/pubspec.lock
index 7041f24..63ca6d9 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -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:
diff --git a/pubspec.yaml b/pubspec.yaml
index 887fadb..3d756c6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -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: