Android 尝试获取 http 请求时失败

Android fails when trying to GET http request

我正在尝试从 http 请求中获取信息,但它显示以下错误:

> 06-17 18:06:05.931  10913-10913/com.example.user.project
> E/RecyclerView﹕ No adapter attached; skipping layout 06-17
> 18:06:05.947  10913-10913/com.example.user.project E/AndroidRuntime﹕
> FATAL EXCEPTION: main
>     Process: com.example.user.project, PID: 10913
>     android.os.NetworkOnMainThreadException
>             at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
>             at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
>             at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
>             at java.net.InetAddress.getAllByName(InetAddress.java:215)
>             at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:142)
>             at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
>             at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
>             at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
>             at com.example.user.project.helper.JSONParser.makeHttpRequest(JSONParser.java:55)
>             at com.example.user.project.itemActivity$getitem.run(itemActivity.java:120)
>             at android.os.Handler.handleCallback(Handler.java:739)
>             at android.os.Handler.dispatchMessage(Handler.java:95)
>             at android.os.Looper.loop(Looper.java:135)
>             at android.app.ActivityThread.main(ActivityThread.java:5254)
>             at java.lang.reflect.description.invoke(Native description)
>             at java.lang.reflect.description.invoke(description.java:372)
>             at com.android.internal.os.ZygoteInit$descriptionAndArgsCaller.run(ZygoteInit.java:903)
>             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

itemActivity.java:

public class itemActivity extends AppCompatActivity {

private static final String TAG_SUCCESS = "success";
private static final String TAG_item = "item";
private static final String TAG_item_NAME = "name";
private static final String TAG_item_description = "description";

Integer item_id;
String name;
String username;
String description;
TextView itemname;
TextView itemdescription;
ProgressDialog pDialog;
JSONParser jParser;
RecyclerView recycler;
ActionBar actionBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_item);

    Intent i = getIntent();
    if (i.hasExtra("item_id")) {
        Bundle bd = getIntent().getExtras();
        /*if ((!bd.getString("name").equals(null) || bd.getString("name").trim().length() > 0) && (!bd.getString("username").equals(null) || bd.getString("username").trim().length() > 0) && (!bd.getString("description").equals(null) || bd.getString("description").trim().length() > 0)) {
            name = bd.getString("name");
            username = bd.getString("username");
            description = bd.getString("description");
        }*/
        item_id = bd.getInt("item_id");
    }

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    actionBar = getSupportActionBar();
    actionBar.setTitle(R.string.app_name);

    itemname = (TextView) findViewById(R.id.itemName);
    itemdescription = (TextView) findViewById(R.id.itemdescription);

    new getitem().execute();
    /*recycler = (RecyclerView) findViewById(R.id.recycler);
    recycler.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recycler.setLayoutManager(layoutManager);*/

}

/**
 * Background Async Task to Get complete item details
 */
class getitem extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(itemActivity.this);
        pDialog.setMessage(getResources().getString(R.string.loadingitem));
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Getting item details in background thread
     */
    protected String doInBackground(String... params) {

        // updating UI from Background Thread

        // Check for success tag
        int success;
        try {
            // Building Parameters
            List<NameValuePair> myParameters = new ArrayList<NameValuePair>();
            myParameters.add(new BasicNameValuePair("item_id", Integer.toString(item_id)));

            // getting item details by making HTTP request
            // Note that item details url will use GET request
            jParser = new JSONParser();
            JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_item, "GET", myParameters);

            // check your log for json response
            Log.d("Single item Details", json.toString());

            // json success tag
            success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // successfully received item details
                JSONArray itemObj = json.getJSONArray(TAG_item); // JSON Array

                // get first item object from JSON Array
                JSONObject item = itemObj.getJSONObject(0);

                // item with this pid found
                // Edit Text
                itemname.setText(item.getString(TAG_item_NAME));
                itemdescription.setText(item.getString(TAG_item_description));
            } else {
                // item with pid not found
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * After completing background task Dismiss the progress dialog
     * *
     */
    protected void onPostExecute(String file_url) {
        // dismiss the dialog once got all details
        pDialog.dismiss();
    }
}

/*itemname=(TextView)

findViewById(R.id.itemName);

itemdescription=(TextView)

findViewById(R.id.itemdescription);*/

//itemname.setText(name);
//itemdescription.setText(description);

activity_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="@bool/fitsSystemWindows">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimary" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimaryDark" />

    </LinearLayout>

    <FrameLayout
        android:id="@+id/flma"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/status_bar_height">

        <TextView
            android:id="@+id/itemName"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            android:layout_marginTop="80dp"
            android:gravity="center"
            android:textAllCaps="true"
            android:textSize="25dp"
            android:textStyle="bold" />

        <ImageView
            android:id="@+id/itemPhoto"
            android:layout_width="fill_parent"
            android:layout_height="300dp"
            android:layout_gravity="center"
            android:background="#000"
            android:src="@drawable/header" />

        <TextView
            android:id="@+id/itemdescription"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_marginBottom="50dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="@bool/fitsSystemWindows"
        app:headerLayout="@layout/navigation_drawer_header"
        app:menu="@menu/navigation_drawer_menu"
        app:theme="@style/NavigationViewTheme" />

