Я столкнулся с сложной проблемой при работе с приложениями Android - загрузкой класса из .zip или .dex в приложение. Я не могу решить проблему Classloader
. Пожалуйста, помогите мне, спасибо. Я пытаюсь загрузить класс из zip, но класс (например, провайдер Android или что-то в этом роде) должен быть загружен при запуске программы. Итак, я должен оставить файл в своих программах, например, с пакетами com.example.androidprovider
и файл TestProvider.java.Classloader, используемый в приложении для Android
package com.example.androidprovider;
public class TestProvider extends ContentProvider {
public static final String AUTHORY="com.lcz.tst";
DBHelper dbHelp;
SQLiteDatabase sq;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
sq.delete(DBHelper.TABLE, selection, selectionArgs);
return 0;
}
...
@Override
public boolean onCreate() {
dbHelp=new DBHelper(getContext(),null, null, 1);
sq=dbHelp.getWritableDatabase();
Log.i("TestProvider", "text");
return true;
}
}
В моем файле .zip, я упаковать класс с пакет com.example.androidprovider
и именем класса TestProvider
. (Два класса отличается, а второй класс является классом мне действительно нужно.)
package com.example.androidprovider;
public class TestProvider extends ContentProvider {
public static final String AUTHORY="com.lcz.tst";
DBHelper dbHelp;
SQLiteDatabase sq;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
sq.delete(DBHelper.TABLE, selection, selectionArgs);
return 0;
}
...
@Override
public boolean onCreate() {
dbHelp=new DBHelper(getContext(),null, null, 1);
sq=dbHelp.getWritableDatabase();
Log.i("Original Provider", "This is the original!!!");
return true;
}
}
Теперь это мой код загрузчика.
public void loadDex(String strActivity){
final File optimizedDexOutputPath = oriActivity.getDir("outdex", Context.MODE_PRIVATE);
// Initialize the class loader with the secondary dex file.
//dexInternalStoragePath.getAbsolutePath() is the path there the .zip is,
DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),
libPath,
this.getClass().getClassLoader());
Class<?> cls;
try {
cls = cl.loadClass("com.example.androidprovider.TestProvider");
Object instant = cls.newInstance();
Method method = cls.getDeclaredMethod("onCreate");
method.invoke(instant);
}catch (Exception e) {
e.printStackTrace();
}
Я проверил LogCat, но журнал всегда показывает "TestProvider текст". Таким образом, это означает, что мой код загрузчика не удался. Я думаю, причина в том, что мое приложение инициализирует класс com.example.androidprovider.TestProvider
(первый кусок кода), а загрузчик загружает другой класс с тем же пакетом и именем, поэтому второй класс не может быть успешно загружен.
Но мне действительно нужно загрузить второй класс. Могу ли я использовать некоторые способы запуска второго класса? Спасибо ...
Спасибо. Возможно, это может работать хорошо. В моем примере первый TestProviderProxy должен измениться как можно меньше. Это всего лишь кусок тестового кода, на самом деле, возможно, я не могу получить исходный код первого TestProviderProxy. Но он должен быть инициализирован из-за файла AndroidMenifest.xml в приложении Android Appliciton. Поэтому я должен написать альтернативный TestProviderProxy (второй), чтобы загрузить фактический TestProviderProxy (первый). Я не думал переписывать свой альтернативный TestProviderProxy, я попробую. Большое спасибо! –
Кстати, я знаю, что отражение действительно мощное. так, могу ли я иметь некоторые способы охватить первый класс вторым классом во время выполнения? Я думаю, возможно, это может сработать, изменив некоторые данные системного уровня с отражением, но я не знал, какие данные следует изменить. Благодарю. –
Я все еще не уверен, чего вы пытаетесь достичь ... но я надеюсь, что это вам помогло. Да отражения «мощные», но сама система работает на собственном коде, а ваше приложение работает в SandBox. Вы не можете просто изменить «некоторые данные», чтобы сделать всю работу. – cwin