你可以使用 AES 加密 ZIP 文件 https://stackoverflow.com/questions/166340/write-a-password-protected-zip-file-in-java但是提取资产时会产生开销,这可能是一个问题,因为在编写游戏时性能通常相当重要。
然而,正如您所说,使用安全加密并不真正值得,因为如果有人真正感兴趣,他们可以在您的应用程序的源代码中找到密钥。所以你可以写一个InputStream
and OutputStream
您自己对 ZIP 文件的字节执行一些简单的转换。这在读取文件时可以快速撤消,但会“损坏”ZIP 文件,足以阻止某人浏览他们的 SD 卡。
使用它时,您可以将流放在File
and ZIPInputStream
, e.g.:
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 看起来像其他东西。