2013-06-27 38 views
1

我道歉,如果这是一个重复(链接吗?)如何在使用Scribe进行OAuth请求时解决java.io.EOFException?

我收到运行时错误这样的:

E/AndroidRuntime(26112): FATAL EXCEPTION: AsyncTask #3 

E/AndroidRuntime(26112): java.lang.RuntimeException: An error occured while executing doInBackground() 

E/AndroidRuntime(26112):  
at android.os.AsyncTask$3.done(AsyncTask.java:299) 

E/AndroidRuntime(26112):  
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) 

E/AndroidRuntime(26112):  
at java.util.concurrent.FutureTask.setException(FutureTask.java:219) 

E/AndroidRuntime(26112):  
at java.util.concurrent.FutureTask.run(FutureTask.java:239) 

E/AndroidRuntime(26112):  
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 

E/AndroidRuntime(26112):  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 

E/AndroidRuntime(26112):  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 

E/AndroidRuntime(26112):  
at java.lang.Thread.run(Thread.java:856) 

E/AndroidRuntime(26112): 
Caused by: org.scribe.exceptions.OAuthException: Problems while creating connection. 

E/AndroidRuntime(26112):  
at org.scribe.model.Request.send(Request.java:70) 

E/AndroidRuntime(26112):  
at org.scribe.model.OAuthRequest.send(OAuthRequest.java:12) 

E/AndroidRuntime(26112):  
at com.notbyimgur.imguraffe.ImageGridActivity$getAccountData.doInBackground(ImageGridActivity.java:1091) 

E/AndroidRuntime(26112):  
at com.notbyimgur.imguraffe.ImageGridActivity$getAccountData.doInBackground(ImageGridActivity.java:1) 

E/AndroidRuntime(26112):  
at android.os.AsyncTask$2.call(AsyncTask.java:287) 

E/AndroidRuntime(26112):  
at java.util.concurrent.FutureTask.run(FutureTask.java:234) 

E/AndroidRuntime(26112): ... 4 more 

E/AndroidRuntime(26112): Caused by: java.io.EOFException 

E/AndroidRuntime(26112): at libcore.io.Streams.readAsciiLine(Streams.java:203) 

E/AndroidRuntime(26112): at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573) 

E/AndroidRuntime(26112): at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821) 

E/AndroidRuntime(26112):  
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283) 

E/AndroidRuntime(26112):  
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:495) 

E/AndroidRuntime(26112):  
at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134) 

E/AndroidRuntime(26112): at org.scribe.model.Response.<init>(Response.java:28) 

E/AndroidRuntime(26112): at org.scribe.model.Request.doSend(Request.java:110) 

E/AndroidRuntime(26112): at org.scribe.model.Request.send(Request.java:62) 

E/AndroidRuntime(26112): ... 9 more 

代码:

只有贴有问题的部分。 在同一活动中可能会同时执行多个OAuth请求(全部在单独的asynctask类中),如果这一点很重要的话。

