dart 我正在做一个.XAPK安装程序在flutter中,与open_file包我可以打开正常的.APK安装对话框,但我如何安装.XAPK

1tu0hz3e  于 2023-01-15  发布在  Flutter
关注(0)|答案(1)|浏览(260)

由于. XAPK文件包含1 base_apk以及obb文件和其他一些额外的. apk文件。通过将. XAPK文件转换为zip,然后提取它让我安装base_apk,但该APK实际上并不工作,因为它没有正确安装它的其他额外的APK。我如何才能正确安装. XAPK文件的所有APK。(下面的代码是在 dart 语言,因为它是FlutterAPK)。
这是我的代码:

import 'dart:io';

import 'package:archive/archive.dart';
import 'package:package_archive_info/package_archive_info.dart';
import 'package:path_provider/path_provider.dart';

    abstract class XapkInstaller {   static install({ required String apkPath }) async {
    
        late List<FileSystemEntity> allFiles, apkFiles;
        late PackageArchiveInfo appInfo;
        late String appPackageName;
    
        Directory tempDir = await getTemporaryDirectory();
        String tempPath = tempDir.path;
    
        String appName = apkPath.split("/").last.replaceAll(".xapk", "");
        String zipFilePath = tempDir.path + "/${appName}_zip";
        // this function convert xapk in zip file and moves in appname_zip dirctory
        _moveFile(File(apkPath), zipFilePath, appName);
    
        final bytes = File(zipFilePath + "/$appName" + ".zip").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 &&
              appPackageName == App.apkName(apkPath: filePath)) {
            try {
              // moving real app from extracting folder to APKdojo folder
              File(filePath)
                  .copySync(await App.getApksDirectory() + "/$appName.apk");
    
              // moving obb file to android/obb folder
              _moveObbToAndroidDir(allFiles, appPackageName);
    
              // showing popup to install app
              await OpenFile.open(filePath);
    
              // deleting .xapk file after moving real extracted app in the APKdojo folder and obb file into android folder
              File(await App.getApksDirectory() + "/$appName" + ".xapk").delete();
            } catch (e) {
              //error in installing
            }
          }
        }
        // clearing cache file after installing xapk
        Future.delayed(const Duration(seconds: 180), () {
          tempDir.deleteSync(recursive: true);
          tempDir.create();
        });   }
    
      static _moveFile(File sourceFile, String newPath, String appname) async {
        if (!Directory(newPath).existsSync()) Directory(newPath).createSync();
        final String zipFilePath = "$newPath/" + appname + ".zip";
    
        try {
          return sourceFile.copySync(zipFilePath);
        } on FileSystemException {
          // if rename fails, copy the source file and then delete it
          await sourceFile.copy(zipFilePath);
          await sourceFile.delete();
        }   }
    
      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 = await App.internalStoragePath() +
                "/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);
            }
          }
        }   } }
nvbavucw

nvbavucw1#

如果你还在尝试安装一个. xapk文件,我分享一段代码来帮助我。我使用的软件包:
archive(用于所有作为zip逻辑的提取)
device_apps(在您没有所需权限的情况下打开设置应用程序)
open_filex(使用Android 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文件的权限,你就万事俱备了。

相关问题