2010-03-25 5 views
16

मैं इस stackoverflow posting के समान कुछ करने की कोशिश कर रहा हूं। मैं क्या करना चाहता हूं एसडी कार्ड से किसी गतिविधि या सेवा की परिभाषा को पढ़ना है। स्पष्ट अनुमति समस्याओं से बचने के लिए, मैं .apk में इस गतिविधि का एक खोल संस्करण बनाता हूं, लेकिन इसे रन टाइम पर एसडी कार्ड पर रहने वाले उसी नाम की गतिविधि के साथ बदलने की कोशिश करता हूं। दुर्भाग्यवश, मैं DexClassLoader का उपयोग कर एसडी कार्ड से गतिविधि श्रेणी परिभाषा को लोड करने में सक्षम हूं, लेकिन मूल श्रेणी परिभाषा वह है जिसे निष्पादित किया जाता है। क्या यह निर्दिष्ट करने का कोई तरीका है कि नई कक्षा परिभाषा पुराने में बदलती है, या वास्तव में पैकेज में आवश्यक गतिविधि प्रदान किए बिना मेनिफेस्ट अनुमति समस्याओं से बचने के किसी भी सुझाव को बदलती है? कोड नमूना:एंड्रॉइड, किसी गतिविधि या सेवा को गतिशील रूप से बदलने के लिए DexClassLoader का उपयोग कैसे करें

com.android.my.path.to.a.loaded.activity /sdcard/mypath/My.apk में निर्दिष्ट शुरू करने का
ClassLoader cl = new DexClassLoader("/sdcard/mypath/My.apk", 
      getFilesDir().getAbsolutePath(), 
      null, 
      MainActivity.class.getClassLoader()); 

    try { 
     Class<?> c = cl.loadClass("com.android.my.path.to.a.loaded.activity"); 
     Intent i = new Intent(getBaseContext(), c); 
     startActivity(i); 
    } 
    catch (Exception e) { 

intead, यह गतिविधि स्थिर परियोजना में लोड की शुरूआत।

+0

मुझे एहसास है कि एंड्रॉइड संपत्तियों को कैसे प्रबंधित करता है इस वजह से यह नहीं किया जा सकता है। यदि आपने किसी अन्य एप्लिकेशन में कक्षा पर स्टार्टएक्टिविटी कहा है तो उसे उस एप्लिकेशन के थ्रेड में लोड करना होगा, न कि एंड्रॉइड के इरादे के लिए यह एक खतरनाक विकल्प होगा। – Tom

उत्तर

13

DexClassLoader के माध्यम से एक गतिविधि शुरू करना बहुत मुश्किल होगा, क्योंकि आपने एपीके इंस्टॉल नहीं किया है, और इसलिए आपके इरादे को संभालने के लिए कुछ भी नहीं है।

आपके पास अपने प्लेटफ़ॉर्म एपीके में एक ही गतिविधि कक्षा होनी चाहिए और इसे AndroidManifest.xml में घोषित करना चाहिए। फिर, आपको वर्तमान क्लासलोडर को अपने वांछित DexClassLoader में बदलना चाहिए। नतीजतन, यह आपकी प्लगइन एपीके शुरू करेगा। (नोट: "प्लेटफ़ॉर्म एपीके" उस ऐप को संदर्भित करता है जो पहले से ही फोन में स्थापित है, जबकि "प्लगइन एपीके" आपके एसडी कार्ड में सहेजी गई एपीके फ़ाइल को संदर्भित करता है।)

प्लेटफ़ॉर्म के एप्लिकेशन को इस तरह कुछ दिखना चाहिए:

public static ClassLoader ORIGINAL_LOADER; 
public static ClassLoader CUSTOM_LOADER = null; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    try { 
     Context mBase = new Smith<Context>(this, "mBase").get(); 

     Object mPackageInfo = new Smith<Object>(mBase, "mPackageInfo") 
       .get(); 
     //get Application classLoader 
     Smith<ClassLoader> sClassLoader = new Smith<ClassLoader>(
       mPackageInfo, "mClassLoader"); 
     ClassLoader mClassLoader = sClassLoader.get(); 
     ORIGINAL_LOADER = mClassLoader; 

     MyClassLoader cl = new MyClassLoader(mClassLoader); 
     //chage current classLoader to MyClassLoader 
     sClassLoader.set(cl); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

class MyClassLoader extends ClassLoader { 
    public MyClassLoader(ClassLoader parent) { 
     super(parent); 
    } 

    @Override 
    public Class<?> loadClass(String className) 
      throws ClassNotFoundException { 
     if (CUSTOM_LOADER != null) { 
      try { 
       Class<?> c = CUSTOM_LOADER.loadClass(className); 
       if (c != null) 
        return c; 
      } catch (ClassNotFoundException e) { 
      } 
     } 
     return super.loadClass(className); 
    } 
} 

अधिक कोड के लिए, आप https://github.com/Rookery/AndroidDynamicLoader

यात्रा कर सकते हैं मैं इस सुविधा को लागू करने के लिए एक और अधिक सुरुचिपूर्ण विधि खोजने के लिए एंड्रॉयड स्रोत कोड पढ़ रहा हूँ। यदि आपके पास कोई विचार है, तो मुझसे संपर्क करने में संकोच न करें।

+0

आपका उत्तर इसके लिए शानदार +1 है। यह मेरा दिन बनाता है। – Krypton

+0

महान जवाब !! लिंक ने मुझे बहुत मदद की। – qiuping345

+1

यदि आप कक्षा स्मिथ को यहां समझाते हैं तो यह बेहतर होगा। –

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