【问题标题】:Why my android app cannot get data from JSON url?为什么我的 android 应用无法从 JSON url 获取数据?
【发布时间】:2013-12-06 19:38:57
【问题描述】:

我正在尝试运行基于 WorlBank API 的应用程序。我有一个 JSON URL 来获取有关国家/地区的数据,然后在 TextViews 中显示它。简单的。但是一旦我运行应用程序就关闭了。

这是我的文件:

主要活动:

public class MainActivity extends Activity {

//URL to get JSON Array
private static String url = "http://api.worldbank.org/countries/ir?format=json";

//JSON node Names
private static final String PAGE = "page";
private static final String VALUE = "value";
private static final String NAME = "name";
private static final String GEO = "region";

JSONArray page = null;

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

    //Creating new JSON Parser
    JSONParser jParser = new JSONParser();
    // Getting JSON from URL
    JSONObject json = jParser.getJSONFromUrl(url);

    try{
        //Getting JSON Array
        page = json.getJSONArray(PAGE);
        JSONObject c = page.getJSONObject(0);

        //Sorting JSON item in a Variable
        String value = c.getString(VALUE);
        String name = c.getString(NAME);
        String geo = c.getString(GEO);

        //Importing to TextView
        final TextView id1 = (TextView) findViewById(R.id.id);
        final TextView name1 = (TextView) findViewById(R.id.name);
        final TextView geo1 = (TextView) findViewById(R.id.geo);

        //set JSON Data in TextView
        id1.setText(value);
        name1.setText(name);
        geo1.setText(geo);
    } catch (JSONException e){
        e.printStackTrace();
    }



}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

    }

JSON解析器:

public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";

// constructor
public JSONParser() {

}

public JSONObject getJSONFromUrl(String url) {

    // Making HTTP request
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        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 parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    // return JSON String
    return jObj;

}
}

XML:

<TextView
    android:id="@+id/id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/name"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/id"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/geo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/id"
    android:layout_alignParentTop="true"
    android:layout_marginTop="76dp"
    android:textAppearance="?android:attr/textAppearanceLarge" />

有什么想法吗?

世界银行api:http://data.worldbank.org/node/18

更新:

android:minSdkVersion="8"

android:targetSdkVersion="18"

FATAL EXCEPTION: main
E/AndroidRuntime(966): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.jsonsyctask/com.example.jsonsyctask.Main}: android.os.NetworkOnMainThreadException
E/AndroidRuntime(966):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
E/AndroidRuntime(966):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
E/AndroidRuntime(966):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
E/AndroidRuntime(966):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
E/AndroidRuntime(966):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(966):  at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(966):  at android.app.ActivityThread.main(ActivityThread.java:5103)
E/AndroidRuntime(966):  at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(966):  at java.lang.reflect.Method.invoke(Method.java:525)
E/AndroidRuntime(966):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)

【问题讨论】:

  • 尝试在异步任务中运行...
  • @HarshitRathi 我不知道这个。你能解释一下吗?
  • 使用此链接androidhive.info/2012/01/android-json-parsing-tutorial 它将帮助您了解如何在异步任务中解析 json...
  • 首先,不要只做类似 “但只要我在关闭应用程序时运行。” 而不提供来自 logcat 的堆栈跟踪 - 向我们展示错误和代码。其次,您的问题的答案是,正如其他人所说,您正在 UI 线程上进行网络操作(在旧版本的 Android 上可以,但在更高版本的 Android 上不行)或者(无论如何这会咬你)URL 返回一个JSON 数组而不是 JSON 对象。此外,您正在执行 HTTP Post,而应该使用 HTTP GET。解决所有这些问题,您就可以开始了。
  • 我同意@Squonk。您应该发布您的log。上面提到的代码有很多问题..

标签: java android json textview


【解决方案1】:

出现问题是因为您试图在 UI 线程上执行网络操作。网络操作需要使用后台线程。

如下使用AsyncTask

public class MainActivity extends Activity {

    //URL to get JSON Array
    private static String url = "http://api.worldbank.org/countries/ir?format=json";

    //JSON node Names
    private static final String PAGE = "page";
    private static final String VALUE = "value";
    private static final String NAME = "name";
    private static final String GEO = "region";

    JSONArray page = null;

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

        new GetJSONTask().execute(url);

        // do not parse here..
        ...
        ...
    }
    ...
    ...

    class GetJSONTask extends AsyncTask<String, Void, JSONObject> {


        protected JSONObject doInBackground(String... urls) {
            try {
                JSONParser jParser = new JSONParser();
                return jParser.getJSONFromUrl(urls[0]);
            } catch (Exception e) {
                return null;
            }
        }

        protected void onPostExecute(JSONObject json) {
            // do all the parsing here:
            try {
                //Getting JSON Array
                page = json.getJSONArray(PAGE);
                JSONObject c = page.getJSONObject(0);

                //Sorting JSON item in a Variable
                String value = c.getString(VALUE);
                String name = c.getString(NAME);
                String geo = c.getString(GEO);

                //Importing to TextView
                final TextView id1 = (TextView) findViewById(R.id.id);
                final TextView name1 = (TextView) findViewById(R.id.name);
                final TextView geo1 = (TextView) findViewById(R.id.geo);

                //set JSON Data in TextView
                id1.setText(value);
                name1.setText(name);
                geo1.setText(geo);
            }
            catch (JSONException e)
            {
                e.printStackTrace();
            }
        } 
    }
}

