【问题标题】:Downloading game assets to SD card on Android在 Android 上将游戏资源下载到 SD 卡
【发布时间】:2010-04-23 09:58:26
【问题描述】:

我正在开发一个 Android 游戏,它必须将一些 资产 下载到 SD 卡 以保持应用的大小尽可能小尽可能。我正在考虑使用 未压缩的 zip 文件来捆绑所有资产。

客户的要求是尽可能保护这些资产。作为 apk 的一部分被认为是足够的保护,但如果我这样做,apk 大小 将是巨大的。如果我只是将压缩包放入 SD 卡中,那么任何人都可以解压缩并浏览其中的内容。

有没有一种简单的方法来做到这一点,而不用反驳可怕的 DRM?

显然,如果有人真的想要查看 Android 游戏的资源,他们可以。我只是在寻找一个简单的解决方案来避免让这变得非常容易。

【问题讨论】:

  • 只是检查一下 - 您是否意识到 APK 文件只是一个重命名的 zip 文件?它可以使用任何可以打开 zip 的程序打开,而且许多 Android 文件浏览器甚至不需要您更改文件扩展名。因此,在 apk 中包含要保护的资产根本不是任何保护,无论文件大小问题如何。您的许多代码和清单都是使用您的开发密钥编译/加密的,但图像之类的东西是原始可用的。
  • 我相信如果您打开复制保护,用户将无法轻松访问 APK 文件的内容。不过,并不是说这是万无一失的方法。
  • @Steve H - 如果您在上传到市场时通过勾选相关框“转发锁定”应用程序,那么用户无法在无根手机上轻松找到.apk。这不会阻止某人下定决心,但它会阻止随意浏览器找到我认为是此处意图的资产。
  • 啊,应用上的复制保护是否会阻止备份程序对 sdcard 上的 APK 进行备份?如果没有,那么获取 apk 仍然相当容易。我承认我对这个选项知之甚少,除了它将你的 APK 的大小增加一倍之外,这对于大型游戏来说可能是令人望而却步的。无论如何,戴夫已经提出了一个很好的建议,所以听他的,不是我的:p

标签: android copy-protection sd-card


【解决方案1】:

您可以encrypt the ZIP file with AES,但在提取资源时会产生开销,这可能是个问题,因为在编写游戏时性能通常相当重要。

但是,正如您所说,自己使用安全加密并不值得,因为如果有人真的感兴趣,他们可以在您的应用程序的源代码中找到密钥。因此,您可以自己编写 InputStreamOutputStream 来对 ZIP 文件的字节进行一些简单的转换。这在读取文件时可以快速撤消,但会“损坏” ZIP 文件,足以阻止有人浏览他们的 SD 卡。

使用它时,您会将流放在FileZIPInputStream 之间,例如:

File assets = new File(Environment.getExternalStorageDirectory(),"assets");
ZipInputStream zip = new ZipInputStream(new TranslateInputStream(assets));

作为示例翻译,您可以对所有具有已知值的字节进行异或:

private static final byte MAGIC_NUMBER = 13;

private void translateBuffer(byte[] buffer) {
    for (int i = 0;i < buffer.length;i++) {
        buffer[i] ^= MAGIC_NUMBER;
    }
}

private class TranslateOutputStream extends FileOutputStream {
    public TranslateOutputStream(File file) throws FileNotFoundException {
        super(file);
    }

    @Override
    public void write(int oneByte) throws IOException {
        oneByte ^= MAGIC_NUMBER;
        super.write(oneByte);
    }

    //In Android write(byte[]) calls this method so we don't need to override both        
    @Override
    public void write(byte[] buffer, int offset, int count)
            throws IOException {
        translateBuffer(buffer);
        super.write(buffer, offset, count);
    }
}

private class TranslateInputStream extends FileInputStream {

    public TranslateInputStream(File file) throws FileNotFoundException {
        super(file);
    }

    @Override
    public int read() throws IOException {
        return super.read() ^ MAGIC_NUMBER;
    }

    //In Android read(byte[]) calls this method so we don't need to override both        
    @Override
    public int read(byte[] buffer, int offset, int count)
            throws IOException {
        int bytesRead = super.read(buffer, offset, count);
        translateBuffer(buffer);
        return bytesRead;
    }
}

或者,您不能使用 ZIP,因为您不关心压缩。只需将所有资产连接到一个大块中即可。在创建 blob 时,将每个资产的开始和结束位置写入索引文件。然后,索引文件将包含在您的 .apk 文件中,允许从应用程序的大文件中获取所需的数据。由于大 blob 不是标准格式,因此人们无法轻松地从中提取文件。为了更加确定,您总是可以用一些其他数据(也许只是一些纯文本)填充文件的开头,以使 blob 看起来像其他东西。

【讨论】:

  • 这看起来是一个简单而有效的解决方案。会试一试。谢谢戴夫!
  • 我想我更喜欢流转换解决方案而不是 blob 解决方案。前者可以让我轻松更新资产,而后者需要更多的工作来重新生成和更新索引文件。
猜你喜欢
  • 2011-03-25
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
相关资源
最近更新 更多