Джерси-клиент на Android – NullPointerException

Я пытаюсь создать простой клиент Android для веб-службы, которую я создал, но что-то не так во время выполнения.

Вот клиент:

public class MyClient extends AsyncTask<EditText, Integer, String> { private EditText text; protected String doInBackground(EditText... strings) { RuntimeDelegate .setInstance(new com.sun.ws.rs.ext.RuntimeDelegateImpl()); WebResource wbr; Client client = Client.create(); wbr = client .resource("http://my.ip:8080/MazeService/rest/service/hello"); String result = wbr.queryParam("number", "10") .accept(MediaType.APPLICATION_JSON).get(String.class); text = strings[0]; return result; } protected void onProgressUpdate(Integer... progress) { // setProgressPercent(progress[0]); } protected void onPostExecute(String result) { if (result != null) this.text.setText(result); else Log.d("MyApp", "No Result"); } 

}

И Служба:

 @Path("/service") public class AndroidService { @GET @Produces(MediaType.APPLICATION_JSON ) @Path("/hello") public String getJSON(@QueryParam("number") String nr) { String s = "Hi there! The number is: "+nr; return s; } } 

Я получаю этот стек в LogCat:

 02-18 16:26:06.446: E/AndroidRuntime(1381): FATAL EXCEPTION: AsyncTask #1 02-18 16:26:06.446: E/AndroidRuntime(1381): java.lang.RuntimeException: An error occured while executing doInBackground() 02-18 16:26:06.446: E/AndroidRuntime(1381): at android.os.AsyncTask$3.done(AsyncTask.java:278) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 02-18 16:26:06.446: E/AndroidRuntime(1381): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.lang.Thread.run(Thread.java:856) 02-18 16:26:06.446: E/AndroidRuntime(1381): Caused by: java.lang.NullPointerException 02-18 16:26:06.446: E/AndroidRuntime(1381): at javax.ws.rs.core.MediaType.valueOf(MediaType.java:119) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.ClientResponse.getType(ClientResponse.java:615) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:532) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:506) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.WebResource.handle(WebResource.java:674) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:503) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.maze.client.MyClient.doInBackground(MyClient.java:25) 02-18 16:26:06.446: E/AndroidRuntime(1381): at com.maze.client.MyClient.doInBackground(MyClient.java:1) 02-18 16:26:06.446: E/AndroidRuntime(1381): at android.os.AsyncTask$2.call(AsyncTask.java:264) 02-18 16:26:06.446: E/AndroidRuntime(1381): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 02-18 16:26:06.446: E/AndroidRuntime(1381): ... 5 more 

Я не понимаю, в чем проблема, так как аналогичный клиент работает на ПК. Нет проблем с IP-адресом, так как я могу получить доступ к серверу с Android VirtualDevice.

Версия Android 4.0.3 API версии 15. Для клиента я использовал Jersey 1.11.

РЕДАКТИРОВАТЬ

Я также попытался удалить все это с помощью EditText, так как кто-то сказал мне, что он не используется так, как должно быть. Тем не менее, у меня такая же ошибка. Я просто не понимаю, что я делаю неправильно. Если я покажу любую другую дополнительную информацию, сообщите мне. Кроме того, ЛЮБАЯ идея хороша. Я новичок в Android, и я, возможно, допустил некоторые глупые ошибки.

Solutions Collecting From Web of "Джерси-клиент на Android – NullPointerException"

Предложение Павла верное. Я немного глубже в этом вопросе и нашел причину.

Инструмент упаковки Android apk (класс APKBuilder из sdklib.jar) игнорирует разные папки, пока он создает пакет ( источник ). Одна из этих папок – META-INF – независимо от того, находится ли она в прикрепленной библиотеке или в исходной папке проекта.

Обходной путь для версии 1.8 (и, возможно, другой, но я не тестировал его) в Джерси, должен предоставить пользовательские (по умолчанию один ищет META-INF / services / который отсутствует в android apk) для ServiceFinder $ ServiceIteratorProvider, который имеет Жесткие кодированные имена классов поставщика. Я основывал свою реализацию на этой реализации, предложенной Лукасом:

