Java Reflection в Android Studio не может найти публичный статический метод для вызова - PullRequest
1 голос
/ 02 апреля 2019

Код отражения Java в моем приложении Android вызывает открытый статический метод в пакете B из пакета A.

Недавно, после некоторых обновлений Gradle, я не могу вызвать тот же метод. Моя реализация терпит неудачу с исключением NoSuchMethodFound. Как я могу получить реализацию, чтобы можно было найти этот метод?

Я попытался распечатать все доступные методы из класса. Результатом являются все публичные нестатические методы. Нет доступных статических методов для вызова. Метод, который я хочу вызвать, является статическим методом «getInstance», который инициализирует класс и возвращает единичный экземпляр.

Телефонный код:

implementationClass = Class.forName(CLIENT_CLASS_NAME, false, ClientProvider.class.getClassLoader());
final Method method = implementationClass.getMethod("getInstance", (Class[]) null);
result = method.invoke(null, (Object[]) null);

Вызываемый код:

/**
* Public static method to be reflected.
*/
public static ClientImpl getInstance() {
    return ClientImplHolder.INSTANCE;
}

/**
 * Private class used to hold the lazily initialized singleton instance.
 */
private static class ClientImplHolder {
    private static final ClientImpl INSTANCE = new ClientImpl();
}

При попытке getMethod я получаю исключение NoSuchMethodException.

Не уверен, что я здесь делаю неправильно, благодарю за любую помощь. Спасибо!

Ответы [ 4 ]

0 голосов
/ 05 апреля 2019

Оказывается, Proguard удалял метод из сборки, так как он не использовался в другом месте.Добавлено исключение для класса, и проблема исчезла.

0 голосов
/ 02 апреля 2019

Попробуйте заменить его, возможно, это проблема с параметрами.

    final Method method = implementationClass.getMethod("getInstance");
    result = method.invoke(null);
0 голосов
/ 02 апреля 2019

Начиная с Android 9 (уровень API 28), платформа ограничивает интерфейсы, не относящиеся к SDK, которые может использовать ваше приложение. Эти ограничения применяются всякий раз, когда приложение ссылается на интерфейс не-SDK или пытается получить его дескриптор, используя отражение.

0 голосов
/ 02 апреля 2019

Если я правильно понял, вы использовали API отражения неправильно

, просто попробуйте это.

public class Test {

    public static void main(String[] args) {
        try {
            ClientImpl client = (ClientImpl) Class.forName(ClientImpl.class.getCanonicalName())
                    .getMethod("getInstance")
                    .invoke(null);

            System.out.println(client.toString() + " with some -> " + client.getSome());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

/**
 * Public static method to be reflected.
 */

class ClientImpl {

    private final int some;

    public int getSome() {
        return some;
    }

    private ClientImpl(int some) {
        this.some = some;
    }

    public static ClientImpl getInstance() {
        return ClientImplHolder.INSTANCE;
    }

    /**
     * Private class used to hold the lazily initialized singleton instance.
     */
    private static class ClientImplHolder {
        private static final ClientImpl INSTANCE = new ClientImpl(123);
    }
}

, и он будет правильно отображать результат

ClientImpl@<hashcode> with some -> 123

Когда вы используетестатические методы в API отражений, вам не нужно явно вызывать его ClassLoader, вы должны поместить его canonicalName в аргумент, затем вы можете вызвать его методы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...