参考:http://developer.android.com/reference/android/os/AsyncTask.html

更新发现另一个错误,更新 XML

<TextView
    android:id="@+id/id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/name"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge" />
...
...

你不能有两个视图并说A below B,然后B below Acause problems!

【讨论】:

  • 这不是问题的保证答案(取决于 Android 版本,允许在 UI 线程上联网,并且 OP 不会告诉我们他正在使用哪个版本)。在这个阶段可能是正确的,但请参阅我对 OP 问题的评论 - 他还有一些其他问题需要解决。
  • 如前所述,我同意你的看法。将根据提供的更多信息更新我的答案..
  • @Squonk 我刚刚更新了我的帖子并添加了 logcat 的前几行。
  • @user2977338 你得到NetworkOnMainThread 异常。这就是我上面解释的。如果有任何进一步的崩溃,请按照我的回答和报告..
  • 感谢您的帖子。刚试过。应用程序停止,这是目录:E/AndroidRuntime(1136): FATAL EXCEPTION: main E/AndroidRuntime(1136): java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout E/AndroidRuntime(1136): at android.widget.RelativeLayout$DependencyGraph.getSortedViews(RelativeLayout.java:1692) E/AndroidRuntime(1136): at android.widget.RelativeLayout.sortChildren(RelativeLayout.java:382)
【解决方案2】:

您可以使用droidQuery 大大简化您所做的一切:

$.ajax(new AjaxOptions().url(url).success(new Function() {
    @Override
    public void invoke($ d, Object... args) {
        JSONObject json = (JSONObject) args[0];
        JSONArray page = json.getJSONArray(PAGE);
        JSONObject c = page.getJSONObject(0);

        $.with(MyActivity.this, R.id.id).text(c.getString(VALUE))
                            .id(R.id.name).text(c.getString(NAME))
                            .id(geo).text(c.getString(GEO));

    }
}));

【讨论】:

  • 嗯...为什么投反对票?这大大简化了 OP 的代码,并使用 AsyncTasks 处理所有后台线程。
  • 我投了反对票,因为您没有尝试解决 OP 的直接问题,而是使用完全不同的技术发布了代码。您只是假设他们会自动转换他们的编码方法。请记住,OP 正在努力执行基本的 GET 请求以检索 JSON 字符串(使用 POST 代替),并试图将生成的 JSON 数组作为 JSON 对象处理,我觉得你不合适假设他们会理解您的方法或知道如何使用它。
【解决方案3】:

我使用了 Kevin Sawicki 的 HTTP Request Library,这非常有帮助,请在下面找到工作示例。不要忘记添加android权限

<uses-permission android:name="android.permission.INTERNET" />

http://api.worldbank.org/countries/ir?format=json检索到的json值

package com.javasrilankansupport.testhttps;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.github.kevinsawicki.http.HttpRequest;
import com.github.kevinsawicki.http.HttpRequest.HttpRequestException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

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

    new DownloadTask().execute("http://api.worldbank.org/countries/ir?format=json");
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

private class DownloadTask extends AsyncTask<String, Long, Boolean> {
    protected Boolean doInBackground(String... urls) {
        try {

            // kevinsawicki's HttpRequest from github
            HttpRequest request = HttpRequest.get(urls[0])
                    .trustAllCerts() // for HTTPS request
                    .trustAllHosts() // to trust all hosts 
                    .acceptJson();   // to accept JSON objects 

            if (request.ok()) {

                JSONObject jsonObject;
                try {
                    String s = request.body();
                    Log.d("MyApp",
                            "Downloaded json data: "+ s);

                    //  change parameters according to your JSON 
                    jsonObject = new JSONObject(s);

                    JSONArray jsonArray = jsonObject
                            .getJSONArray("categories");

                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject jsonObj = jsonArray.getJSONObject(i);
                        Log.d("MyApp",
                                "Downloaded json data: "
                                        + jsonObj.getString("id") + "  "
                                        + jsonObj.getString("slug"));
                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.print("error");
            }
        } catch (HttpRequestException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    protected void onProgressUpdate(Long... progress) {
        // progress bar here
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
    }

 }
}

【讨论】:

    【解决方案4】:

    从服务器获取数据需要以下步骤:

    1. 确保您生成的 json 字符串格式正确。您可以在各种网站上找到它。
    2. 从服务器请求时,您必须使用 AsyncTask。

    下面的例子有助于理解逻辑

    package com.example.sonasys.net;
    import java.util.ArrayList;
    import java.util.HashMap;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    import com.example.sonaprintersd.R;
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.graphics.Bitmap;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class SingleContactActivity extends Activity {
    
    
    private static final String TAG_CONTACTS = "Contacts";
    private static final String TAG_POSTLINE = "PostLine";
    private static final String TAG_Post_Img = "Post_Img";
    private static final String TAG_Post_Img_O = "Post_Img_O";
    
    private static String url;
    TextView uid, pid;
    JSONArray contacts = null;
    private ProgressDialog pDialog;
    String details;
    // String imagepath = "http://test2.sonasys.net/Content/WallPost/b3.jpg";
    String imagepath = "";
    Bitmap bitmap;
    ImageView image;
    String imagepath2;
    
    ArrayList<HashMap<String, String>> contactList;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_contact);
    
        url = "http://test2.sonasys.net/MobileApp/GetSinglePost?UserId="
                + uid.getText() + "&Post_ID=" + pid.getText();
    
        contactList = new ArrayList<HashMap<String, String>>();
        new GetContacts().execute();
    
    }
    
