【问题标题】:How to install .xapk file from local storage programmatically in Flutter?如何在 Flutter 中以编程方式从本地存储安装 .xapk 文件?
【发布时间】:2023-01-15 03:01:54
【问题描述】:

我想实现这个功能;

按下按钮后,将从具有以下路径的本地存储安装 .xapk 文件。

String _apkFilePath = '/storage/emulated/0/Download/filename.xapk';

【问题讨论】:

    标签: java android flutter dart


    【解决方案1】:

    副本:I am making an .XAPK installer application in flutter. with open_file package I can open normal .apk installation dialogue but how can I install .XAPK

    如果您仍在尝试安装 .xapk 文件,我正在分享一段对我有帮助的代码。我正在使用这些包:

    archive(所有提取为 zip 逻辑)

    device_apps(在您没有所需权限的情况下打开“设置”应用程序)

    open_filex(用安卓intent打开apk文件)

    package_archive_info(从.apk包中获取信息)

    path_provider(获取目录和路径)

    permission_handler(请求安装权限)

    file_picker,因为我使用该包使用选择的文件启动了该方法。

    abstract class XapkInstaller {
    static install({required PlatformFile file}) async {
    late List<FileSystemEntity> allFiles, apkFiles;
    late PackageArchiveInfo appInfo;
    late String appPackageName;
    
    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    
    String appName = file.path.toString().split("/").last.replaceAll(".apklis", "");
    
    String zipFilePath = "${tempDir.path.replaceAll('/$appName.apklis', '')}/$appName.zip";
    
    // this function convert xapk in zip file and moves in appname_zip directory
    _moveFile(File(file.path.toString()), zipFilePath);
    
    final bytes = File(zipFilePath).readAsBytesSync();
    final archive = ZipDecoder().decodeBytes(bytes);
    
    // Extract the contents of the Zip archive to disk app cache.
    for (final file in archive) {
      final String filename = file.name;
    
      if (file.isFile) {
        final data = file.content as List<int>;
        File("${tempDir.path}/$appName/$filename")
          ..createSync(recursive: true)
          ..writeAsBytesSync(data);
      } else {
        Directory(tempPath).create(recursive: true);
      }
    }
    final Directory myDir = Directory("${tempDir.path}/$appName");
    
    allFiles = myDir.listSync(recursive: true, followLinks: true);
    
    apkFiles = allFiles.where((element) => element.path.endsWith('.apk')).toList();
    for (int x = 0; x < apkFiles.length; x++) {
      final String filePath = apkFiles[x].path;
      try {
        appInfo = await PackageArchiveInfo.fromPath(filePath);
        appPackageName = appInfo.packageName;
      } catch (e) {
        appInfo = PackageArchiveInfo(appName: "", packageName: "", version: "", buildNumber: "");
      }
      if (appInfo.appName.isNotEmpty) {
        try {
          // moving obb file to android/obb folder
          _moveObbToAndroidDir(allFiles, appPackageName);
    
          // showing popup to install app
          if (await Permission.requestInstallPackages.request().isGranted) {
            await OpenFilex.open(filePath);
          } else {
            DeviceApps.openAppSettings(appInfo.packageName);
          }
        } catch (e) {
          //catch error in installing
        }
      }
    }
    // clearing cache file after installing xapk
    Future.delayed(const Duration(seconds: 180), () {
      tempDir.deleteSync(recursive: true);
      tempDir.create();
    });
    }
    
    static _moveObbToAndroidDir(List<FileSystemEntity> allFiles, String appPackageName) async {
    for (int x = 0; x < allFiles.length; x++) {
      final fileExtension = allFiles[x].path.split("/").last.split(".").last;
    
      if (fileExtension == "obb") {
        String filepath = allFiles[x].path;
        String obbFileName = filepath.split("/").last.split(".").first;
    
        String obbDirPath = "/Android/obb/$appPackageName";
    
        // creating the directory inside android/obb folder to place obb files
        if (!Directory(obbDirPath).existsSync()) {
          Directory(obbDirPath).createSync();
        }
    
        // rename path should also contains filename i.e. whole path with filename and extension
        final String renamePath = "$obbDirPath/$obbFileName.obb";
    
        try {
          // syncronus copying
          File(filepath).copySync(renamePath);
        } on FileSystemException {
          // in case of exception copying asyncronushly
          await File(filepath).copy(renamePath);
        }
        }
      }
     }
    
    static Future<File> _moveFile(File sourceFile, String newPath) async {
    try {
      // prefer using rename as it is probably faster
      return await sourceFile.rename(newPath);
    } on FileSystemException catch (e) {
      // if rename fails, copy the source file and then delete it
      final newFile = await sourceFile.copy(newPath);
      await sourceFile.delete();
      return newFile;
      }
     }
    }
    

    我已经试过了,它确实有效,所以请记住更新 AndroidManifest 文件的权限,一切就绪。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 2020-08-25
      • 2019-06-06
      相关资源
      最近更新 更多