2011-04-07 12 views
28

मैं एक एंड्रॉइड एप्लिकेशन पर काम कर रहा हूं जो ईएलएफ बाइनरी पर निर्भर करता है: हमारे जावा कोड इस बाइनरी के साथ काम करने के लिए बातचीत करते हैं। यह रनटाइम को प्रारंभ करने और एप्लिकेशन स्टार्टअप और एप्लिकेशन से बाहर निकलने/मांग पर समाप्त करने की आवश्यकता है।Android एप्लिकेशन के भीतर निष्पादन योग्य होस्टिंग

सवाल:

  1. मैं यह सोचते हैं कि हम इस द्विआधारी Runtime.exec() API का उपयोग निष्पादित करने के लिए सक्षम हो जाएगा। क्या मुझे कोई समस्या है कि को मेरी लाइब्रेरी को फ़ोल्डर संरचना में डालने की आवश्यकता है? सिस्टम रनटाइम इस निष्पादन योग्य कैसे पता लगाएगा? क्या कक्षा पथ सेटिंग का कोई प्रकार है?

  2. के बाद से आवेदन इस क्रम पर निर्भरता है, मैं एक सेवा के आसपास लपेटकर इतना है कि यह शुरू किया जा सकता या बंद कर दिया के रूप में आवश्यक के सोच रहा था। एंड्रॉइड प्रोजेक्ट में ऐसे निष्पादन योग्य को संभालने का सबसे अच्छा तरीका क्या है?

  3. अन्य विकल्प क्या हैं, यह मानते हुए कि मेरे पास इस निष्पादन योग्य के लिए स्रोत कोड नहीं है?

कृपया सलाह दें।

धन्यवाद।

उत्तर

37

1) नहीं, सिस्टम फ़ाइलों तक पहुंचने वाले लोगों के अलावा कोई बाधा नहीं होनी चाहिए और इस प्रकार रूट की आवश्यकता है। कहीं और प्रदूषण से बचने के लिए सबसे अच्छी जगह सीधे/डेटा/डेटा/[your_package_name] होगी।

2) देशी पुस्तकालयों के खिलाफ संकलन के बारे में एक बहुत अच्छी चर्चा यहां पाई जा सकती है: http://www.aton.com/android-native-libraries-for-java-applications/। एक और विकल्प हाथ के लिए एक क्रॉस-कंपाइलर है (यहां कर्नेल को संकलित करने के लिए उपयोग किया जाता है, यह मुफ़्त है: http://www.codesourcery.com/sgpp/lite/arm)। यदि आप अपनी कैमांड निष्पादित करने वाली सेवा को बनाए रखने की योजना बनाते हैं, तो चेतावनी दी जानी चाहिए कि किसी भी समय एंड्रॉइड द्वारा सेवाओं को रोका जा सकता है और पुनरारंभ किया जा सकता है।

3) अब, यदि आपके पास स्रोत कोड नहीं है, तो मुझे उम्मीद है कि आपकी फ़ाइल कम से कम एक हाथ निष्पादन योग्य के रूप में संकलित की जाएगी। यदि नहीं, तो मैं नहीं देखता कि आप इसे कैसे चला सकते हैं।


आप अपने जावा वर्ग में निम्न कमांड चलाकर फ़ाइल निष्पादित करेंगे:

String myExec = "/data/data/APPNAME/FILENAME"; 
Process process = Runtime.getRuntime().exec(myExec); 
DataOutputStream os = new DataOutputStream(process.getOutputStream()); 
DataInputStream osRes = new DataInputStream(process.getInputStream()); 

मैं अपने निष्पादन के बारे में कुछ भी नहीं पता है, तो आप या वास्तव में InputStream और outputStream प्राप्त करने की आवश्यकता नहीं हो सकता है ।


मुझे लगता है कि एडीबी चल बाइनरी फ़ाइल पुश करने के लिए यह सोचते हैं रहा हूँ, इसलिए मैं एक स्वच्छ जिस तरह से यह पैकेज करने के लिए देख रहा था सवाल से बाहर है। मुझे आपके ऐप में निष्पादन योग्य समेत एक शानदार पोस्ट मिली। यहाँ देखें:

