android - 在 Android 上将游戏 Assets 下载到 SD 卡

标签 android copy-protection sd-card

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

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

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

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

最佳答案

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

但是,正如您自己所说,使用安全加密并不值得,因为如果有人真的感兴趣,他们可以在您的应用程序的源代码中找到 key 。因此,您可以自己编写一个 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,因为您不关心压缩。只需将所有 Assets 连接成一个大 blob。在创建 blob 时,将每个 Assets 的开始和结束位置写入索引文件。然后索引文件将包含在您的 .apk 文件中,允许您从应用程序的大文件中获取所需的数据。由于大 blob 不是标准格式,因此人们无法轻松地从中提取文件。为了更加确定,您始终可以用一些其他数据填充文件的开头 - 也许只是一些纯文本 - 使 blob 看起来像其他东西。

关于android - 在 Android 上将游戏 Assets 下载到 SD 卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2697644/

相关文章:

Android 到 Android TCP 连接

android - 使用 Python 进行 Unicode URL 编码/解码

C# 应用程序许可证组件和控件

android - 将图像从 sdcard 加载到 imageview 不工作

java - Sqlite使用ListView插入数据

android - Flutter 应用程序中的 Bottomnavigationbar 项目图标

ios - 在 iOS 上检测盗版应用程序 - 会产生服务器成本的吸血鬼

java - 使用 JNI 保护 Java 源代码

android - 我如何编写其他应用程序可读的文件?

android - 使用cordova和文件插件在android上强制使用外部sdcard