fopen / fread APK Активы от NativeActivity на Android

Я смог найти решения только от 2010 года и ранее. Поэтому я хотел посмотреть, есть ли более актуальная позиция по этому вопросу.

Я хотел бы избежать использования Java и просто использовать C ++ для доступа к файлам (некоторые размером менее 1 МБ или более), хранящимся в APK. С помощью AssetManager означает, что я не могу получить доступ к файлам, как любой другой файл в любой другой операционной системе (включая iOS).

Если нет, есть ли метод в C ++, где я мог бы каким-то образом отобразить fopen / fread в API AssetManager?

6

Решение

Я действительно нашел довольно элегантный ответ на проблему и написал об этом здесь.

Резюме:

  • API AAssetManager имеет привязки NDK. Это позволяет загружать активы из APK.
  • Можно объединить набор функций, которые знают, как читать / писать / искать что-либо, и маскировать их как указатель файла (FILE *).
  • Если мы создаем функцию, которая принимает имя актива, использует AssetManager, чтобы открыть его, а затем маскирует результат как ФАЙЛ *, то у нас есть нечто, очень похожее на fopen.
  • Если мы определим макрос с именем fopen, мы можем вместо этого заменить все виды использования этой функции на наши.

В моем блоге есть полная запись и весь код, который вам нужно реализовать на чистом C. Я использую это для сборки lua и libogg для Android.

10

Другие решения

Короткий ответ

Нет. AFAIK отображение fread / fopen в C ++ в AAssetManager невозможно. И если бы это было возможно, это ограничило бы вас файлами в папке активов. Однако есть обходной путь, но он не прост.

Длинный ответ

Это ЯВЛЯЕТСЯ можно получить доступ к любому файлу в любом месте APK, используя zlib и libzip в C ++.
Требования: немного java, zlib и / или libzip (для простоты использования, поэтому я остановился). Вы можете получить libzip здесь: http://www.nih.at/libzip/

libzip может потребоваться немного поработать, чтобы заставить его работать на Android, но ничего серьезного.

Шаг 1: получить местоположение APK в Java и перейти к JNI / C ++

String PathToAPK;
ApplicationInfo appInfo = null;
PackageManager packMgmr = parent.getPackageManager();
try {
appInfo = packMgmr.getApplicationInfo("com.your.application", 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Unable to locate APK...");
}

PathToAPK = appInfo.sourceDir;

Передача PathToAPK в C ++ / JNI

JNIEXPORT jlong JNICALL Java_com_your_app(JNIEnv *env, jobject obj, jstring PathToAPK)
{
// convert strings
const char *apk_location = env->GetStringUTFChars(PathToAPK, 0);

// Do some assigning, data init, whatever...
// insert code here

//release strings
env->ReleaseStringUTFChars(PathToAPK, apk_location);

return 0;
}

Предполагая, что теперь у вас есть std :: string с вашим местоположением APK и у вас работает zlib на libzip, вы можете сделать что-то вроде этого:

if(apk_open == false)
{
apk_file = zip_open(apk_location.c_str(), 0, NULL);

if(apk_file == NULL)
{
LOGE("Error opening APK!");
result = ASSET_APK_NOT_FOUND_ERROR;
}else
{
apk_open = true;
result = ASSET_NO_ERROR;
}
}

И прочитать файл из APK:

if(apk_file != NULL){
// file you wish to read; **any** file from the APK, you're not limited to regular assets
const char *file_name = "path/to/file.png";

int file_index;
zip_file *file;
struct zip_stat file_stat;

file_index = zip_name_locate(apk_file, file_name, 0);

if(file_index == -1)
{
zip_close(apk_file);
apk_open = false;

return;
}

file = zip_fopen_index(apk_file, file_index, 0);
if(file == NULL)
{
zip_close(apk_file);
apk_open = false;

return;
}

// get the file stats
zip_stat_init(&file_stat);
zip_stat(apk_file, file_name, 0, &file_stat);
char *buffer = new char[file_stat.size];

// read the file
int result = zip_fread(file, buffer, file_stat.size);
if(result == -1)
{
delete[] buffer;
zip_fclose(file);

zip_close(apk_file);
apk_open = false;

return;
}

// do something with the file
// code goes here

// delete the buffer, close the file and apk
delete[] buffer;
zip_fclose(file);

zip_close(apk_file);
apk_open = false;

Не совсем fopen / fread, но он выполняет свою работу. Должно быть довольно легко обернуть это в вашу собственную функцию чтения файлов, чтобы абстрагировать zip-слой.

6

По вопросам рекламы [email protected]