Я собираюсь полностью отказаться от запутывания! У меня есть основное приложение, которое использует несколько apks в качестве плагинов, запускающих свои сервисы и импортирующих их фрагменты в MainActivity. Это немного сложно, но может быть сделано со знанием всех имен классов и рефлексии.
Теперь идет обуфкация. Я знал, что мне нужно защитить все классы фрагментов, чтобы иметь возможность доступа к их классам через строковые константы и загрузчик классов.
Давайте начнем с StartupFragment, который является внутренним в основном приложении. Фрагмент моего proguard-rules.pro:
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable,InnerClasses,Signature,*Annotation*
-keeppackagenames com.my.company.**
-keep public class * extends com.my.company.plugin.MyFragmentExtension{
public <methods>;
public static <fields>;
}
Похоже, что keeppackagenames и the keep расширяют работу: я проверил apk с помощью: apk-> unzip-> dex2jar classes.dex -> jd-gui dex2jar.jar И StartupFragment находится прямо внутри полностью именованного пакета.
Теперь я написал небольшой тест:
try
{
Fragment direct = new StartupFragment(); //always works OK!
Log.d(TAG,TAG + " CLTEST: StartupFragment created directly");
Fragment reflect = null;
//Classloader taken right from the class I want to load via reflection
ClassLoader cl = StartupFragment.class.getClassLoader();
//reflection load always fails ClassNotFoundException
Class classss= cl.loadClass(StartupFragment.class.toString());
Log.d(TAG, TAG + " CLTEST: "+StartupFragment.class.toString() +".class loaded via reflection via OWN classloader");
reflect = (Fragment)classss.newInstance();
}catch (ClassNotFoundException e)
{
Log.e(TAG,TAG + " CLTEST StartupFragment classloader has failed to find " + StartupFragment.class.getName());
e.printStackTrace();
}catch (Throwable e)
{
Log.e(TAG,TAG + " CLTEST StartupFragment classloader has failed: ",e);
e.printStackTrace();
}
Вопрос теперь таков: почему загрузчик классов мог взятьиз самого класса он должен загрузить сбой, даже если класс не был переименован (и даже имя взято непосредственно из класса) ??
Дополнительная информация:
- безobfuscation (minifyEnabled false) все отлично работает с отражением
- com.my.company.plugin.MyFragmentExtension находится в пакете aar, но это не должно быть проблемой, поскольку класс сохранен и не переименован?!
- все внутренние классы StartupFragment (как и все, например, onClickListeners) были переименованы и удалены из исходного класса (см. Dex2jar.jar)