2016-10-01 56 views
0

我正在編寫Android的Phonegap應用程序,該應用程序使用我在同一時間開發的一個插件。該應用程序使用Rhino運行JavaScript中的一組數據分析操作。這樣做的原因之一是使我能夠在需要時靜默更新數據分析規則,而不會強制整個應用程序版本更新。Android HTTPUrlConnection錯誤

Rhino使用的JavaScript代碼由應用程序下載並存儲到內部存儲器中。這發生在兩個方面

  • 在應用程序啓動:當應用程序啓動時,它會檢查JS代碼文件的存在。如果不存在,則從服務器獲取它。
  • 回覆推送消息:當需要時,我發送推送消息到應用程序,通過嘗試從服務器獲取更新的JS代碼進行反應。

兩條路由都使用相同位的底層Java代碼來執行JS代碼更新。第一個沒有任何問題。然而第二個拋出異常。

相關的代碼

private boolean doInit(CallbackContext cbc) 
{ 
    Storage.setFilePath(this.context.getFilesDir()); 
    Storage.loadJSCode(); 
    ... 
} 

當PhoneGap的觸發其onDeviceReady事件上面被稱爲 - i.e.when應用程序啓動。

Storage是我在應用程序中處理文件I/O操作的泛型類。實際loadJSCode如下所示

public static String loadJSCode() 
{ 
    try 
    { 
    String rslt = ""; 
    HttpURLConnection conn = null; 
    addr = "https://path/to/rhinocode.php"; 
    try 
    { 
    URL url = new URL(addr); 
    conn = (HttpURLConnection)url.openConnection(); 
    conn.setRequestMethod("GET"); 
    conn.setRequestProperty("User-Agent", Statics.USER_AGENT); 

    InputStream ips = conn.getInputStream(); 
    //THE EXCEPTION IS THROWN HERE 
    int responseCode = conn.getResponseCode(); 
    if (200 != responseCode) 
    { 
    Feedback.logError("GET error: " + responseCode + " on " + addr); 
    return null; 
    } 

    BufferedReader bufr = new BufferedReader(new InputStreamReader(ips)); 
    String line; 
    while ((line = bufr.readLine()) != null) rslt += line; 
    bufr.close(); 
    } finally{if (null != conn) conn.disconnect();} 
    return rslt; 
    } catch(Exception e) 
    { 
    Feedback.logError("get fault " + Utils.stackTrace(e)); 
    return null; 
    } 
} 
} 

一對夫婦的解釋筆記

  • 反饋是I類使用,以處理涉及顯示的東西給用戶的所有操作。
  • Utils是一個我用來封裝實用程序例程的類。在這個例子中,stackTrace例程爲我提供了一個完整的堆棧跟蹤,導致問題作爲一個字符串。

觸發違規調用loadJSCode如下所示

public class Receive extends BroadcastReceiver 
{ 
    @Override 
    public void onReceive(Context context,Intent intent) 
    { 
    Bundle extras = intent.getExtras(); 
    if (extras != null) 
    { 
    if (extras.getString("message") != null && 
    extras.getString("message").length() != 0) 
    { 
    try 
    { 
     JSONObject jo = new JSONObject(extras.getString("message")); 
     int code = jo.optInt("kind",0); 
     if (1 == code) storage.loadJSCode(); 
    } catch(Exception e){Feedback.setError(e.getMessage());} 
    } 
    } 
    } 
} 

Push消息處理程序的完整的堆棧跟蹤導致這一問題如下所示

android.os.NetworkOnMainThread Exception 
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictM ode.java:1 156) 
at com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSock etImpl.javal 009) 
at com.android.okhttp.Connection.c1ose(Connection.java:175) 
at com.android.okhttp.internal.Util.c1oseQuietly(Util.java:110) 
at com.android.okhttp.internal.http.HttpEngine.release(HttpEngine.java: 447) 
at com.android.okhttp.internal.http.HttpURLConnectionImpl.disconnect 
(HttpURLConnectionImpl.java:104) 
at 
com.android.okhttp.internal.http.HttpsURLConnectionlmpl. 
disconnect(HttpsURLConnectionImpl java:124) 
at example.com.plugin.Storage.IoadJSCode(Storage.java:28) 
at example.com.plugin.Receive.onReceive (Receive.java:50) 
at android.app.ActivityThread.handle (Storage.java:28) 
at com.example.plugin.Receive.onReceive (Receive.java:50) 
at android.app.ActivityThread.handle Receiver(ActivityThread.java:2585) 
at android.app.ActivityThread.access $1800(ActivityThread.java:151) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1409) 
at android.os.Handler.dispatchMessage(Handler.java:1 10) 
at android.os.Looper.loon(Looper.java) 
$1800(ActivityThread.java 51) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java 409) 
at android.os.HandlerdispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper java:193) 
at android.app.ActivityThread main(ActivityThread.java:5304) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at com.android.internal.os.Zygotelnit $MethodAndArgsCaller.run(Zygote 
at android.os.Looper.loop(Looper.jav a:193) 
at android.app.ActivityThread.main(ActivityThread.java:5304) 
at java.lang.reflect.Method.invokeNative(Native Method) at  
java.lang.reflect.Method.invoke(Method.java:515) at 
com.android.internal.os.Zygotelnit 
$MethodAndArgsCaller.run(Zygot elnit.java:824) 
at com.android.internal.os.Zygotelnit .main(Zygotelnit.java:640) 
at dalvik.system.NativeStart.main 

通過一些力實驗我已經確定當執行上述loadJSCodeInputStream ips = conn.getInputStream();時拋出異常。

爲了完整起見,我應該提到ReceiveBroadcastReceiver子類是通過嵌入在plugin.xml文件中的以下內容觸發的。

<receiver android:name="com.example.plugin.Receive" 
            android:exported="false"> 
<intent-filter> 
    <!-- Do not modify this --> 
    <action android:name="pushy.me" /> 
</intent-filter> 
</receiver> 

我在使用Java 7的Phonegap CLI 6.3.3。

我懷疑我在這裏以某種方式運行線程規則,並且正在做一些來自後臺線程或者這些線程的東西。然而,我並不清楚我可能是否會造成這種錯誤。我希望這裏的某個人能夠解釋。

+1

第一件事。 –

+0

@VishalThakkar--你能否詳細說明一下?你的意思是整個HTTPUrl位應該在asynctask中執行? – DroidOS

+1

這應該調用asynctask doinbackground –

回答

1

網絡操作無法在主線程中執行。你應該在不同的線程中進行網絡操作。您可以創建自己的線程或使用android framwork提供的AsyncTask。例如:

class AsyncTaskRunner extends AsyncTask<Void, Void, Void> { 

    private String resp; 

    @Override 
    protected String doInBackground(String... params) { 
//don't perform UI operation here, perform network operation 
    resp = loadJSCode(); 
    return resp; 
    } 


    @Override 
    protected void onPostExecute(String result) { 
    // When network operation completed then this method is called and you 
    // can update UI from this method. 
    } 


    @Override 
    protected void onPreExecute() { 

    } 


} 

現在可以執行的任務:

new AsyncTaskRunner().execute(); 

詳情https://developer.android.com/reference/android/os/AsyncTask.html

你必須調用裏面的AsyncTask web服務而不是主線程
相關問題