    private class GetContacts extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Showing progress dialog
            pDialog = new ProgressDialog(SingleContactActivity.this);
            pDialog.setMessage("Please wait...");
            pDialog.setCancelable(false);
            // pDialog.setTitle("Post Details");
            pDialog.show();
    
        }
    
        @Override
        protected Void doInBackground(Void... arg0) {
            // Creating service handler class instance
            ServiceHandler sh = new ServiceHandler();
    
            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
    
            Log.d("Response: ", "> " + jsonStr);
    
            if (jsonStr != null) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);
    
                    // Getting JSON Array node
                    contacts = jsonObj.getJSONArray(TAG_CONTACTS);
    
                    // looping through All Contacts
    
                    JSONObject c = contacts.getJSONObject(0);
    
                    details = c.getString(TAG_POSTLINE);
                    imagepath = c.getString(TAG_Post_Img);
                    imagepath2 = c.getString(TAG_Post_Img_O);
    
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                Log.e("ServiceHandler", "Couldn't get any data from the url");
            }
    
            return null;
        }
    
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            // Dismiss the progress dialog
            if (pDialog.isShowing())
                pDialog.dismiss();
            /**/
            TextView Details = (TextView) findViewById(R.id.details);
            // Details.setText(details);
            Details.setText(android.text.Html.fromHtml(details));
    
        }
    }
    
    
    
    
    
    public class ServiceHandler {
    
    static String response = null;
    public final static int GET = 1;
    public final static int POST = 2;
    
    public ServiceHandler() {
    
    }
    
    /*
     * Making service call
     * @url - url to make request
     * @method - http request method
     * */
    public String makeServiceCall(String url, int method) {
    
    
    
        return this.makeServiceCall(url, method, null);
    }
    
    /*
     * Making service call
     * @url - url to make request
     * @method - http request method
     * @params - http request params
     * 
    
     * */
    
    public String makeServiceCall(String url, int method,List<NameValuePair> params) {
    
        try {
            // http client
    
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpEntity httpEntity = null;
            HttpResponse httpResponse = null;
    
            // Checking http request method type
            if (method == POST) {
                HttpPost httpPost = new HttpPost(url);
                // adding post params
                if (params != null) {               
                    httpPost.setEntity(new UrlEncodedFormEntity(params));
    
                }
    
                httpResponse = httpClient.execute(httpPost);
    
            } else if (method == GET) {
                // appending params to url
                if (params != null) {
                    String paramString = URLEncodedUtils.format(params, "utf-8");
                    url += "?" + paramString;
                }
                HttpGet httpGet = new HttpGet(url);
    
                httpResponse = httpClient.execute(httpGet);
    
            }
            httpEntity = httpResponse.getEntity();
            response = EntityUtils.toString(httpEntity);
    
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return response;
    
    }
    

    【讨论】:

    • @benka 你能建议我如何以一种好的方式格式化我的帖子吗?
    • 我建议查看此链接:stackoverflow.com/editing-help,讨论格式化/降价。此外,当您编写/编辑帖子时,右侧会有帮助,编辑器窗口的右上角有一个橙色的大问号,如果您单击它会提供有用的帮助:) 此外,它不会给您带来任何负面影响或者当有人编辑您的帖子时,实际上格式良好的帖子可以帮助您获得更多声誉。
    【解决方案5】:

    我的猜测是,这是因为您尝试在主线程上进行网络活动。这是不行的。

    也许添加一个默认的异常处理程序和一个断点会有所帮助-

    Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread thread, Throwable throwable) {
            throwable.printStackTrace();
        }
    });
    

    【讨论】:

    • 谢谢。我应该在哪里添加它?
    • 添加异常处理程序无济于事,他只需要在 AsyncTask 中完成网络工作,正如他的问题的 cmets 中已经提到的那样。
    • 我的意思是,如果他/她安装了处理程序,他们将能够确认这是问题所在,而不是解决他们的问题。
    猜你喜欢
    • 1970-01-01
    • 2013-07-14
    • 2013-02-17
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2017-10-11
    相关资源
    最近更新 更多