2017-11-20 10 views
8

मैं एक "गतिशील" एंड्रॉइड एप्लिकेशन विकसित करने का प्रयास कर रहा हूं।मैनिफेस्ट में उल्लिखित एक गैर मौजूद गतिविधि कैसे शुरू करें?

इस अर्थ में गतिशील है कि मेरे पास मैनिफेस्ट में सूचीबद्ध गतिविधि है जो रनटाइम पर "निर्मित" है।

मैं आवश्यक गतिविधि ठीक निर्माण कर सकते हैं, तथापि, जब मैं इसे अपने आवेदन शुरू करने का प्रयास के साथ विफल हो ...

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.research.ps/com.research.Dynamic}: java.lang.ClassNotFoundException: 
Didn't find class "com.research.Dynamic" on path: DexPathList[[zip file "/data/app/com.research.ps-1/base.apk"],nativeLibraryDirectories=[/data/app/com.research.ps-1/lib/arm, 
/data/app/com.research.ps-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]] 

वहाँ एक दृष्टिकोण मैं सफलतापूर्वक कार्यावधि में एक Android गतिविधि का दृष्टांत के लिए ले सकता है?

क्या कोई तरीका है कि मैं अपने आवेदन पथ पर "अस्थायी" या "खोल" गतिविधि जोड़ सकता हूं? और फिर मेरे गतिशील उदाहरण के साथ "अस्थायी" गतिविधि को प्रतिस्थापित करें?

अद्यतन

मेरे मेनीफ़ेस्ट XML इस प्रविष्टि

<activity 
    android:name=".Dynamic" 
    android:label="@string/title_activity_dynamic" 
    android:theme="@style/AppTheme.NoActionBar" /> 

शामिल हालांकि, कोई गतिविधि "गतिशील" अपने आवेदन के भीतर निहित कहा जाता है।

मैं ByteBuddy उपयोग कर रहा हूँ मेरी गतिशील गतिविधि का निर्माण करने की: -

final Class<? extends android.support.v7.app.AppCompatActivity> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V8) 
      .subclass(android.support.v7.app.AppCompatActivity.class, IMITATE_SUPER_CLASS) 
      .name("com.research.Dynamic") 
      .make() 
      .load(getClass().getClassLoader(), new AndroidClassLoadingStrategy.Wrapping(this.getDir("dexgen", Context.MODE_PRIVATE))) 
      .getLoaded(); 

final Intent intent = new Intent(this, dynamicType); 
startActivity(intent); 
+4

क्या आप कुछ कोड जोड़ सकते हैं? उदाहरण के लिए आप अपनी गतिविधि कैसे शुरू कर रहे हैं –

+1

क्या आप मुझे quetion समझने के लिए अपनी कुछ गतिविधि की गतिविधि देख सकते हैं? – SahdevRajput74

उत्तर

5

मैंने गतिशील रूप से तत्काल गतिविधि को कॉल करने और बाइटबड्डी का उपयोग करके आवश्यक लेआउट सामग्री सेट करने में कामयाब रहा है।

यहाँ है कि कैसे

final DynamicType.Unloaded<? extends AppCompatActivity> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V8) 
     .subclass(AppCompatActivity.class) 
     .name(CLASS_NAME) 
     .method(named("onCreate").and(takesArguments(1))) 
     .intercept(MethodDelegation.to(TargetActivity.class).andThen(SuperMethodCall.INSTANCE)) 
     .make(); 

final Class<? extends AppCompatActivity> dynamicTypeClass = dynamicType.load(getClassLoader(), new AndroidClassLoadingStrategy.Injecting(this.getDir("dexgen", Context.MODE_PRIVATE))).getLoaded(); 

final Intent intent = new Intent(this, dynamicTypeClass); 
startActivity(intent); 

विधि प्रतिनिधिमंडल वर्ग

public class TargetActivity { 

