@@ -356,11 +356,76 @@ class DownloadManager {
356356 return newPath;
357357 }
358358
359+ /// 检查是否为 APK 文件
360+ static bool _isApkFile (String filePath) {
361+ return filePath.toLowerCase ().endsWith ('.apk' );
362+ }
363+
364+ /// 检查和请求安装权限
365+ static Future <bool > _checkInstallPermission () async {
366+ if (! Platform .isAndroid) return true ;
367+
368+ try {
369+ // 检查是否有安装权限
370+ bool hasPermission = await Permission .requestInstallPackages.isGranted;
371+
372+ if (! hasPermission) {
373+ // 请求安装权限
374+ PermissionStatus status = await Permission .requestInstallPackages.request ();
375+
376+ if (status.isGranted) {
377+ return true ;
378+ } else if (status.isPermanentlyDenied) {
379+ // 权限被永久拒绝,引导用户到设置页面
380+ getx.Get .dialog (
381+ AlertDialog (
382+ title: const Text ('需要安装权限' ),
383+ content: const Text ('为了安装 APK 文件,需要授予安装权限。请在设置中手动开���。' ),
384+ actions: [
385+ TextButton (
386+ onPressed: () => getx.Get .back (),
387+ child: const Text ('取消' ),
388+ ),
389+ TextButton (
390+ onPressed: () {
391+ getx.Get .back ();
392+ openAppSettings ();
393+ },
394+ child: const Text ('去设置' ),
395+ ),
396+ ],
397+ ),
398+ );
399+ return false ;
400+ } else {
401+ getx.Get .showSnackbar (const getx.GetSnackBar (
402+ message: '需要安装权限才能安装 APK 文件' ,
403+ duration: Duration (seconds: 3 ),
404+ ));
405+ return false ;
406+ }
407+ }
408+
409+ return true ;
410+ } catch (e) {
411+ log ('检查安装权限失败: $e ' );
412+ return true ; // 如果检查失败,继续尝试打开
413+ }
414+ }
415+
359416 /// 尝试打开文件
360417 static Future <void > _openFile (String filePath) async {
361418 try {
362419 log ('尝试打开文件: $filePath ' );
363420
421+ // 如果是 APK 文件,先检查安装权限
422+ if (_isApkFile (filePath)) {
423+ bool hasPermission = await _checkInstallPermission ();
424+ if (! hasPermission) {
425+ return ; // 没有权限,不继续打开
426+ }
427+ }
428+
364429 // 使用 open_filex 插件打开文件
365430 final result = await OpenFilex .open (filePath);
366431
@@ -372,16 +437,29 @@ class DownloadManager {
372437 // 文件成功打开,不需要额外提示
373438 break ;
374439 case ResultType .noAppToOpen:
375- getx.Get .showSnackbar (getx.GetSnackBar (
376- message: '没有找到可以打开此文件的应用' ,
377- duration: const Duration (seconds: 3 ),
378- mainButton: TextButton (
379- onPressed: () {
380- _showFileLocation (filePath);
381- },
382- child: const Text ('查看位置' ),
383- ),
384- ));
440+ if (_isApkFile (filePath)) {
441+ getx.Get .showSnackbar (getx.GetSnackBar (
442+ message: '无法安装 APK 文件,可能需要在设置中开启"允许安装未知来源应用"' ,
443+ duration: const Duration (seconds: 5 ),
444+ mainButton: TextButton (
445+ onPressed: () {
446+ openAppSettings ();
447+ },
448+ child: const Text ('去设置' ),
449+ ),
450+ ));
451+ } else {
452+ getx.Get .showSnackbar (getx.GetSnackBar (
453+ message: '没有找到可以打开此文件的应用' ,
454+ duration: const Duration (seconds: 3 ),
455+ mainButton: TextButton (
456+ onPressed: () {
457+ _showFileLocation (filePath);
458+ },
459+ child: const Text ('查看位置' ),
460+ ),
461+ ));
462+ }
385463 break ;
386464 case ResultType .fileNotFound:
387465 getx.Get .showSnackbar (const getx.GetSnackBar (
@@ -390,10 +468,23 @@ class DownloadManager {
390468 ));
391469 break ;
392470 case ResultType .permissionDenied:
393- getx.Get .showSnackbar (const getx.GetSnackBar (
394- message: '没有权限打开此文件' ,
395- duration: Duration (seconds: 3 ),
396- ));
471+ if (_isApkFile (filePath)) {
472+ getx.Get .showSnackbar (getx.GetSnackBar (
473+ message: '没有权限安装 APK 文件,请在设置中开启安装权限' ,
474+ duration: const Duration (seconds: 5 ),
475+ mainButton: TextButton (
476+ onPressed: () {
477+ openAppSettings ();
478+ },
479+ child: const Text ('去设置' ),
480+ ),
481+ ));
482+ } else {
483+ getx.Get .showSnackbar (const getx.GetSnackBar (
484+ message: '没有权限打开此文件' ,
485+ duration: Duration (seconds: 3 ),
486+ ));
487+ }
397488 break ;
398489 case ResultType .error:
399490 default :
0 commit comments