feat : apk installer
This commit is contained in:
@@ -1,23 +1,18 @@
|
||||
|
||||
import 'package:rasadyar_auth/auth.dart';
|
||||
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
final di = GetIt.instance;
|
||||
|
||||
Future<void> setupPreInjection() async{
|
||||
Future<void> setupPreInjection() async {
|
||||
await setupAllCoreProvider();
|
||||
await setupAuthDI();
|
||||
|
||||
|
||||
|
||||
di.registerSingleton<DioRemote>(
|
||||
DioRemote(baseUrl: 'https://everestacademy.ir/'),
|
||||
instanceName: 'baseRemote',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setupInjection() async{
|
||||
|
||||
Future<void> setupInjection() async {
|
||||
await setupChickenDI();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:rasadyar_auth/data/services/token_storage_service.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
@@ -8,6 +10,11 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
late final AnimationController rotateController;
|
||||
Rxn<Animation<double>> scaleAnimation = Rxn();
|
||||
Rxn<Animation<double>> rotationAnimation = Rxn();
|
||||
RxBool hasUpdated = false.obs;
|
||||
RxBool onUpdateDownload = false.obs;
|
||||
RxDouble percent = 0.0.obs;
|
||||
final RxnString _updateFilePath = RxnString();
|
||||
final platform = MethodChannel('apk_installer');
|
||||
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
@@ -24,15 +31,9 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
duration: const Duration(milliseconds: 8000),
|
||||
);
|
||||
|
||||
scaleAnimation.value = Tween<double>(
|
||||
begin: 0.8,
|
||||
end: 1.2,
|
||||
).animate(scaleController);
|
||||
scaleAnimation.value = Tween<double>(begin: 0.8, end: 1.2).animate(scaleController);
|
||||
|
||||
rotationAnimation.value = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1,
|
||||
).animate(rotateController);
|
||||
rotationAnimation.value = Tween<double>(begin: 0.0, end: 1).animate(rotateController);
|
||||
|
||||
rotateController.forward();
|
||||
rotateController.addStatusListener((status) {
|
||||
@@ -51,21 +52,171 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
scaleController.forward();
|
||||
}
|
||||
});
|
||||
|
||||
hasUpdated.listen((data) {
|
||||
if (data) {
|
||||
requiredUpdateDialog(
|
||||
onConfirm: () async {
|
||||
await fileDownload();
|
||||
},
|
||||
);
|
||||
} else if (!data && Get.isDialogOpen == true) {
|
||||
Get.back();
|
||||
}
|
||||
});
|
||||
onUpdateDownload.listen((data) {
|
||||
hasUpdated.value = false;
|
||||
if (data) {
|
||||
Get.bottomSheet(
|
||||
isDismissible: false,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
Container(
|
||||
height: 170,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
|
||||
),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Text('در حال دانلود بروزرسانی برنامه...'),
|
||||
Obx(
|
||||
() => Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: LinearProgressIndicator(
|
||||
value: percent.value,
|
||||
color: AppColor.greenNormal,
|
||||
minHeight: 4,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 55.w,
|
||||
child: Text(
|
||||
'${(percent.value * 100).toStringAsFixed(2)}%',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ObxValue((data) {
|
||||
return RElevated(
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
height: 40.h,
|
||||
onPressed: data.value != null
|
||||
? () {
|
||||
installApk();
|
||||
Get.back();
|
||||
}
|
||||
: null,
|
||||
text: 'نصب',
|
||||
);
|
||||
}, _updateFilePath),
|
||||
),
|
||||
Expanded(
|
||||
child: ROutlinedElevated(
|
||||
borderColor: AppColor.error,
|
||||
text: 'خروج',
|
||||
onPressed: () async {
|
||||
exit(0);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
|
||||
hasUpdated.value = !hasUpdated.value;
|
||||
|
||||
//TODO
|
||||
/*Future.delayed(const Duration(seconds: 1), () async {
|
||||
var module = tokenService.appModule.value;
|
||||
Get.offAndToNamed(getTargetPage(module));
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
rotateController.dispose();
|
||||
scaleController.dispose();
|
||||
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
Future<void> fileDownload() async {
|
||||
onUpdateDownload.value = true;
|
||||
Dio dio = Dio();
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final filePath = "${dir.path}/app-release.apk";
|
||||
final file = File(filePath);
|
||||
if (await file.exists()) {
|
||||
await file.delete();
|
||||
}
|
||||
int attempts = 0;
|
||||
int retryCount = 4;
|
||||
bool success = false;
|
||||
|
||||
while (attempts < retryCount && !success) {
|
||||
try {
|
||||
await dio.download(
|
||||
'https://everestacademy.ir/app/app-release.apk',
|
||||
filePath,
|
||||
onReceiveProgress: (count, total) {
|
||||
if (total != -1 && total > 0) {
|
||||
percent.value = count / total;
|
||||
}
|
||||
},
|
||||
);
|
||||
success = true;
|
||||
} on DioException catch (e) {
|
||||
attempts++;
|
||||
percent.value = 0.0;
|
||||
if (attempts >= retryCount) {
|
||||
eLog("Download failed after $attempts attempts: ${e.message}");
|
||||
} else {
|
||||
await Future.delayed(const Duration(milliseconds: 1200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_updateFilePath.value = filePath;
|
||||
|
||||
tLog(filePath);
|
||||
fLog(_updateFilePath.value);
|
||||
}
|
||||
|
||||
onUpdateDownload.value = false;
|
||||
}
|
||||
|
||||
Future<void> installApk() async {
|
||||
try {
|
||||
eLog(_updateFilePath.value);
|
||||
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
await platform.invokeMethod('apk_installer', {'appPath': _updateFilePath.value});
|
||||
} catch (e) {
|
||||
print("خطا در نصب: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class SplashPage extends GetView<SplashLogic> {
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
|
||||
ObxValue((data) {
|
||||
return ScaleTransition(
|
||||
scale: data.value!,
|
||||
|
||||
Reference in New Issue
Block a user