    public static void intercept(Bundle savedInstanceState, @This AppCompatActivity thiz) { 
     thiz.setContentView(R.layout.activity_fourth); 
    } 
} 

हालांकि इस वांछित परिणाम यह अभी भी मुद्दों के रूप में super.onCreate(savedInstanceState) कॉल के बाद मैं setContent बुलाया जाता है देता है (मुझे लगता है कि) ।

उत्कृष्ट बाइटबड्डी लाइब्रेरी का उपयोग डीईएक्स मैनिपुलेशन के साथ काम करने से आईएमएचओ का एक बेहतर तरीका है।

12

हाँ आप शुरू कर सकते हैं इस तरह के एक Activity (यह मानते हुए कि आप एक डमी प्रकट Activity प्रविष्टि है)।
यदि आपको इस तकनीक को पसंद नहीं है, तो Fragments (उन्हें मेनिफेस्ट में प्रविष्टियों की आवश्यकता नहीं है) का उपयोग करें।
वैकल्पिक रूप से WebView और JavaScript जैसे Apache Cordova एट-अल (क्रॉस प्लेटफ़ॉर्म भी!) का उपयोग करें।
ByteBuddy (बाइट बडी के @ राफेल विंटरहल्टर लेखक भी कुडोस) शांत दिखते हैं, शायद एक सीखने की वक्र शामिल है। linked project क्यों डाउनलोड न करें और दोनों तकनीकों को आजमाएं।

android { 
    compileSdkVersion 25 
    buildToolsVersion '25' 
    dependencies { 
     compile 'com.android.support:appcompat-v7:25' 
     compile 'net.bytebuddy:byte-buddy:1.7.9' 
     compile 'net.bytebuddy:byte-buddy-android:1.7.9' 
    } 
} 

कैसे मैं "लगता है" कर सकते हैं अपने गतिशील रूप क्रम में वर्ग का दृष्टांत:
यहाँ कैसे करने के लिए includeByteBuddy अपने Android स्टूडियो Gradle परियोजना (build.gradle) में है?

DEX फ़ाइलों के बाहरी लोड हो रहा है (कक्षा बाइट कोड) एक ही कोड के

See my answer here और स्रोत कोड और ट्यूटोरियल के लिए लिंक का अनुसरण करें (अपाचे चींटी {Eclipse संगत, build.xml} और एंड्रॉयड स्टूडियो Gradle उदाहरण build.gradle, आपको कुछ कस्टम बिल्ड चरणों की आवश्यकता है जो इन परियोजनाओं को प्रदान करते हैं)।
कोड स्निपेट:

 // Internal storage where the DexClassLoader writes the optimized dex file to. 
     final File optimizedDexOutputPath = getDir(SECONDARY_DEX_INTERNAL_DIR, Context.MODE_PRIVATE); 

     // Initialize the class loader with the secondary dex file. 
     DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(), 
               optimizedDexOutputPath.getAbsolutePath(), 
               null, 
               getClassLoader()); 
     Class libProviderClazz = null;//variable libProviderClazz of type Class 

     try { 
      // Load the library class from the class loader. 
      libProviderClazz = cl.loadClass(PROVIDER_CLASS); 

      // Cast the return object to the library interface so that the 
      // caller can directly invoke methods in the interface. 

      // Alternatively, the caller can invoke methods through reflection, 
      // which is more verbose and slow. 
      LibraryInterface lib = (LibraryInterface) libProviderClazz.newInstance(); 

     } 
     catch (Exception exception) 
     { 
      // Handle exception gracefully here. 
      exception.printStackTrace(); 
     } 

प्रश्न: मैं एक गतिविधि को जोड़ने करते हैं, मैं इसे प्रकट करने के लिए जोड़ नहीं कर सकते?
ए: टुकड़ों का उपयोग करें, उन्हें मैनिफेस्ट में प्रविष्टियों की आवश्यकता नहीं है।

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