एंड्रॉयड जावा एप्लिकेशन से, assets फ़ोल्डर

  • संपत्ति फ़ोल्डर में द्विआधारी का उपयोग करके: http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App

    महत्वपूर्ण हिस्सा इस एक (जोर मेरा) है।

  • InputStream प्राप्त करने के लिए getAssets().open(FILENAME) का उपयोग करें।
  • इसे /data/data/APPNAME (उदा। /data/data/net.gimite.nativeexe) पर लिखें, जहां आपके एप्लिकेशन के पास फाइलें लिखने और इसे निष्पादन योग्य बनाने की पहुंच है।
  • ऊपर दिए गए कोड का उपयोग कर /system/bin/chmod 744 /data/data/APPNAME/FILENAME चलाएं।
  • ऊपर दिए गए कोड का उपयोग करके अपने निष्पादन योग्य को चलाएं।

पद assets फ़ोल्डर का उपयोग करता है, कि एंड्रॉयड स्थिर फ़ाइलों के लिए पता चलता है raw फ़ोल्डर के insted:

युक्ति: यदि आप संकलन समय पर अपने आवेदन में एक स्थिर फ़ाइल को बचाने के लिए चाहते हैं, फ़ाइल को अपने प्रोजेक्ट res/raw/निर्देशिका में सेव करें। आप RRraw को पारित करके, OpenRawResource() के साथ इसे खोल सकते हैं। संसाधन आईडी यह विधि एक इनपुटस्ट्रीम देता है जिसका उपयोग आप फ़ाइल को पढ़ने के लिए कर सकते हैं (लेकिन आप मूल फ़ाइल में नहीं लिख सकते हैं)।

डेटा फ़ोल्डर को एक्सेस करने के लिए आपको यहां दिए गए निर्देशों का पालन कर सकते: http://developer.android.com/guide/topics/data/data-storage.html#filesInternal इसके अलावा, वहाँ है File#setExecutable(boolean); विधि है कि शेल कमांड के बजाय काम करता है चाहिए।

तो, सब कुछ एक साथ डाल, मैं कोशिश करेंगे:

InputStream ins = context.getResources().openRawResource (R.raw.FILENAME) 
byte[] buffer = new byte[ins.available()]; 
ins.read(buffer); 
ins.close(); 
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); 
fos.write(buffer); 
fos.close(); 


File file = getFileStreamPath (FILENAME); 
file.setExecutable(true); 

बेशक, यह सब स्थापना के बाद केवल एक बार किया जाना चाहिए। आप onCreate() के अंदर एक त्वरित जांच कर सकते हैं या फ़ाइल की उपस्थिति के लिए जो कुछ भी जांचता है और फ़ाइल नहीं है, तो यह सभी आदेश निष्पादित करता है।

अगर यह काम करता है तो मुझे बताएं। सौभाग्य!

+0

@Aleadam: आपके उत्तर के लिए धन्यवाद। हाँ, स्रोत कोड एआरएम निष्पादन योग्य के रूप में संकलित किया गया है और मैंने इसे कमांड लाइन से रूट किए गए एंड्रॉइड फोन पर निष्पादित करने का प्रयास किया है और यह काम करता है। मुझे यह निष्पादन योग्य पैकेज करने का एक तरीका है मेरे एंड्रॉइड प्रोजेक्ट के अंदर, इसे आंतरिक फ़ाइल सिस्टम (/ डेटा/डेटा/) पर कॉपी करें और फिर इसे वहां से निष्पादित करें। – Samuh

+0

कूल, तो मुझे लगता है कि आप अच्छे आकार में हैं। क्या आपको उस निष्पादन योग्य को सभी को चलाने की आवश्यकता है समय या यह सिर्फ एक विशिष्ट, त्वरित नौकरी कर रहा है? – Aleadam

+0

@ सैमुह अद्यतन उत्तर की जांच करें। – Aleadam

1

मैंने एनडीके का उपयोग करके ऐसा कुछ किया है। मेरी रणनीति एनडीके का उपयोग करके कार्यक्रम को पुन: संकलित करना था और कुछ रैपर जेएनआई कोड लिखना था जिसे प्रोग्राम के main फ़ंक्शन में बुलाया गया था।

मुझे यकीन नहीं है कि एनडीके कोड का जीवन चक्र कैसा है। यहां तक ​​कि सेवाओं को लंबे समय तक चलने के इरादे से भी शुरू किया जा सकता है जब सिस्टम सुविधाजनक हो। आपको शायद अपने एनडीके थ्रेड को बंद करना होगा और आवश्यक होने पर इसे पुनरारंभ करना होगा।

+0

