Google Play扩展文件位置

时间:2013-03-08 23:59:34

标签: android apk-expansion-files

我们使用Google Play扩展APK机制获得了大约600MB的扩展文件。我们还必须解压缩此文件以供实际使用。整个应用程序加数据因此需要大约1.4 GB的存储空间。

据我所知,Google Play坚持将.obb下载到“内部”SD,似乎无法改变这种情况。我们有很多用户在他们的“外部”SD卡上有很多可用空间,但内部空间有限。他们尖叫着应用程序占用了这么多空间。我们能做些什么吗?

我们目前将.obb文件扩展为:

getExternalStorageDirectory()/ Android设备/数据

我想我们可以问用户他们想要的地方,他们可以选择真正的外部SD卡。然而,这仍然会在内部SD卡上留下(基本上无用的).obb文件,Google Play说我们无法删除它。

有没有人对如何正确处理这个问题有任何建议?

3 个答案:

答案 0 :(得分:2)

根据Expansion File Storage Location documentation,扩展文件存储在

<shared-storage>/Android/obb/<package-name>/

其中shared-storagegetExternalStorageDirectory()返回的内容,对于拥有SD卡的用户,应该在SD卡上。

不幸的是,如同一页上所述:

  

为确保正常行为,您不得删除,移动或重命名扩展文件。

我会特别注意这一段:

  

如果您必须解压缩扩展文件的内容,不要之后删除.obb扩展文件,不要将解压缩的数据保存在同一目录中。您应该将解压缩的文件保存在getExternalFilesDir()指定的目录中。但是,如果可能,最好使用扩展文件格式,允许您直接从文件中读取,而不是要求您解压缩数据。例如,我们提供了一个名为APK Expansion Zip Library的库项​​目,它直接从ZIP文件中读取数据。

答案 1 :(得分:1)

将OBB文件放在其他任何地方的问题是,当用户卸载您的应用程序时,它们将不会被删除,这往往会使他们心情不好,温和地说明。但是,如果您认为收益超过成本,则没有任何技术可以阻止您更改存储位置,因为执行OBB文件的源代码下载和提供验证,您可以修改其行为以满足您的需求。

例如,存储OBB文件的路径由com.google.android.vending.expansion.downloader.Helpers

提供
static public String getSaveFilePath(Context c) {
    File root = Environment.getExternalStorageDirectory();
    String path = root.toString() + Constants.EXP_PATH + c.getPackageName();
    return path;
}

(还需要修改getFilesystemRoot(String path)&amp; isFilenameValid(String filename)

如果您同时使用Google的扩展zip文件库,那么您还需要在com.android.vending.expansion.zipfile.APKExpansionSupport中更改指定Environment.getExternalStorageDirectory()作为根目录的3个方法。

这些改变至少应该让你到那里一半。

另请注意,外置SD卡的问题在于它们的速度变化很大,通常情况下内部SD至少会有不错的速度。也许您可以将OBB分成2个文件(假设您不需要更新文件功能),并将其中一个移动到外部SD。

答案 2 :(得分:0)

我遇到了同样的问题,但我找到了解决问题的方法。

如果删除OBB,则didFileExist(在Helpers.java中)将返回false。在ExpDownloaderActivity中,检查expansionFilesDelivered,您将使用此信息重新下载OBB。

我已经改变了didFileExist和expandFilesDelivered,其方式是不返回布尔值,而是返回具有以下含义的整数:

fileStatus == 0:缺少OBB(必须下载)

fileStatus == 1:OBB可用,可以解压缩到其他地方

fileStatus == 2:OBB中的数据已经存储到另一个地方

现在te技巧: 在将数据从OBB解压缩到我喜欢的位置后,我将原始OBB替换为同名文件,该文件只包含原始OBB的文件大小作为字符串。这释放了SD卡上占用的空间。

对didFileExist和expansionFilesDelivered的进一步调用将返回filestatus = 2,这意味着,不需要任何操作。

以下是我在Helpers.java中的更改:

static public int doesFileExist(Context c, String fileName, long fileSize,
        boolean deleteFileOnMismatch) {
    // the file may have been delivered by Market --- let's make sure
    // it's the size we expect


    File fileForNewFile = new File(Helpers.generateSaveFileName(c, fileName));
    if (fileForNewFile.exists()) {
        if (fileForNewFile.length() == fileSize) {
            return 1;
        } else if (fileForNewFile.length() < 100) {
            // Read the file and look for the file size inside
            String content = "";
            long isSize = 0;
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(fileForNewFile);
                char current;
                while (fis.available() > 0) {
                    current = (char) fis.read();
                    content = content + String.valueOf(current);
                }

            } catch (Exception e) {
                Log.d("ReadOBB", e.toString());
            } finally {
                if (fis != null)
                    try {
                        fis.close();
                    } catch (IOException ignored) {
                }
            }
            try {
                isSize = Long.parseLong(content);
            } catch(NumberFormatException nfe) {
                Log.d("ReadOBBtoInt", nfe.toString());
            } 
            if (isSize == fileSize) {
                return 2;
            }
        }
        if (deleteFileOnMismatch) {
            // delete the file --- we won't be able to resume
            // because we cannot confirm the integrity of the file
            fileForNewFile.delete();
        }
    }
    return 0;
}

如果OBB的文件大小不匹配,我读取OBB并与存储在其中的文件大小进行比较(这就是filesize应该是什么)。如果这给出匹配,我知道该文件已经处理完毕。

这是我对ExpDownloaderActivity的更改:

int expansionFilesDelivered() {
    int fileStatus = 0;

    for (XAPKFile xf : xAPKS) {
        if (xf.mFileSize > 0) {
            String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
            fileStatus = Helpers.doesFileExist(this, fileName, xf.mFileSize, false);
            if (fileStatus==0)
                return 0;
        }
    }
    return fileStatus;
}

在ExpDownloaderActivity的onCreate中:

    initializeDownloadUI();

    int fileStatus = expansionFilesDelivered();
    if (fileStatus==0) {        // OBB is missing
            // ... Download the OBB file, same as on Downloader example
    } else if (fileStatus==1) {
        validateXAPKZipFiles(); // and, if OBB has no errors, unpack it to my favorite place
                                // if done, create a new OBB file with the original name
                                // and store a string with the original filesize in it.
    } else {
        finish();               // No action required        }

所以我把数据解压缩到任何我想要的地方 - 正如OP提到的那样 - 不需要sdcard上的空间来获得完整的OBB 解压缩的数据。