2017-11-20 106 views
8

"Dinamik" bir Android uygulaması geliştirmeye çalışıyorum. Çalışma zamanında "yerleşik" olan bildirimde listelenen bir etkinliğim olması açısından dinamik.Manifest'te bahsedilmeyen bir Etkinlik nasıl başlatılır?

Bunun benim uygulama başlatmaya çalıştığınızda Ben, ancak, ince Gerekli etkinliği inşa edebilirsiniz başarıyla zamanında bir Android Aktivite örneğini alabilir bir yaklaşım var mı? ...

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]] 

ile başarısız?

Uygulama yoluma "geçici" veya "kabuk" etkinliği ekleyebileceğim bir yol var mı? ve sonra "geçici" etkinliği dinamik durumumla değiştirilsin mi?

GÜNCELLEME

Benim Bildirisi XML benim uygulaması içinde yer alan "Dinamik" olarak adlandırılan hiçbir Etkinlik olduğunda, Ancak bu giriş,

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

içerir. Benim dinamik aktiviteyi inşa etmek ByteBuddy kullanıyorum

: -

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

Bazı kodları ekleyebilir misiniz? Aktivitenizi bir örnek için nasıl başlatıyorsunuz? –

+1

Sizi anlamak için bazı etkinlik kodlarınızı görebilir misiniz? – SahdevRajput74

cevap

5

Dinamik olarak başlatılmış bir Etkinliği çağırmayı ve ByteBuddy'yi kullanarak gerekli düzen içeriğini ayarlamayı başardım.

İşte nasıl

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); 

yöntem heyeti sınıfı

bu hala ben setContent çağrıda sonra super.onCreate(savedInstanceState) çağrısı yapıldığında olarak sorunları vardır istenen sonucu verir (Sanırım) olsa
public class TargetActivity { 

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

.

Mükemmel ByteBuddy kitaplığını kullanmak DEX işlemi ile çalışmaktan çok daha iyi bir yaklaşımdır.

12

Evet Eğer başlatmak CAN böyle (bir kukla tezahür Activity girişi olan varsayarak) bir Activity.
Bu teknikten hoşlanmıyorsanız, Fragments kullanın (bildiride girişlere gerek yoktur).
Alternatif olarak WebView ve JavaScript gibi Apache Cordova et-al (çapraz platform!) Kullanın.
ByteBuddy (kudos da @Rafael Winterhalter, Byte Buddy'nin yazarı) havalı görünüyor, belki de bir öğrenme eğrisi dahil. Neden linked project'u indirip her iki tekniği de denemeyin.

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' 
    } 
} 

ben "Bul" benim çalışma zamanında dinamik olarak sınıf örneğini nasıl: Burada
nasıl includeByteBuddy Android Studio Gradle projesi (build.gradle) var?

DEX dosyalarının Dış yükleme (sınıf bayt kodu) aynı kod

See my answer here ve kaynak kodu ve öğretici için bağlantıları takip (Apache Ant {Eclipse uyumlu, build.xml} ve Android Studio Gradle örnekler build.gradle, Bu projenin sağladığı bazı özel oluşturma adımlarına ihtiyacınız var).
Kod pasajı:

 // 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(); 
     } 

S: Nasıl bir Aktivite eklerim, ben apaçık eklemek olamaz?
A: Kullanım Fragmanlar, manifestlerde girişlere ihtiyaç duymazlar.

İlgili konular