2011-06-23 8 views
6

मेरे पास काम करने के लिए अनुवर्ती परिदृश्य है। मुझे एक एंड्रॉइड प्रोजेक्ट में उपयोग करने के लिए एक साझा लाइब्रेरी (libeffect.so) दिया गया था, मैं एक क्लाइंट के लिए काम कर रहा हूं। मेरे पास साझा लाइब्रेरी स्रोत कोड नहीं है, मेरे पास सिर्फ मेरे साथ .so फ़ाइल है। पुस्तकालय एंड्रॉइड उपकरणों पर काम करने के लिए पूर्व संकलित है। साझा लाइब्रेरी के साथ साथ मैं विधि हस्ताक्षरएंड्रॉइड एप्लिकेशन में मौजूदा साझा लाइब्रेरी (.so) का उपयोग

public static native void doEffect(int param1, IntBuffer intBuffer); 

तो अब मैं कैसे इस देशी पद्धति को कॉल करने के लिए स्रोत की, पर कुछ questiosn है, अगर यह सिर्फ .so फ़ाइल होने के लिए संभव है, इसलिए वहाँ है वे हैं:

  1. मैं परिभाषित जब .so था या मैं अपने प्रोजेक्ट में किसी भी पैकेज/कक्षा में इस हस्ताक्षर का उपयोग कर सकते उन लोगों के रूप में एक ही पैकेज/कक्षा में देशी विधि हस्ताक्षर जगह की जरूरत है कि रनटाइम के दौरान jvm साझा लाइब्रेरी में विधि ढूंढ पाएगा? उदाहरण के लिए, यदि यह साझा लाइब्रेरी पहली बार क्लास mypackage में उपयोग की गई थी। MyClass, क्या मुझे एक ही पैकेज, कक्षा बनाने और फिर विधि हस्ताक्षर डालने की आवश्यकता है?

  2. मुझे यह जगह कहां रखने की आवश्यकता है। इसलिए मेरी एपीके फ़ाइल के अंदर इस फ़ाइल को तैनात करने के लिए मेरे ग्रहण एंड्रॉइड प्रोजेक्ट के अंदर फ़ाइल?

ये सवाल noob ध्वनि सकता है, लेकिन मैं JNDI के साथ काम किया कभी नहीं किया है पहले तो मैं थोड़ा चिंतित हूँ किसी भी त्रुटि के बिना विधि doEffect बुला प्राप्त हो सकते हैं। कोई भी जवाब जो मुझे मार्गदर्शन कर सकता है, बहुत स्वागत है।

कई धन्यवाद थियागो

उत्तर

6
  1. मैं उन परिभाषित जब .so था या मैं किसी भी में इस हस्ताक्षर का उपयोग कर सकते रूप में एक ही पैकेज/कक्षा में देशी विधि हस्ताक्षर जगह की जरूरत है मेरे प्रोजेक्ट में पैकेज/क्लास रनटाइम के दौरान जेवीएम साझा लाइब्रेरी में विधि ढूंढ पाएगा? उदाहरण के लिए, यदि यह साझा लाइब्रेरी पहली बार कक्षा mypackage में उपयोग की गई थी। MyClass, क्या मुझे समान पैकेज, कक्षा बनाने और फिर विधि हस्ताक्षर डालने की आवश्यकता है?

समान पैकेज/कक्षा बनाने की कोई आवश्यकता नहीं है। आप किसी भी पैकेज में विधि हस्ताक्षर डाल सकते हैं।

public class NativeLib { 

    static { 
    System.loadLibrary("so_file"); 
    } 

    public static native void doEffect(int param1, IntBuffer intBuffer); 

} 

2.Where मैं इस फ़ाइल मेरी apk फ़ाइल के अंदर तैनात करने के लिए मेरी ग्रहण एंड्रॉयड परियोजना अंदर इस .so फ़ाइल की आवश्यकता है?

आपने इसे अपने आवेदन के lib फ़ोल्डर में भी रखा है। अगर lib फ़ोल्डर नहीं है तो आप एक lib फ़ोल्डर बना सकते हैं और .so फ़ाइल डाल सकते हैं। आप सिस्टम.लोड लाइब्रेरी ("so_ file") का उपयोग करके इसे कॉल कर सकते हैं;

+0

धन्यवाद @ सुजीत। मैं इस ट्यूटोरियल को देख रहा था, http://www.android10.org/index.php/articlesother/276-call-c-code-from-application-using-ndk, और मुझे लगता है कि उत्पन्न सी ++ कोड स्निपेट में है जावा पैकेज और विधि नाम द्वारा रचित विधि का नाम। क्या मैं देशी हस्ताक्षर का उपयोग करने के तरीके को प्रभावित नहीं करता? मैंने सोचा कि साझा पुस्तकालय बनाया गया था जब मुझे उसी नाम सम्मेलन का पालन करना चाहिए। एक और सवाल, एक बार जब मेरे एंड्रॉइडप्रोजेक्ट/lib फ़ोल्डर में .so फ़ाइल हो, तो क्या यह फ़ाइल एपीके फ़ाइल के साथ निर्यात की जाएगी? क्या मुझे उप फ़ोल्डर armeabi फ़ोल्डर बनाने की आवश्यकता है? बहुत धन्यवाद, टी – Thiago

