Загрузка игровых ресурсов на SD-карту на Android - PullRequest
3 голосов
/ 23 апреля 2010

Я разрабатываю игру для Android , которая должна загрузить некоторые ресурсы на SD-карту , чтобы размер приложения был как можно меньше. Я думал об использовании несжатого zip файла для объединения всех активов.

Требование клиента - максимально защитить этих активов. Быть частью apk считается достаточной защитой, но если я сделаю это, apk size будет огромным. Если я просто вставлю пакет SD в карту SD, то любой сможет распаковать его и изучить его содержимое.

Есть ли простой способ сделать это, не возвращаясь к ужасному DRM?

Очевидно, что если кто-то действительно хочет проверить ресурсы игры для Android, он может. Я просто ищу простое решение, чтобы не делать это очень простым.

1 Ответ

4 голосов
/ 23 апреля 2010

Вы можете зашифровать ZIP-файл с помощью AES , но при извлечении ресурсов могут возникнуть накладные расходы, что может быть проблемой, поскольку производительность при написании игры обычно очень важна.

ОднакоКак вы уже сказали, использование безопасного шифрования на самом деле не имеет смысла, поскольку, если кто-то действительно заинтересован, он может найти ключи в исходном коде вашего приложения.Таким образом, вы можете написать InputStream и OutputStream самостоятельно, чтобы выполнить тривиальный перевод байтов ZIP-файла.Это было бы быстро отменить при чтении файла, но «повредило» ZIP-файл достаточно, чтобы помешать кому-то просто просматривать их SD-карту.

При использовании вы помещаете ваш поток между Fileи ZIPInputStream, например:

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

В качестве примера перевода вы можете просто XOR для всех байтов с известным значением:

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 кактебя не волнует сжатие.Просто объедините все активы в один большой объект.При создании большого двоичного объекта запишите начальное и конечное местоположение каждого актива в индексный файл.Затем индексный файл будет включен в ваш файл .apk, что позволит вам получить необходимые данные из большого файла в вашем приложении.Поскольку большой двоичный объект не был бы в стандартном формате, люди не смогли бы легко извлечь из него файлы.Чтобы быть уверенным, вы всегда можете дополнить начало файла некоторыми другими данными - возможно, просто каким-нибудь простым текстом - чтобы блоб выглядел как-то еще.

...