2010-03-25 25 views
16

Tôi đang cố gắng thực hiện điều gì đó tương tự với số stackoverflow posting này. Những gì tôi muốn làm là đọc định nghĩa của một hoạt động hoặc dịch vụ từ thẻ SD. Để tránh các vấn đề về quyền hiển thị, tôi tạo phiên bản shell của hoạt động này trong tệp .apk, nhưng cố gắng thay thế phiên bản đó bằng hoạt động cùng tên nằm trên thẻ SD vào thời gian chạy. Thật không may, tôi có thể tải định nghĩa lớp hoạt động từ thẻ SD bằng DexClassLoader, nhưng định nghĩa lớp gốc là định nghĩa được thực hiện. Có cách nào để xác định rằng định nghĩa lớp mới thay thế định dạng cũ hoặc bất kỳ đề xuất nào về tránh các vấn đề về quyền hiển thị mà không thực sự cung cấp hoạt động cần thiết trong gói? Các mẫu mã:Android, cách sử dụng DexClassLoader để thay thế động Hoạt động hoặc Dịch vụ

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 phát động com.android.my.path.to.a.loaded.activity quy định tại /sdcard/mypath/My.apk, nó sẽ khởi động các hoạt động tĩnh nạp vào dự án.

+0

Tôi có cảm giác rằng điều này không thể được thực hiện đơn giản chỉ vì cách Android xử lý nội dung. Nếu bạn gọi startActivity trên một lớp trong một ứng dụng khác, nó sẽ phải tải trong thread của ứng dụng chứ không phải của riêng bạn, và do đó chỉ đơn giản là một thay thế nguy hiểm cho Intent của Android. – Tom

Trả lời

13

Bắt đầu Hoạt động thông qua DexClassLoader sẽ rất phức tạp, bởi vì bạn không cài đặt APK và do đó không có gì để xử lý Ý định của bạn.

Bạn nên có cùng lớp hoạt động trong APK nền tảng của mình và khai báo trong AndroidManifest.xml. Sau đó, bạn nên thay đổi ClassLoader hiện tại thành DexClassLoader bạn muốn. Kết quả là, nó sẽ bắt đầu APK plugin của bạn. (Lưu ý: "APK nền tảng" đề cập đến ứng dụng đã được cài đặt trong điện thoại, trong khi "APK plugin" đề cập đến tệp APK được lưu trong thẻ SD của bạn.)

Ứng dụng của nền tảng sẽ trông giống như sau:

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

Đối với mã hơn, bạn có thể truy cập https://github.com/Rookery/AndroidDynamicLoader

tôi đang đọc mã nguồn Android để tìm ra một phương pháp đơn giản hơn để thực hiện tính năng này. Nếu bạn có bất kỳ ý tưởng, cảm thấy tự do để liên hệ với tôi.

+0

Câu trả lời của bạn là tuyệt vời +1 cho nó. Điều này làm cho ngày của tôi. – Krypton

+0

câu trả lời tuyệt vời !! liên kết đã giúp tôi rất nhiều. – qiuping345

+1

Sẽ tốt hơn nếu bạn giải thích lớp Smith ở đây. –

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