改造|处理“服务器未找到异常”

时间:2014-05-25 19:05:05

标签: android exception retrofit

当尝试从Android应用程序访问RESTful api时,您需要检查两件事:

  1. 启用了用户的wifi(并且已经建立了连接)
  2. 您的应用实际上可以访问服务器。 (我的服务器在本地网络上)
  3. 我设法检查了第一个,但我不知道如何检查最新的。

    这是我的输出

    05-25 15:49:46.929  15485-15999/com.tesis.restapp.restapp E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
        java.lang.RuntimeException: An error occured while executing doInBackground()
                at android.os.AsyncTask$3.done(AsyncTask.java:278)
                at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
                at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
                at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
                at java.util.concurrent.FutureTask.run(FutureTask.java:137)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
                at java.lang.Thread.run(Thread.java:856)
         Caused by: retrofit.RetrofitError: java.net.ConnectException: failed to connect to /192.168.1.25 (port 8080) after 15000ms: isConnected failed: ECONNREFUSED (Connection refused)
                at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:385)
                at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:241)
                at $Proxy0.logIn(Native Method)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:83)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:70)
                at android.os.AsyncTask$2.call(AsyncTask.java:264)
                at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
                at java.util.concurrent.FutureTask.run(FutureTask.java:137)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
                at java.lang.Thread.run(Thread.java:856)
         Caused by: java.net.ConnectException: failed to connect to /192.168.1.25 (port 8080) after 15000ms: isConnected failed: ECONNREFUSED (Connection refused)
                at libcore.io.IoBridge.isConnected(IoBridge.java:220)
                at libcore.io.IoBridge.connectErrno(IoBridge.java:158)
                at libcore.io.IoBridge.connect(IoBridge.java:118)
                at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
                at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
                at java.net.Socket.connect(Socket.java:849)
                at libcore.net.http.HttpConnection.<init>(HttpConnection.java:77)
                at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
                at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:351)
                at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:86)
                at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
                at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308)
                at libcore.net.http.HttpEngine.connect(HttpEngine.java:303)
                at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
                at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
                at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
                at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:188)
                at retrofit.client.UrlConnectionClient.prepareRequest(UrlConnectionClient.java:66)
                at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:37)
                at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:322)
                at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:241)
                at $Proxy0.logIn(Native Method)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:83)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:70)
                at android.os.AsyncTask$2.call(AsyncTask.java:264)
                at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
                at java.util.concurrent.FutureTask.run(FutureTask.java:137)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
                at java.lang.Thread.run(Thread.java:856)
         Caused by: libcore.io.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
                at libcore.io.IoBridge.isConnected(IoBridge.java:207)
                at libcore.io.IoBridge.connectErrno(IoBridge.java:158)
                at libcore.io.IoBridge.connect(IoBridge.java:118)
                at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
                at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
                at java.net.Socket.connect(Socket.java:849)
                at libcore.net.http.HttpConnection.<init>(HttpConnection.java:77)
                at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
                at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:351)
                at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:86)
                at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
                at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308)
                at libcore.net.http.HttpEngine.connect(HttpEngine.java:303)
                at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
                at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
                at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
                at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:188)
                at retrofit.client.UrlConnectionClient.prepareRequest(UrlConnectionClient.java:66)
                at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:37)
                at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:322)
                at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:241)
                at $Proxy0.logIn(Native Method)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:83)
                at com.tesis.restapp.restapp.activities.intro.IntroActivity$SignIn.doInBackground(IntroActivity.java:70)
                at android.os.AsyncTask$2.call(AsyncTask.java:264)
                at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
                at java.util.concurrent.FutureTask.run(FutureTask.java:137)
                at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
                at java.lang.Thread.run(Thread.java:856)
    

    修改

    这是我的界面(目前,它只是尝试登录用户)

    public interface RestAppApiInterface {
    
        @FormUrlEncoded
        @POST(Constants.URL_LOGIN)
        public User logIn(@Field("username") String username, @Field("password") String password);
    
    }
    

    该类返回接口的实例:

    public class ApiClient {
    
        private static final String API_URL = "http://192.168.1.25:8080";
    
        private static RestAppApiInterface sRestAppService;
    
        public static RestAppApiInterface getRestAppApiClient() {
            if (sRestAppService == null) {
                RestAdapter restAdapter = new RestAdapter.Builder()
                        .setEndpoint(API_URL)
                        .build();
                sRestAppService = restAdapter.create(RestAppApiInterface.class);
            }
            return sRestAppService;
        }
    
    }
    

    我在像这样的AsynTask中调用服务

    RestAppApiInterface apiInterface = ApiClient.getRestAppApiClient();
    apiInterface.logIn("username","p@55w0rd");
    

3 个答案:

答案 0 :(得分:3)

[未经测试,从我的头脑中]

看起来你可以在这里干预:

Caused by ... yada yada ...
retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:37)

改造RestAdapter.Builder可让您使用setClient()方法自定义后端访问方式,因此您可以这样:

RestAdapter restAdapter = new RestAdapter.Builder().setClient(
  new Client.Provider() {
    public Client get() {
      return new UrlConnectionClient() {
          @Override
          public Response execute(Request request) {
            // Test avail. / handle exceptions here,
            // call through to the real implementation
            return super.execute();
          }
      };
    }
  });

对于实际的主机可用性逻辑,您可以尝试this recipe

答案 1 :(得分:0)

这是我最终做的事情: 我不知道这是否是一个很好的解决方案,但它确实有效。 (我每次使用界面时都要记得抓住这个例外。

        try {
            user = apiInterface.logIn(params[0], params[1]);
            if (user != null) {
                return Constants.LOG_IN_OK;
            } else {
                return Constants.LOG_IN_INVALID_CREDENTIALS;
            }
        } catch (RetrofitError e) {
            return Constants.LOG_IN_SERVER_NOT_FOUND;
        }

答案 2 :(得分:0)

如果可以,您可以使用异步呼叫。 如果使用异步调用,则可以更好地处理Retrofit中的异常。异步执行要求方法的最后一个参数是Callback。 (http://square.github.io/retrofit/) 所以你的界面看起来像这样:

public interface RestAppApiInterface {

@FormUrlEncoded
@POST(Constants.URL_LOGIN)
void logIn(@Field("username") String username, @Field("password") String password, Callback<User>pCallback);

异常在Callbacks失败方法中处理。而且不需要在单独的线程中执行它。

使用:

apiInterface.logIn("username","p@55w0rd", new Callback<User>() {
                @Override
                public void success(User u, Response response) {
                    //on success
                }

                @Override
                public void failure(RetrofitError error) {
                    //on failure
                }
            });