</android.support.v4.widget.DrawerLayout>

JSONParser.java:

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    // constructor
    public JSONParser() {

    }

    // función para obtener JSON desde la URL
    public JSONObject makeHttpRequest(String url, String description, List<NameValuePair> params) {

        try {

            if(description == "POST"){
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);
                httpPost.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();

            }else if(description == "GET"){
                DefaultHttpClient httpClient = new DefaultHttpClient();
                String paramString = URLEncodedUtils.format(params, "utf-8");
                url += "?" + paramString;
                HttpGet httpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }


        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        return jObj;

    }
}

我正在尝试通过项目 ID 发送 GET 请求来获取项目的所有信息。查看错误,我认为失败是我发出HTTP请求时出现的问题,但我不确定。

有谁知道为什么会失败?

谢谢!

编辑:

现在我收到以下错误:

06-17 20:56:52.856      418-428/? E/art﹕ Failed sending reply to debugger: Broken pipe
06-17 20:57:07.391      418-767/com.example.user.project_test E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #3
    Process: com.example.user.project_test, PID: 418
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask.done(AsyncTask.java:304)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
            at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909)
            at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690)
            at android.view.View.invalidateInternal(View.java:11801)
            at android.view.View.invalidate(View.java:11765)
            at android.view.View.invalidate(View.java:11749)
            at android.widget.TextView.checkForRelayout(TextView.java:6858)
            at android.widget.TextView.setText(TextView.java:4057)
            at android.widget.TextView.setText(TextView.java:3915)
            at android.widget.TextView.setText(TextView.java:3890)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:132)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:84)
            at android.os.AsyncTask.call(AsyncTask.java:292)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
06-17 20:57:07.612      418-418/com.example.user.project_test E/WindowManager﹕ android.view.WindowLeaked: Activity com.example.user.project.itemActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{19feb64d V.E..... R......D 0,0-1026,348} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
            at android.app.Dialog.show(Dialog.java:298)
            at com.example.user.project.itemActivity$getitem.onPreExecute(itemActivity.java:96)
            at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)
            at android.os.AsyncTask.execute(AsyncTask.java:539)
            at com.example.user.project.itemActivity.onCreate(itemActivity.java:71)
            at android.app.Activity.performCreate(Activity.java:5990)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access0(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.description.invoke(Native description)
            at java.lang.reflect.description.invoke(description.java:372)
            at com.android.internal.os.ZygoteInit$descriptionAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

它失败了,因为你试图在主线程上获取食谱 android.os.NetworkOnMainThreadException

似乎有问题的是:

JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_RECIPE, "GET", params);

此调用失败的原因是因为您将其包装在 runOnUIThread 调用中,该调用将尝试处理主线程上的所有内容。这反过来会导致您的网络请求,尽管处于异步任务中,但在主线程上 运行。


问题 params

protected String doInBackground(String... params) {

        // updating UI from Background Thread
        runOnUiThread(new Runnable() {
            public void run() {
                // Check for success tag
                int success;
                try {
                    // Building Parameters
                    List<NameValuePair> params = new ArrayList<NameValuePair>();

doInBackground 的参数称为 params,您正在尝试创建另一个名为 params 的变量。只是改变

List<NameValuePair> params = new ArrayList<NameValuePair>();

类似于

List<NameValuePair> myParameters = new ArrayList<NameValuePair>();

确保同时更新所有对参数的引用。这最好通过 IDE.

中的重构工具来完成

太近了!这个错误也很容易修复。

默认情况下 doInBackground 运行s 在由 AsyncTask 生成和维护的后台线程中。因为这是一个后台线程 而不是执行 UI 的主线程 你不能对 UI (编辑文本、标签、按钮等)进行更改除主线程外的任何其他线程。 这个就是我们要用runOnUIThread的地方。目前,在您的 doInBackground 中有以下几行:

recipename.setText(recipe.getString(TAG_RECIPE_NAME));
recipemethod.setText(recipe.getString(TAG_RECIPE_METHOD));

只需将它们包裹在 runOnUIThread

runOnUIThread(new Runnable()
{
    recipename.setText(recipe.getString(TAG_RECIPE_NAME));
    recipemethod.setText(recipe.getString(TAG_RECIPE_METHOD));
});

但是,我建议您 return 此方法中的字符串并在 onPostExecute 中执行所有 UI 更改,因为此方法 运行s 在 UI 默认线程。您还可以在 onProgressUpdate 中进行更改,因为这将在 UI 线程上 运行。