मैं इसके साथ सहमत हूं - एक जेएनआई रैपर आगे सामान्य तरीका है। यदि संभव हो, तो मैं फिर से डिज़ाइन करूँगा ताकि ईएलएफ एक सामान्य डेमॉन न हो - लंबी अवधि की प्रक्रिया बैटरी जीवन के लिए खराब हो। –

+0

मेरे पास इस बाइनरी के लिए स्रोत कोड नहीं है; सिर्फ एक विशेष मशीन आर्किटेक्चर के लिए निष्पादन योग्य। :-( – Samuh

9

यहां निष्पादन योग्य पैकेज को चलाने और चलाने के लिए एक संपूर्ण मार्गदर्शिका है। मैंने इसे यहां और अन्य लिंक, साथ ही साथ अपने स्वयं के परीक्षण और त्रुटि पर आधारित पाया।

1.) अपने एसडीके परियोजना में, अपने/संपत्ति फ़ोल्डर में निष्पादन योग्य फ़ाइल डाल

2.) (/ डेटा/डेटा को प्रोग्राम है कि निर्देशिका फ़ाइलें स्ट्रिंग प्राप्त/your_app_name/फ़ाइलें) इस

की तरह
String appFileDirectory = getFilesDir().getPath(); 
String executableFilePath = appFileDirectory + "/executable_file"; 

3।(आमतौर पर/डेटा/इस तरह एक समारोह के साथ डेटा से/संपत्ति को अपने ऐप्लिकेशन के "फ़ाइलें" सबफ़ोल्डर में फ़ोल्डर निष्पादन योग्य फ़ाइल कॉपी/your_app_name/फ़ाइलें):) यदि आपके ऐप की परियोजना जावा कोड में

private void copyAssets(String filename) { 

AssetManager assetManager = getAssets(); 

InputStream in = null; 
OutputStream out = null; 
Log.d(TAG, "Attempting to copy this file: " + filename); // + " to: " +  assetCopyDestination); 

try { 
    in = assetManager.open(filename); 
    Log.d(TAG, "outDir: " + appFileDirectory); 
    File outFile = new File(appFileDirectory, filename); 
    out = new FileOutputStream(outFile); 
    copyFile(in, out); 
    in.close(); 
    in = null; 
    out.flush(); 
    out.close(); 
    out = null; 
} catch(IOException e) { 
Log.e(TAG, "Failed to copy asset file: " + filename, e); 
} 

Log.d(TAG, "Copy success: " + filename); 
} 

4.) निष्पादन योग्य_फाइल पर फ़ाइल अनुमतियों को वास्तव में निष्पादन योग्य बनाने के लिए बदलें। जावा के साथ यह क्या कहता है:

File execFile = new File(executableFilePath); 
execFile.setExecutable(true); 

5.) इस तरह फ़ाइल निष्पादित करें:

Process process = Runtime.getRuntime().exec(executableFilePath); 

ध्यान दें कि यहाँ करने के लिए भेजा किसी भी फाइल (जैसे इनपुट और आउटपुट फाइल के रूप में) अपने पूर्ण पथ स्ट्रिंग्स होना आवश्यक है का निर्माण किया। ऐसा इसलिए है क्योंकि यह एक अलग स्पॉन्डेड प्रक्रिया है और इसमें "pwd" क्या है इसकी कोई अवधारणा नहीं है।

आप कमांड के stdout में पढ़ना चाहते हैं तो आप ऐसा कर सकते हैं, लेकिन अभी तक यह केवल, नहीं निष्पादन योग्य फ़ाइल ("ls" की तरह) प्रणाली आदेश के लिए मेरे लिए काम कर रहा है:

BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())); 
int read; 
char[] buffer = new char[4096]; 
StringBuffer output = new StringBuffer(); 
while ((read = reader.read(buffer)) > 0) { 
    output.append(buffer, 0, read); 
} 
reader.close(); 
process.waitFor(); 

Log.d (टैग, "आउटपुट:" + output.toString());

+0

कौन सा copyFile() विधि आप उपयोग कर रहे हैं? – x29a

+0

IOUtils।कॉमन्स-आईओ पैकेज में कॉपी (इन, आउट) काम करता है: http://stackoverflow.com/a/51753/134761 – angularsen

+0

अगर कोई आवश्यक तर्क कोड को स्पष्ट करता है तो यह अच्छा होगा। क्या आप "execableFilePath" के बाद सीधे एक तर्क लिख सकते हैं .. उदाहरण – Zillinium

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