Как надуть фрагмент, включая пользовательское представление, с помощью 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
Спасибо