2017-11-20 17 views
8

Tôi đang cố phát triển ứng dụng Android "Động".Cách bắt đầu một Hoạt động không tồn tại được đề cập trong Tệp kê khai?

Động theo nghĩa là tôi có hoạt động được liệt kê trong tệp kê khai được "tạo" khi chạy.

tôi có thể xây dựng các hoạt động cần thiết tốt, tuy nhiên, khi tôi cố gắng để bắt đầu nó ứng dụng của tôi không thành công với ...

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

Có một cách tiếp cận tôi có thể làm để nhanh chóng thành công Hoạt động Android trong thời gian chạy?

Có cách nào tôi có thể thêm hoạt động "tạm thời" hoặc "vỏ" vào đường dẫn ứng dụng của mình không? và sau đó thay thế hoạt động "tạm thời" bằng cá thể động của tôi?

CẬP NHẬT

XML Manifest của tôi có chứa cụm từ này

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

Tuy nhiên, không có Hoạt động gọi là "Dynamic" chứa trong ứng dụng của tôi.

Tôi đang sử dụng ByteBuddy để xây dựng hoạt động năng động của tôi: -

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

bạn có thể thêm một số mã không?! làm thế nào để bạn bắt đầu hoạt động của bạn cho một ví dụ –

+1

Bạn có thể nhìn thấy tôi một số mã hoạt động của bạn để hiểu sự quetion? – SahdevRajput74

Trả lời

5

Tôi đã quản lý để gọi một Hoạt động được khởi động động và đặt nội dung bố cục được yêu cầu bằng ByteBuddy.

Heres cách

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

Đoàn Phương pháp lớp

public class TargetActivity { 

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

Mặc dù điều này mang lại kết quả mong muốn nó vẫn có các vấn đề như cuộc gọi super.onCreate(savedInstanceState) được thực hiện sau khi tôi đã gọi setContent (tôi nghĩ) .

Sử dụng thư viện ByteBuddy xuất sắc là cách tiếp cận IMHO tốt hơn nhiều so với làm việc với thao tác DEX.

12

bạn THỂ bắt đầu như một Activity (giả sử bạn có một hình nộm manifest Activity nhập ).
Nếu bạn không thích kỹ thuật này, hãy sử dụng Fragments (chúng không cần mục nhập trong tệp kê khai).
Hoặc sử dụng WebViewJavaScript như Apache Cordova et-al (nền tảng chéo quá!).
ByteBuddy (kudo quá @Rafael Winterhalter tác giả của Byte Buddy) trông thật tuyệt, có thể là một đường cong học tập liên quan. Tại sao không tải xuống linked project và thử cả hai kỹ thuật.
Dưới đây là làm thế nào để includeByteBuddy trong dự án Gradle Android Studio của bạn (build.gradle):

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

làm thế nào tôi có thể "tìm" của tôi tự động khởi tạo lớp trong thời gian chạy?

tải bên ngoài các tập tin DEX (lớp mã byte)

See my answer here và làm theo các liên kết cho mã nguồn và hướng dẫn (Apache Ant {Eclipse tương thích, build.xml} và Android Studio Gradle ví dụ build.gradle của cùng mã, bạn cần một số bước xây dựng tùy chỉnh mà các dự án này cung cấp).
Đoạn mã:

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

Q: Làm thế nào để thêm một hoạt động, tôi không thể thêm nó vào manifest?
A: Sử dụng Các mảnh vỡ, chúng không cần mục nhập trong tệp kê khai.

Các vấn đề liên quan