1

1 मैं परिभाषित जब उन के रूप में ही पैकेज/कक्षा में देशी विधि हस्ताक्षर जगह की जरूरत है।तो क्या मैं इस परियोजना में किसी भी पैकेज/कक्षा में इस हस्ताक्षर का उपयोग कर सकता था कि रनटाइम के दौरान जेवीएम साझा लाइब्रेरी में विधि ढूंढ पाएगा?

http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html के अनुसार आपको एक मिलान पैकेज और कक्षा का नाम उपयोग करना होगा।

मैंने केवल जेएनआई विधियों को देखा है जहां सी साइड फ़ंक्शंस को Java_com_company_whatever_SomeClass_someMethod जैसी चीजें कहा जाता है, जिसका अर्थ है कि आपको समान नाम वाली जावा क्लास में 'मूल' घोषणाएं डालनी होंगी।

.so फ़ाइल को देखने के लिए टूल 'एनएम' या 'एनएम ++' (वे एनडीके में प्रीकंपल्ड फ़ोल्डरों में हैं) का उपयोग करें और देखें कि इसमें क्या फ़ंक्शन परिभाषित किए गए हैं। यदि आप कोई प्रारंभिक जावा_ देखते हैं, तो वे वही हैं जो आप चाहते हैं।

मुझे पिछले दावा का संदेह है कि आप उन कार्यों को कॉल कर सकते हैं जिन्हें Java_PACKAGE_CLASS_METHOD प्रारूप में नामित नहीं किया गया है; यह एक विरासत व्यवहार हो सकता है यदि यह वास्तव में काम करता है, लेकिन यदि आप कर सकते हैं, तो यह खतरनाक लगता है - आपको गलत मिल सकता है।

2 कहाँ मैं इस फ़ाइल मेरी apk फ़ाइल के अंदर तैनात करने के लिए मेरी ग्रहण एंड्रॉयड परियोजना के अंदर इस .so फ़ाइल की आवश्यकता है?

आपका .so libs में रहती है/कितने प्लेटफार्मों आप के साथ, जहां 'libs' की एक सहकर्मी है काम कर रहे हैं पर निर्भर करता है armeabi, libs/armeabi-v7a, libs/86, और/या libs/MIPS 'src' और 'res'। मुझे नहीं पता कि एंड्रॉइड प्लेटफार्म क्वालीफायर के बिना libs/lib में दिखता है, लेकिन इसमें कोई स्पष्ट लाभ नहीं है। स्थिति अधिकांश/सभी इंटेल उपकरणों द्वारा जटिल होती है जिसमें फैंसी तकनीक शामिल है जो उन्हें x86 हार्डवेयर पर अधिकांश एआरएम पुस्तकालयों को निष्पादित करने की अनुमति देती है।

आगे, मैं एक जेएनआई कक्षा का एक इंटरफ़ेस घोषित करना चाहता हूं और एक कारखाना प्रदान करना चाहता हूं (यह यहां एक विधि है, लेकिन यह एक कारखाना वर्ग पसंद करती है) जो चीजें गलत होने पर इंटरफ़ेस का नो-ऑप कार्यान्वयन प्रदान करती है: यह यूनिट परीक्षण की सुविधा प्रदान करता है और इसके तरीकों को कॉल करने से पहले शून्य मूल्यों के परीक्षण के बारे में गड़बड़ी करने से बचाता है (मानते हुए कि आप आरामदायक हैं कि आपकी शिप लाइब्रेरी कभी गायब नहीं होगी या विधि हस्ताक्षर नहीं बदलेगी - आपके एकीकरण परीक्षणों को यह जांचना चाहिए):

public interface YourLibI { 
    @Override 
    public native yourMethod(); 

    public static final NO_OP = new YourLibI() { 
     @Override 
     public void yourMethod(){} 
    } 
} 

public class YourLib extends YourLibI { 
    public newYourLibI() { 
     try { 
      return new YourLib(); 
     } 
     catch (UnsatisfiedLinkError e) { 
      Log.e("YourLibJNI", "Load failed, returning NO-OP dummy", e); 
      return YourLibI.NO_OP; 
     } 
    } 

    static { 
     System.loadLibrary("arbitronSDK"); 
    } 

    private YourLib() { 
    } 

    @Override 
    public native void yourMethod(); 
} 

मैं आम तौर पर इंटरफेस 'xxxI' नहीं कहता हूं लेकिन मुझे लगता है कि आपकी लाइब्रेरी की जेएनआई कक्षा को यूटिलिटीजेएनआई (जहां मैं इंटरफ़ेस 'उपयोगिता' कहूंगा) जैसी कुछ अच्छी तरह से नहीं कहा जाता है।