GeoNames и JDOM запрашивают java .rmi.RemoteException после shrinkResources - PullRequest
0 голосов
/ 26 января 2020

Я использую GeoNames Java Client для автозаполнения географических названий в приложении Android: пользователь вводит некоторые символы и появляется список предложений.
Библиотека Также требуется jdom-1.0.jar , чтобы проанализировать XML результаты, полученные GeoNames.

Все работает отлично, за исключением случаев, когда я добавляю shrinkResources true в build.gradle .
В этот момент теряется какой-то критический класс, я не знаю, какой ... Все, что я знаю, это то, что WebService.search() терпит неудачу, но я не могу понять , почему терпит неудачу. Фактически здесь запрашивается java.rmi.RemoteException, но библиотека RMI не поддерживается в Android, поэтому вместо трассировки стека исключений создается ClassNotFoundException.

PlaceFinder. java:

public class PlaceFinder extends AppCompatAutoCompleteTextView {
    ToponymSearchCriteria searchCriteria;
    public PlaceFinder( Context context, AttributeSet attributeSet ) {
        super( context, attributeSet );
        Adapter adapter = new Adapter(context, android.R.layout.simple_spinner_dropdown_item);
        setAdapter(adapter);
        WebService.setUserName("demo");
        searchCriteria = new ToponymSearchCriteria();
        searchCriteria.setMaxRows(3);
    }
    class Adapter extends ArrayAdapter<String> implements Filterable {
        List<String> places;
        Adapter( Context context, int layout ) {
            super( context, layout );
            places = new ArrayList<>();
        }
        @Override
        public int getCount() {
            return places.size();
        }
        @Override
        public String getItem(int index) {
            return places.get(index);
        }
        @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering( CharSequence constraint ) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        searchCriteria.setNameStartsWith(constraint.toString());
                        try {
                            ToponymSearchResult searchResult = WebService.search(searchCriteria); // search() fails
                            places.clear();
                            for( Toponym toponym : searchResult.getToponyms() ) {
                                places.add( toponym.getName() + ", " + toponym.getCountryName() );
                            }
                            filterResults.values = places;
                            filterResults.count = places.size();
                        } catch( Exception e ) {
                            e.printStackTrace(); // The class "java.rmi.RemoteException" is requested but missing
                        }
                    }
                    return filterResults;
                }
                @Override
                protected void publishResults( CharSequence constraint, FilterResults results ) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
            };
        }
    }
}

Роковое исключение (восстановлено):

FATAL EXCEPTION: Filter
    Process: com.example, PID: 32084
    java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/RemoteException;
        at com.example.PlaceFinder$Adapter$1.performFiltering(:57)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.os.HandlerThread.run(HandlerThread.java:61)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "java.rmi.RemoteException" on path: DexPathList[[zip file "/data/app/com.example-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
        at org.jdom.JDOMException.getNestedException(:294)
        at org.jdom.JDOMException.getMessage(:144)
        at java.lang.Throwable.getLocalizedMessage(Throwable.java:188)
        at java.lang.Throwable.toString(Throwable.java:355)
        at java.lang.Throwable.printStackTrace(Throwable.java:315)
        at java.lang.Throwable.printStackTrace(Throwable.java:282)
        at org.jdom.JDOMException.printStackTrace(:216)
        at java.lang.Throwable.printStackTrace(Throwable.java:236)
        at org.jdom.JDOMException.printStackTrace(:189)
        at com.example.PlaceFinder$Adapter$1.performFiltering(:57)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        Suppressed: java.lang.ClassNotFoundException: java.rmi.RemoteException
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                        ... 15 more
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

Как решить эту проблему с двойным слоем?

1 Ответ

0 голосов
/ 23 февраля 2020

Я до сих пор не знаю, какой важный класс или метод удаляется shrinkResources, но решение, которое я нашел после нескольких часов попыток, просто добавляет к proguard-rules.pro правило:

-keep class org.jdom.input.* { *; }

Вот и все.


Тем временем я также обнаружил, что можно обновить JDOM до более новой версии, которая также совместима с GeoNames. Вместо использования jdom-1.0.jar , предоставляемого GeoNames, добавьте к build.gradle зависимости:

implementation 'org.jdom:jdom:1.1.3'

Также в этом случае необходимо вышеуказанное правило ProGuard .

Вместо этого JDOM 2 больше не совместим с GeoNames 1.1.14.

...