小米手机使用FlutterDownloader下载安卓apk文件不能正常安装

项目场景:

在Flutter项目中使用flutter_downloader: ^1.9.1下载apk文件,小米手机提示下载成功但是通知栏进度条卡住并且未跳出安装apk的窗口。
当前Android项目包名:com.app.update.demo


问题描述

下载更新app提示“下载成功!”,但是执行语句

OpenResult openResult=  await OpenFile.open(file.path,type: 'application/vnd.android.package-archive');

时报错:ResultType.fileNotFound。下载保存地址为:/storage/emulated/0/Android/data/com.app.update.demo/files/my_app/my_app_1668582134848.apk,可是在文件管理器中找到my_app_1668582134848.apk文件实际保存地址为:/storage/emulated/0/Download/my_app_1668582134848.apk,与目标位置不一致所以报错找不到文件

upDateApp() async {
    if (Platform.isIOS) {
      if (await canLaunchUrl(Uri.parse(XConfig.appStoreUrl))) {
        await launchUrl(Uri.parse(XConfig.appStoreUrl));
      } else {
        throw ('无效的url');
      }
    } else if (Platform.isAndroid) {
      bool isStorage = await PreferenceUtils.requestStoragePermission();
      if (!isStorage) {
        Fluttertoast.showToast(
          msg: "未开启手机储权限",
          gravity: ToastGravity.CENTER,
        );
        return;
      }
      var times = DateTime.now().millisecondsSinceEpoch;
      var fileName = 'my_app_$times.apk';
      _bindBackgroundIsolate(fileName);
      FlutterDownloader.registerCallback(downloadCallback);
      var savedDir = await _prepareSaveDir();
      File file = File(Uri.encodeFull(savedDir + '/' + fileName));
      if (await file.exists()) await file.delete();
      FlutterDownloader.enqueue(
          url: XConfig.androidApkUrl + '?time=$times',
          headers: {"auth": "test_for_sql_encoding"},
          savedDir: savedDir,
          fileName: fileName,
          showNotification: true,
          saveInPublicStorage: true,
          openFileFromNotification: true);
    }
  }
void _bindBackgroundIsolate(String name) {
    final ReceivePort _port = ReceivePort();
    bool isSuccess = IsolateNameServer.registerPortWithName(
        _port.sendPort, 'downloader_send_port_app');
    if (!isSuccess) {
      _unbindBackgroundIsolate();
      _bindBackgroundIsolate(name);
      return;
    }
    _port.listen((dynamic data) async {
      String? id = data[0];
      DownloadTaskStatus? status = data[1];
      double progress = data[2] / 100;
      if (status == DownloadTaskStatus.running) {
        EasyLoading.showProgress(progress, status: '正在下载最新版本');
      }
      if (status == DownloadTaskStatus.failed) {
        EasyLoading.showError('下载失败,请稍后再试!');
        EasyLoading.dismiss();
      }
      if (status == DownloadTaskStatus.complete && id != null) {
        EasyLoading.showSuccess('下载成功!');
        EasyLoading.dismiss();
        var savedDir = await _prepareSaveDir();
        var filePath = '$savedDir/$name';
        File file =File(Uri.encodeFull(filePath));
        OpenResult openResult=  await OpenFile.open(file.path,
            type: 'application/vnd.android.package-archive');
        print(openResult.message);
      }
    });
  }
_prepareSaveDir() async {
    String _localPath = (await _findLocalPath())! + '/my_app';
    final savedDir = Directory(Uri.encodeFull(_localPath));
    bool hasExisted = await savedDir.exists();
    if (!hasExisted) {
      savedDir.createSync();
    }
    return _localPath;
  }
  void _unbindBackgroundIsolate() {
    IsolateNameServer.removePortNameMapping('downloader_send_port_app');
  }
    Future<String?> _findLocalPath() async {
    var externalStorageDirPath;
    if (Platform.isAndroid) {
      final directory = await getExternalStorageDirectory();
      externalStorageDirPath = directory?.path??await getTemporaryDirectory();
    } else if (Platform.isIOS) {
      externalStorageDirPath =
          (await getApplicationDocumentsDirectory()).absolute.path;
    }
    return externalStorageDirPath;
  }

原因分析:

小米手机MIUI针对下载保存的apk文件进行了另存,并且删除了原路径的文件


解决方案:

在下载成功以后根据下载目标路径判断当前文件是否存在,如果不存在则使用小米系统下载保存路径+文件名重试:/storage/emulated/0/Download/文件名.apk

 if (status == DownloadTaskStatus.complete && id != null) {
        EasyLoading.showSuccess('下载成功!');
        EasyLoading.dismiss();
        var savedDir = await _prepareSaveDir();
        var filePath = '$savedDir/$name';
        File file =File(Uri.encodeFull(filePath));
        if(file.existsSync()){
          print(file.path);
        }else{
         // 小米手机下载完成后会将文件移动到/storage/emulated/0/Download/路径下
         var xiaomiPath= filePath.replaceAll("Android/data/com.app.update.demo/files/my_app/", "Download/");
         file =File(Uri.encodeFull(xiaomiPath));
        }
        OpenResult openResult=  await OpenFile.open(file.path,
            type: 'application/vnd.android.package-archive');
        print(openResult.message);
      }

创作不易,请作者喝杯咖啡:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

申徒嘉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值