public class getAccountData extends AsyncTask<Void, Void, dataModels.Account> 
    { 
     private String url = ""; 
     private String accessToken = "";  
     private Client_IDs CLID= new Client_IDs(); 
     public getAccountData(String urlin, AuthenticationToken autht) 
     { 
      url = urlin; 
      accessToken = autht.accessToken; 
     } 

     @Override 
     protected dataModels.Account doInBackground(Void... params) { 

      OAuthService service = new ServiceBuilder() 
          .provider(ImgUr3Api.class) 
          .apiKey(CLID.CLIENT_ID) 
          .apiSecret(CLID.CLIENT_SECRET) 
          .debug() 
          .build(); 
      OAuthRequest request = new OAuthRequest(Verb.GET, url); 
      request.setConnectionKeepAlive(true); 
      service.signRequest(new Token(accessToken, null), request); 
      Response response = request.send(); 

      if(response.getBody() != null) 
      { String body = response.getBody(); 
       dataModels.Account account = new dataModels.Account(); 
       JSONObject rawData; 
       try { 
        rawData = new JSONObject(body); 
        if(rawData.getBoolean("success")) 
        { 
         JSONObject data = rawData.getJSONObject("data"); 
         account.id = data.getInt("id"); 
         account.bio = data.getString("bio"); 
         account.url = data.getString("url"); 
         account.reputation = (int)data.getDouble("reputation"); 
        } 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
       return account; 
      } 
      return null; 
     } 
     @Override 
     protected void onPostExecute(dataModels.Account account) 
     { 
      if(account !=null) 
      {    
       userAcc.id = account.id; 
       userAcc.bio = account.bio; 
       userAcc.reputation = account.reputation; 
       userAcc.url = account.url; 
       if(!isCancelled()) 
       finalizeSlider(true); 
      } 
     } 
    } 

我试过切换request.setConnectionKeepAlive(true/false)没有任何积极的结果。除此之外,我对其他方面的尝试毫无头绪。 请指教。

这是org.scribe.model.Request class (Scribe library)

package org.scribe.model; 

import java.io.*; 
import java.net.*; 
import java.nio.charset.*; 
import java.util.*; 
import java.util.concurrent.*; 

import org.scribe.exceptions.*; 

/** 
* Represents an HTTP Request object 
* 
* @author Pablo Fernandez 
*/ 
public class Request 
{ 
    private static final String CONTENT_LENGTH = "Content-Length"; 
    private static final String CONTENT_TYPE = "Content-Type"; 
    private static RequestTuner NOOP = new RequestTuner() { 
    @Override public void tune(Request _){} 
    }; 
    public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded"; 

    private String url; 
    private Verb verb; 
    private ParameterList querystringParams; 
    private ParameterList bodyParams; 
    private Map<String, String> headers; 
    private String payload = null; 
    private HttpURLConnection connection; 
    private String charset; 
    private byte[] bytePayload = null; 
    private boolean connectionKeepAlive = false; 
    private boolean followRedirects = true; 
    private Long connectTimeout = null; 
    private Long readTimeout = null; 

    /** 
    * Creates a new Http Request 
    * 
    * @param verb Http Verb (GET, POST, etc) 
    * @param url url with optional querystring parameters. 
    */ 
    public Request(Verb verb, String url) 
    { 
    this.verb = verb; 
    this.url = url; 
    this.querystringParams = new ParameterList(); 
    this.bodyParams = new ParameterList(); 
    this.headers = new HashMap<String, String>(); 
    } 

    /** 
    * Execute the request and return a {@link Response} 
    * 
    * @return Http Response 
    * @throws RuntimeException 
    *   if the connection cannot be created. 
    */ 
    public Response send(RequestTuner tuner) 
    { 
    try 
    { 
     createConnection(); 
     return doSend(tuner); 
    } 
    catch (Exception e) 
    { 
     throw new OAuthConnectionException(e); 
    } 
    } 

    public Response send() 
    { 
    return send(NOOP); 
    } 

    private void createConnection() throws IOException 
    { 
    String completeUrl = getCompleteUrl(); 
    if (connection == null) 
    { 
     System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false"); 
     connection = (HttpURLConnection) new URL(completeUrl).openConnection(); 
     connection.setInstanceFollowRedirects(followRedirects); 
    } 
    } 

    /** 
    * Returns the complete url (host + resource + encoded querystring parameters). 
    * 
    * @return the complete url. 
    */ 
    public String getCompleteUrl() 
    { 
    return querystringParams.appendTo(url); 
    } 

    Response doSend(RequestTuner tuner) throws IOException 
    { 
    connection.setRequestMethod(this.verb.name()); 
    if (connectTimeout != null) 
    { 
     connection.setConnectTimeout(connectTimeout.intValue()); 
    } 
    if (readTimeout != null) 
    { 
     connection.setReadTimeout(readTimeout.intValue()); 
    } 
    addHeaders(connection); 
    if (verb.equals(Verb.PUT) || verb.equals(Verb.POST)) 
    { 
     addBody(connection, getByteBodyContents()); 
    } 
    tuner.tune(this); 
    return new Response(connection); 
    } 

    void addHeaders(HttpURLConnection conn) 
    { 
    for (String key : headers.keySet()) 
     conn.setRequestProperty(key, headers.get(key)); 
    } 

    void addBody(HttpURLConnection conn, byte[] content) throws IOException 
    { 
    conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length)); 

    // Set default content type if none is set. 
    if (conn.getRequestProperty(CONTENT_TYPE) == null) 
    { 
     conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); 
    } 
    conn.setDoOutput(true); 
    conn.getOutputStream().write(content); 
    } 

    /** 
    * Add an HTTP Header to the Request 
    * 
    * @param key the header name 
    * @param value the header value 
    */ 
    public void addHeader(String key, String value) 
    { 
    this.headers.put(key, value); 
    } 

    /** 
    * Add a body Parameter (for POST/ PUT Requests) 
    * 
    * @param key the parameter name 
    * @param value the parameter value 
    */ 
    public void addBodyParameter(String key, String value) 
    { 
    this.bodyParams.add(key, value); 
    } 

    /** 
    * Add a QueryString parameter 
    * 
    * @param key the parameter name 
    * @param value the parameter value 
    */ 
    public void addQuerystringParameter(String key, String value) 
    { 
    this.querystringParams.add(key, value); 
    } 

    /** 
    * Add body payload. 
    * 
    * This method is used when the HTTP body is not a form-url-encoded string, 
    * but another thing. Like for example XML. 
    * 
    * Note: The contents are not part of the OAuth signature 
    * 
    * @param payload the body of the request 
    */ 
    public void addPayload(String payload) 
    { 
    this.payload = payload; 
    } 

    /** 
    * Overloaded version for byte arrays 
    * 
    * @param payload 
    */ 
    public void addPayload(byte[] payload) 
    { 
    this.bytePayload = payload.clone(); 
    } 

    /** 
    * Get a {@link ParameterList} with the query string parameters. 
    * 
    * @return a {@link ParameterList} containing the query string parameters. 
    * @throws OAuthException if the request URL is not valid. 
    */ 
    public ParameterList getQueryStringParams() 
    { 
    try 
    { 
     ParameterList result = new ParameterList(); 
     String queryString = new URL(url).getQuery(); 
     result.addQuerystring(queryString); 
     result.addAll(querystringParams); 
     return result; 
    } 
    catch (MalformedURLException mue) 
    { 
     throw new OAuthException("Malformed URL", mue); 
    } 
    } 

    /** 
    * Obtains a {@link ParameterList} of the body parameters. 
    * 
    * @return a {@link ParameterList}containing the body parameters. 
    */ 
    public ParameterList getBodyParams() 
    { 
    return bodyParams; 
    } 

    /** 
    * Obtains the URL of the HTTP Request. 
    * 
    * @return the original URL of the HTTP Request 
    */ 
    public String getUrl() 
    { 
    return url; 
    } 

    /** 
    * Returns the URL without the port and the query string part. 
    * 
    * @return the OAuth-sanitized URL 
    */ 
    public String getSanitizedUrl() 
    { 
    return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", ""); 
    } 

    /** 
    * Returns the body of the request 
    * 
    * @return form encoded string 
    * @throws OAuthException if the charset chosen is not supported 
    */ 
    public String getBodyContents() 
    { 
    try 
    { 
     return new String(getByteBodyContents(),getCharset()); 
    } 
    catch(UnsupportedEncodingException uee) 
    { 
     throw new OAuthException("Unsupported Charset: "+charset, uee); 
    } 
    } 

    byte[] getByteBodyContents() 
    { 
    if (bytePayload != null) return bytePayload; 
    String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString(); 
    try 
    { 
     return body.getBytes(getCharset()); 
    } 
    catch(UnsupportedEncodingException uee) 
    { 
     throw new OAuthException("Unsupported Charset: "+getCharset(), uee); 
    } 
    } 

    /** 
    * Returns the HTTP Verb 
    * 
    * @return the verb 
    */ 
    public Verb getVerb() 
    { 
    return verb; 
    } 

    /** 
    * Returns the connection headers as a {@link Map} 
    * 
    * @return map of headers 
    */ 
    public Map<String, String> getHeaders() 
    { 
    return headers; 
    } 

    /** 
    * Returns the connection charset. Defaults to {@link Charset} defaultCharset if not set 
    * 
    * @return charset 
    */ 
    public String getCharset() 
    { 
    return charset == null ? Charset.defaultCharset().name() : charset; 
    } 

    /** 
    * Sets the connect timeout for the underlying {@link HttpURLConnection} 
    * 
    * @param duration duration of the timeout 
    * 
    * @param unit unit of time (milliseconds, seconds, etc) 
    */ 
    public void setConnectTimeout(int duration, TimeUnit unit) 
    { 
    this.connectTimeout = unit.toMillis(duration); 
    } 

    /** 
    * Sets the read timeout for the underlying {@link HttpURLConnection} 
    * 
    * @param duration duration of the timeout 
    * 
    * @param unit unit of time (milliseconds, seconds, etc) 
    */ 
    public void setReadTimeout(int duration, TimeUnit unit) 
    { 
    this.readTimeout = unit.toMillis(duration); 
    } 

    /** 
    * Set the charset of the body of the request 
    * 
    * @param charsetName name of the charset of the request 
    */ 
    public void setCharset(String charsetName) 
    { 
    this.charset = charsetName; 
    } 

    /** 
    * Sets whether the underlying Http Connection is persistent or not. 
    * 
    * @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html 
    * @param connectionKeepAlive 
    */ 
    public void setConnectionKeepAlive(boolean connectionKeepAlive) 
    { 
    this.connectionKeepAlive = connectionKeepAlive; 
    } 

    /** 
    * Sets whether the underlying Http Connection follows redirects or not. 
    * 
    * Defaults to true (follow redirects) 
    * 
    * @see http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects(boolean) 
    * @param followRedirects 
    */ 
    public void setFollowRedirects(boolean followRedirects) 
    { 
    this.followRedirects = followRedirects; 
    } 

    /* 
    * We need this in order to stub the connection object for test cases 
    */ 
    void setConnection(HttpURLConnection connection) 
    { 
    this.connection = connection; 
    } 

    @Override 
    public String toString() 
    { 
    return String.format("@Request(%s %s)", getVerb(), getUrl()); 
    } 
} 

回答

2

的代码错误几乎使我精神错乱时,我与它挣扎着,我(想)在我的代码进行小的改动解决了这个问题。希望它也能帮助你。

  1. 如果您HttpURLConnection的请求是POST请求删除此行conn.setDoOutput(true);

  2. 得到的OutputStream调用之前conn.connect()

  3. 最后我删除http.keepAlive sentece可言。

到目前为止没有更多的随机EOF(因为我上周改变了它)。