2013-11-02 14 views
5

Я пытаюсь выяснить Reflection с этим Android класс:Android Reflection Method Ошибка

Class<?> c = Class.forName("com.android.internal.widget.LockPatternUtils"); 
Method method = c.getDeclaredMethod("getKeyguardStoredPasswordQuality"); 
method.setAccessible(true); 
Object object = method.invoke(c); // Error with this line 
result = object.toString()); 

Метод getKeyguardStoredPasswordQuality объявлен как (без параметров):

public int getKeyguardStoredPasswordQuality() { 
    // codes here 
} 

Ошибка у меня есть :

Exception: java.lang.IllegalArgumentException: expected receiver of type com.android.internal.widget.LockPatternUtils, but got java.lang.Class<com.android.internal.widget.LockPatternUtils> 

Как объявить com.android.internal.widget.LockPatternUtils в качестве приемника?

ответ

10

Вы передаете class на номер #invoke() вместо экземпляра LockPatternUtils.

Вы можете создать экземпляр, используя #newInstance().

+0

Можете ли вы расширить свой ответ так, как это сделать? Object clazz = c.newInstance(); 'затем передать clazz в' Object object = method.invoke (clazz); 'будет работать, только если конструктор ссылочного класса пусто. Что вы делаете в случае, когда конструктор класса определяется как 'public LockPatternUtils (контекст контекста) {..}'? – ChuongPham

+0

Я буду отмечать ваш ответ как правильный, показывая мне doco на метод 'newInstance'. Спасибо друг. – ChuongPham

+0

@ChuongPham: Конечно, есть некоторые ограничения, но они задокументированы в API, к которому я привязываюсь. – Keppil

1

Ничего, я понял это. Я скорректировал приведенные ниже коды на основе этого tutorial.

В случае, если кто заинтересован в решении, вот оно:

Class<?> c = Class.forName("com.android.internal.widget.LockPatternUtils"); 
Constructor<?>[] constructors = c.getDeclaredConstructors(); 
Constructor<?> constructor = null; 
for (int i = 0; i < constructors.length; i++) { 
    constructor = constructors[i]; 
    if (constructor.getGenericParameterTypes().length == 0) 
     break; 
} 
constructor.setAccessible(true); 
Object clazz = constructor.newInstance(context, true); 
Method method = clazz.getClass().getDeclaredMethod("getKeyguardStoredPasswordQuality"); 
Object object = method.invoke(clazz); 
result = object.toString(); 

выше решение требует, чтобы общественность конструктор LockPatternUtils.java класса должен быть определен как:

public LockPatternUtils(Context context) {...} 

Если конструктор изменения в будущем (после 2013 года), решение необходимо будет изменить.

Примечание: вышеизложенное упражнение для меня, чтобы понять использование отражения. Однако использование Reflection в приложениях для Android должно использоваться экономно и когда это абсолютно необходимо.

+0

Мне пришлось слегка изменить код, чтобы запустить его на моем устройстве Andorid 5.1.1 и получить правильный конструктор используемый. Пришлось бы изменить if (constructor.getGenericParameterTypes(). Length == 0) – FunkSoulBrother

Смежные вопросы