2013-08-06 8 views
5

मैं केवल 2010 और उससे पहले के समाधान ढूंढने में सक्षम हूं। तो मैं देखना चाहता था कि इस पर एक और अधिक अद्यतित रुख था या नहीं।एंड्रॉइड पर मूल सक्रियता से एफपीएन/फ्रेड एपीके संपत्ति

मैं जावा का उपयोग करने से बचाना चाहता हूं और एपीके में संग्रहीत फ़ाइलों (कुछ कम या 1 एमबी से अधिक) तक पहुंचने के लिए पूरी तरह से सी ++ का उपयोग करना चाहता हूं। AssetManager का उपयोग करना है कि मैं हर दूसरे ऑपरेटिंग सिस्टम (आईओएस सहित) पर हर दूसरी फ़ाइल जैसी फ़ाइलों तक नहीं पहुंच सकता।

यदि नहीं, तो क्या सी ++ में कोई तरीका है जहां मैं किसी भी तरह से एसेटमैनेजर एपीआई को फॉपेन/फ़्रेड मैप कर सकता हूं?

+1

चूंकि संपत्तियां फाइल नहीं हैं, इसलिए उत्तर "नहीं" है। संपत्ति ज़िप संग्रह में प्रविष्टियां हैं जो एपीके है। – CommonsWare

+0

'टिस एक अच्छा बिंदु ... –

+0

तकनीकी रूप से, चूंकि एक एपीके एक फैंसी ज़िप फ़ाइल से अधिक कुछ नहीं है, इसलिए एपीके में कहीं भी किसी भी फ़ाइल तक पहुंचना पूरी तरह से संभव है जैसे कि यह सी ++ में ज़िप फ़ाइल थी। हालांकि इसे * कुछ * जावा की आवश्यकता होती है, लेकिन केवल आपके एपीके इंस्टॉल स्थान प्राप्त करने के लिए। मुझे पता है कि एक तथ्य रीडिंग एक मुद्दा नहीं है, लेकिन मैंने कभी भी एपीके को लिखने की कोशिश नहीं की। – Erik

उत्तर

6

लघु जवाब

सं AFAIK मानचित्रण fread/AAssetManager को C++ fopen संभव नहीं है। और यदि यह संभवतः आपको संपत्ति फ़ोल्डर में फ़ाइलों तक सीमित कर देगा। हालांकि एक कामकाज है, लेकिन यह सीधा नहीं है।

लांग उत्तर

यह सी में zlib और libzip का उपयोग कर APK में कहीं भी किसी भी फ़ाइल का उपयोग करना संभव है ++। आवश्यकताएं: कुछ जावा, zlib और/या libzip (उपयोग की आसानी के लिए, तो यही है कि मैं किसके लिए बस गया)। आप यहां libzip प्राप्त कर सकते हैं: http://www.nih.at/libzip/

libzip को एंड्रॉइड पर काम करने के लिए कुछ tinkering की आवश्यकता हो सकती है, लेकिन कुछ भी गंभीर नहीं है।

चरण 1: जावा में APK स्थान निकालते हैं और 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 पासिंग ++/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; 
} 

मान लिया जाये कि आप अब एक एसटीडी है :: स्ट्रिंग के लिए पारित आपके एपीके स्थान के साथ और आपके पास libzip पर zlib काम कर रहा है, आप ऐसा कुछ कर सकते हैं:

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 लेकिन यह काम किया जाता है। ज़िप परत को सारणीबद्ध करने के लिए इसे अपने स्वयं के फ़ाइल पढ़ने के फ़ंक्शन पर लपेटना बहुत आसान होना चाहिए।

+0

libz इन दिनों एंड्रॉइड टूलचैन द्वारा प्रदान किया जाता है - क्या libzip पर इसका उपयोग करने में कोई खतरा होगा? क्या वे भी अलग हैं? –

+0

कोई भी नहीं। मैं एंड्रॉइड का उपयोग libz भी प्रदान किया; libzip सिर्फ एक पुस्तकालय है जो थोड़ा आसान पढ़ने/लिखने के लिए शीर्ष libz पर बैठता है। – Erik

+1

बफर पर हटाए गए एक त्वरित फिक्स को हटाएं [] हटाएं। –

8

मुझे वास्तव में समस्या का सुंदर सुरुचिपूर्ण उत्तर और blogged about it here मिला।

सार है:

  • AAssetManager एपीआई NDK बाइंडिंग है। यह आपको एपीके से संपत्ति लोड करने देता है।
  • उन कार्यों के एक समूह को जोड़ना संभव है जो किसी भी चीज को पढ़ने/लिखने/खोजना और फ़ाइल सूचक (फ़ाइल *) के रूप में छिपाने के बारे में जानते हैं।
  • यदि हम एक ऐसा खाता बनाते हैं जो संपत्ति नाम लेता है, तो इसे खोलने के लिए एसेटमैनेजर का उपयोग करता है, और फिर परिणाम को फ़ाइल के रूप में छिपाता है * तो हमारे पास कुछ ऐसा है जो फॉपेन के समान है।
  • यदि हम फॉपेन नामक एक मैक्रो को परिभाषित करते हैं तो हम इसके बजाय उस फ़ंक्शन के सभी उपयोगों को प्रतिस्थापित कर सकते हैं।

मेरे ब्लॉग में एक पूर्ण लेखन और शुद्ध कोड में लागू करने के लिए आवश्यक सभी कोड हैं। मैं एंड्रॉइड के लिए लुआ और libogg बनाने के लिए इसका उपयोग करता हूं।

+1

: 'size_t file_size (FILE * fp) { android_seek (fp, 0L, SEEK_END); size_t sz = ftell (fp); android_seek (fp, 0L, SEEK_SET); रिटर्न एसजे; } ' –

संबंधित मुद्दे