gpt4 book ai didi

android - Android 上的 Jersey 客户端 - NullPointerException

转载 作者:IT老高 更新时间:2023-10-28 23:32:58 27 4
gpt4 key购买 nike

我正在尝试为我构建的 Web 服务创建一个简单的 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

我不明白问题出在哪里,因为类似的客户端可以在 PC 上运行。 IP地址没有问题,因为我可以从Android VirtualDevice访问服务器。

Android 版本是 4.0.3 API 版本 15。对于客户端我使用 Jersey 1.11。

编辑

我还尝试使用 EditText 删除整个内容,因为有人告诉我它没有按应有的方式使用。不过,我得到了同样的错误。我根本无法理解我做错了什么。如果我应该显示任何其他附加信息,请告诉我。此外,任何想法都是好的。我是 Android 新手,可能会犯一些愚蠢的错误。

最佳答案

保罗的建议是正确的。我对该主题进行了更深入的研究并找到了原因。

Android apk 打包工具(来自 sdklib.jar 的 APKBuilder 类)在创建包时会忽略不同的文件夹( source )。这些文件夹之一是 META-INF - 无论它是在附加的库中还是在项目的源文件夹中。

Jersey 版本 1.8(可能还有其他版本,但我没有测试过)的解决方法是为 ServiceFinder$ServiceIteratorProvider 提供自定义(默认查找 META-INF/services/,这在 android apk 中不存在)实现具有硬编码的提供程序类名称。我的实现基于 Lucas 提出的 this 实现:

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 上的验证错误......

注意:这意味着通过此实现,您只能使用 Jersey 支持的 header /类型的子集(我只需要字符串)。要支持其他类型,您必须添加位于 jersey-client.jar 的 META-INF/services 文件夹(或来自 Lucas 的实现)的提供程序,并检查它们是否不会导致 Android 上的验证错误。

上面的代码应该使用如下:

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

编辑:

看来问题出在android-maven-plugin中的fixed

mosa...@gmail.com 写道:

The pull request with the fix was merged into master and will be released with 3.2.1:

关于android - Android 上的 Jersey 客户端 - NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9342506/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com