Как надуть фрагмент, включая пользовательское представление, с помощью dexclassloader (InflateException, ClassNotFoundException)

У меня есть Main apk и Sub apk

Sub apk это своего рода библиотека

Main apk имеет sub apk в папке активов

А у Sub apk есть только два класса

Один - это фрагмент класса, а другой - пользовательский класс представления.

и фрагмент XML-файла включает в себя пользовательский вид

------------------------ Главное приложение MainActivity.java ----------------

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    try {
        InputStream inputStream = getAssets().open("sub.apk");
        FileOutputStream fileOutputStream = new FileOutputStream(new File(getExternalFilesDir(null) + "/sub.apk"));
        int length = inputStream.available();
        byte[] buffer = new byte[length];
        inputStream.read(buffer, 0, length);
        fileOutputStream.write(buffer, 0, length);
        inputStream.close();
        fileOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        DexClassLoader dexClassLoader = new DexClassLoader((getExternalFilesDir(null) + "/sub.apk"), "", null, getClass().getClassLoader());
        Class<?> _class;
        Object object = null;
        try {
            _class = dexClassLoader.loadClass("com.test.tnojc.sub.MyFragment");
            object = _class.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        getFragmentManager().beginTransaction().add(R.id.linear_layout, (android.app.Fragment) object, null).commit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

------------------ подпрограмма MyFragment.java --------------

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    Resources resources = null;
    try {
        resources = getActivity().getPackageManager().getResourcesForApplication("com.test.tnojc.sub");
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return inflater.inflate(resources.getLayout(R.layout.fragment_my), container, false);
}

-------------------------- вспомогательное приложение MyView.java ------------------

открытый класс MyView расширяет View {

public MyView(Context context) {
    super(context);
}

public MyView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

}

------------------------ фрагмент приложения sub_my.xml-------------------

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<com.test.tnojc.sub.MyView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="#ffff00" />

</LinearLayout>

Когда фрагмент надувается Main apk, всегда есть inflateException и ClassNotFoundException

06-21 17:47:22.211 8448-8448/com.test.tnojc.main E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.tnojc.main, PID: 8448
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.tnojc.main/com.test.tnojc.main.MainActivity}: android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class com.test.tnojc.sub.MyView
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2955)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
 Caused by: android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class com.test.tnojc.sub.MyView
 Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class com.test.tnojc.sub.MyView
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.test.tnojc.sub.MyView" on path: DexPathList[[zip file "/data/app/com.test.tnojc.main-frRAX-uSidnbPYWOpcDLTg==/base.apk"],nativeLibraryDirectories=[/data/app/com.test.tnojc.main-frRAX-uSidnbPYWOpcDLTg==/lib/arm64, /system/lib64, /vendor/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    at android.view.LayoutInflater.createView(LayoutInflater.java:606)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
    at com.test.tnojc.sub.MyFragment.onCreateView(MyFragment.java:23)
    at android.app.Fragment.performCreateView(Fragment.java:2611)
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1276)
    at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2421)
    at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2200)
    at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2154)
    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2055)
    at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3050)
    at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2997)
    at android.app.FragmentController.dispatchActivityCreated(FragmentController.java:179)
    at android.app.Activity.performCreateCommon(Activity.java:7168)
    at android.app.Activity.performCreate(Activity.java:7176)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2908)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

если я добавляю настраиваемое представление динамически в onCraeteView или если Main и sub имеют настраиваемое представление в качестве общей библиотеки, это работает нормально, но это не является обязательным требованием.

это невозможно? если нет, как я могу надуть?

это образец apk

https://github.com/woosuk0410/main

https://github.com/woosuk0410/sub

Спасибо

0 ответов

Другие вопросы по тегам