 import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import android.util.Log; import com.sun.jersey.spi.service.ServiceFinder.ServiceIteratorProvider; public class AndroidServiceIteratorProvider<T> extends ServiceIteratorProvider<T> { private static final String TAG = AndroidServiceIteratorProvider.class.getSimpleName(); private static final String MESSAGE = "Unable to load provider"; private static final HashMap<String, String[]> SERVICES = new HashMap<String, String[]>(); private static final String[] com_sun_jersey_spi_HeaderDelegateProvider = { "com.sun.jersey.core.impl.provider.header.MediaTypeProvider", "com.sun.jersey.core.impl.provider.header.StringProvider" }; private static final String[] com_sun_jersey_spi_inject_InjectableProvider = { }; private static final String[] javax_ws_rs_ext_MessageBodyReader = { "com.sun.jersey.core.impl.provider.entity.StringProvider", "com.sun.jersey.core.impl.provider.entity.ReaderProvider" }; private static final String[] javax_ws_rs_ext_MessageBodyWriter = { "com.sun.jersey.core.impl.provider.entity.StringProvider", "com.sun.jersey.core.impl.provider.entity.ReaderProvider" }; static { SERVICES.put("com.sun.jersey.spi.HeaderDelegateProvider", com_sun_jersey_spi_HeaderDelegateProvider); SERVICES.put("com.sun.jersey.spi.inject.InjectableProvider", com_sun_jersey_spi_inject_InjectableProvider); SERVICES.put("javax.ws.rs.ext.MessageBodyReader", javax_ws_rs_ext_MessageBodyReader); SERVICES.put("javax.ws.rs.ext.MessageBodyWriter", javax_ws_rs_ext_MessageBodyWriter); SERVICES.put("jersey-client-components", new String[]{}); SERVICES.put("com.sun.jersey.client.proxy.ViewProxyProvider", new String[]{}); } @SuppressWarnings("unchecked") @Override public Iterator<Class<T>> createClassIterator(Class<T> service, String serviceName, ClassLoader loader, boolean ignoreOnClassNotFound) { String[] classesNames = SERVICES.get(serviceName); int length = classesNames.length; ArrayList<Class<T>> classes = new ArrayList<Class<T>>(length); for (int i = 0; i < length; i++) { try { classes.add((Class<T>) Class.forName(classesNames[i])); } catch (ClassNotFoundException e) { Log.v(TAG, MESSAGE,e); } } return classes.iterator(); } @Override public Iterator<T> createIterator(Class<T> service, String serviceName, ClassLoader loader, boolean ignoreOnClassNotFound) { String[] classesNames = SERVICES.get(serviceName); int length = classesNames.length; ArrayList<T> classes = new ArrayList<T>(length); for (int i = 0; i &lt; length; i++) { try { classes.add(service.cast(Class.forName(classesNames[i]) .newInstance())); } catch (IllegalAccessException e) { Log.v(TAG, MESSAGE,e); } catch (InstantiationException e) { Log.v(TAG, MESSAGE,e); } catch (ClassNotFoundException e) { Log.v(TAG, MESSAGE,e); } } return classes.iterator(); } } 

Я удалил большинство классов, так как не использовал их, а также они вызывали ошибки проверки на dalvik vm …

ПРИМЕЧАНИЕ. Это означает, что с этой реализацией вы можете использовать только подмножество заголовков / типов, поддерживаемых Джерси (мне нужна только строка). Для поддержки других типов вам необходимо добавить поставщиков, находящихся в папке META-INF / services jersey-client.jar (или из реализации Lucas), и проверить, не вызывают ли они ошибки проверки на Android.

Вышеприведенный код следует использовать следующим образом:

 ServiceFinder.setIteratorProvider(new AndroidServiceIteratorProvider()); Client client = Client.create(); 

РЕДАКТИРОВАТЬ:

Похоже, проблема была исправлена в Android-maven-plugin.

Mosa … @ gmail.com написал:

Запрос тяги с исправлением был объединен с мастером и будет выпущен с 3.2.1:

Следуя коду:

ком / ВС / Джерси / API / клиент / ClientResponse.getType ()

 613 public MediaType getType() { 614 String ct = getHeaders().getFirst("Content-Type"); 615 return (ct != null) ? MediaType.valueOf(ct) : null; 616 } 

Я бы проверял, что делегат, используемый MediaType, не является null .

javax / WS / RS / ядро / MediaType.valueOf (java.lang.String)

 118 public static MediaType valueOf(String type) throws IllegalArgumentException { 119 return delegate.fromString(type); 120 } 

Похоже, что delegate имеет значение null для одного клиента (Android), а не для другого клиента.

Взгляните на это, чтобы понять, как инициализируется делегат. Это может помочь в ваших расследованиях.

javax / WS / RS / внутр / RuntimeDelegate.java