你可以使用AES加密ZIP文件,但提取资产时会有一些额外的开销,这可能是一个问题,因为在编写游戏时通常性能非常重要。
然而,正如你自己所说,使用安全加密并不值得,因为如果有人真的感兴趣,他们可以在应用程序的源代码中找到密钥。因此,你可以自己编写InputStream
和OutputStream
来对ZIP文件的字节进行一些微不足道的转换。这样读取文件时很快就可以撤消,但会“破坏”ZIP文件,足以阻止某些人只是浏览他们的SD卡。
在使用它时,你需要将流放置在File
和ZIPInputStream
之间,例如:
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);
}
@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;
}
@Override
public int read(byte[] buffer, int offset, int count)
throws IOException {
int bytesRead = super.read(buffer, offset, count);
translateBuffer(buffer);
return bytesRead;
}
}
或者,如果您不关心压缩,可以不使用ZIP。只需将所有资产连接在一起形成一个大的数据块。创建数据块时,将每个资产的开始和结束位置写入索引文件。然后,在您的.apk文件中包含该索引文件,以便从应用程序中获取所需的数据。由于大型数据块不是标准格式,因此人们无法轻松地从中提取文件。为了确保安全性,您始终可以在文件开头填充其他数据(例如纯文本),使数据块看起来像其他东西。
.apk
。这不会阻止有决心的人,但它将防止随意浏览者找到资产,我认为这是意图所在。 - David Webb