解压

第一次安装完app后,需要将obb文件进行解压并将解压后的文件存储到我们定义的文件夹里(可以是data/data/包名/files/也可以是内置存储下自定义的项目文件夹)。要想解压obb文件,第一步是获取obb文件的本地路径,具体代码如下:

public static String getObbFilePath(Context context) {
    try {
        return Environment.getExternalStorageDirectory().getAbsolutePath()
                + "/Android/obb/"
                + context.getPackageName()
                + File.separator
                + "main."
                + context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode
                + "."
                + context.getPackageName()
                + ".obb";
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return null;
    }
}

拿到obb文件路径后,可以开始进行解压了:

public static void unZipObb(Context context) {
   String obbFilePath = getObbFilePath(context);
   if (obbFilePath == null) {
       return;
   } else {
       File obbFile = new File(obbFilePath);
       if (!obbFile.exists()) {
           //下载obb文件
       } else {
           File outputFolder = new File("yourOutputFilePath");
           if (!outputFolder.exists()) {
               //目录未创建 没有解压过
               outputFolder.mkdirs();
               unZip(obbFile, outputFolder.getAbsolutePath());
           } else {
               //目录已创建 判断是否解压过
               if (outputFolder.listFiles() == null) {
                   //解压过的文件被删除
                   unZip(obbFile, outputFolder.getAbsolutePath());
               }else {
                   //此处可添加文件对比逻辑
               }
           }
       }
   }
}

谷歌官方有提供解压obb文件的库供开发者使用,叫做APK Expansion Zip Library,感兴趣的小伙伴可以在一下路径下查看。

<sdk>/extras/google/google_market_apk_expansion/zip_file/

笔者不推荐使用该库,原因是这个库已经编写了有一些年头了,当时编译的sdk版本比较低,有一些兼容性的bug需要开发者修改代码后才能使用。所以这里使用的upzip方法是用最普通的ZipInputStream和FileOutputStream解压zip包的方式来实现的:

//这里没有添加解压密码逻辑,小伙伴们可以自己修改添加以下
public static void unzip(File zipFile, String outPathString) throws IOException {
    FileUtils.createDirectoryIfNeeded(outPathString);
    ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFile));
    ZipEntry zipEntry;
    String szName;
    while ((zipEntry = inZip.getNextEntry()) != null) {
        szName = zipEntry.getName();
        if (zipEntry.isDirectory()) {
            szName = szName.substring(0, szName.length() - 1);
            File folder = new File(outPathString + File.separator + szName);
            folder.mkdirs();
        } else {
            File file = new File(outPathString + File.separator + szName);
            FileUtils.createDirectoryIfNeeded(file.getParent());
            file.createNewFile();
            FileOutputStream out = new FileOutputStream(file);
            int len;
            byte[] buffer = new byte[1024];
            while ((len = inZip.read(buffer)) != -1) {
                out.write(buffer, 0, len);
                out.flush();
            }
            out.close();
        }
    }
    inZip.close();
}

public static String createDirectoryIfNeeded(String folderPath) {
    File folder = new File(folderPath);
    if (!folder.exists() || !folder.isDirectory()) {
        folder.mkdirs();
    }
    return folderPath;
}

解压完成后,就可以通过输出文件的路径来访问到我们需要访问的大容量资源了,文件的读取在这里就不展开了。