将JSON结果导入ListView时出错

时间:2014-03-26 05:50:05

标签: php android json android-listview android-json

更新4:解决问题检查下面的答案

我试图从PHP Webservice中检索JSON结果并将其保存到ListView但是我收到了错误

我不确定你能帮助我的错误是什么

我从Travis(mybringback)那里学习本教程

http://www.mybringback.com/tutorial-series/13239/android-mysql-php-json-part-6-json-parsing-and-android-design/

他的方法(仅限于此部分)不需要任何参数来获取帖子(并且它实际上是使用HIS PHP方法的工作) 但我的Web服务方法需要2个参数(kioskid(设备ID),accessstoken),它们保存在SharedPreferense中

Update1:​​

我修改了Android代码也卸载旧的代码并从beginig开始(登录等),直到我到达EventListActivity但没有显示List,我在日志中只有一个错误行(设备中没有错误消息)

Update2:修改代码并分离 UpdateJSON() 并尝试在 doInBackground()中获取JSON响应

更新3:我添加了JSONParse类

我收到一条新的错误消息,我在方法 updateList()中的 setListAdapter(适配器) 处获得了NullPointerexception

这是错误日志:

03-26 16:58:38.397: E/AndroidRuntime(16196): FATAL EXCEPTION: main
03-26 16:58:38.397: E/AndroidRuntime(16196): Process: com.test.event, PID: 16196
03-26 16:58:38.397: E/AndroidRuntime(16196): java.lang.NullPointerException
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.widget.ListView.setAdapter(ListView.java:480)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.app.ListActivity.setListAdapter(ListActivity.java:265)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.decoder.tapway.event1.EventListActivity.updateList(EventListActivity.java:140)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.decoder.tapway.event1.EventListActivity.access$3(EventListActivity.java:136)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.decoder.tapway.event1.EventListActivity$LoadEvents.onPostExecute(EventListActivity.java:221)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.decoder.tapway.event1.EventListActivity$LoadEvents.onPostExecute(EventListActivity.java:1)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.os.AsyncTask.finish(AsyncTask.java:632)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.os.Handler.dispatchMessage(Handler.java:102)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.os.Looper.loop(Looper.java:136)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at android.app.ActivityThread.main(ActivityThread.java:5050)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at java.lang.reflect.Method.invokeNative(Native Method)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at java.lang.reflect.Method.invoke(Method.java:515)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-26 16:58:38.397: E/AndroidRuntime(16196):    at dalvik.system.NativeStart.main(Native Method)

这是我试图获得其JSON结果的PHP函数(Yii Framework)

public function actionEventList(){
        if(isset($_POST['kioskid']) && isset($_POST['accesstoken'])){
            $response = array();

            $kiosk = Kiosk::model()->findByAttributes(array('kioskid'=>$_POST['kioskid'], 'accesstoken'=>$_POST['accesstoken']));
            if($kiosk === null){
                $response['status'] = '0';
                $response['message'] = 'Invalid Kiosk';
            } else {
                $events = Event::model()->findAllByAttributes(array('createdby'=>$kiosk->userid, 'status'=>'A'));
                $list = array();
                foreach($events as $row){
                    $list[] = array('id'=>$row->id, 'name'=>$row->eventname);
                }
                $response['status'] = '1';
                $response['list'] = $list;
            }
            $this->_sendResponse(200, CJSON::encode($response));
        } else {
            $this->_sendResponse(400);
        }
    }

这是我在android中的Java代码:(更新2)

最重要的方法是 updateJSONdata() 从服务器检索最近的事件

然后我在 doInBackground()

中调用该方法
public class EventListActivity extends ListActivity {

    // Progress Dialog
    private ProgressDialog pDialog;


    // testing on Server:
    private static final String EVENT_LIST_URL = "http://www.XXX.com/XXX/XXX/eventList";



    // JSON IDS:
    private static final String TAG_STATUS = "status";
    private static final String TAG_EVENT_LIST = "list";
    private static final String TAG_EVENT_ID = "id";
    private static final String TAG_EVENT_NAME = "name";
    private static final String TAG_MESSAGE = "message";

    // An array of all of our Events
    private JSONArray jaEvents = null;

    // manages all of our events in a list.
    private ArrayList<HashMap<String, String>> arrayEventList;


    // prerepare SharedPreferences file name
    private static final String PREFS_NAME = "com.MyApp.event"; 

    private SharedPreferences sharedPref ;

    String accesstoken, username, kioskid,spKioskid, password ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.event_list_layout);

        // setup SharedPreferences file
        this.sharedPref = getSharedPreferences(PREFS_NAME,0);

        // get data from previous activity 
        this.accesstoken = sharedPref.getString("accesstoken", null);
        this.kioskid = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

        Toast.makeText(EventListActivity.this, "onCreate\n"+kioskid, Toast.LENGTH_LONG).show();
        Toast.makeText(EventListActivity.this, "onCreate\n"+accesstoken, Toast.LENGTH_LONG).show();

    }

    @Override
    protected void onResume() {
        super.onResume();
        // assign data from SharedPreferences 
        this.accesstoken = sharedPref.getString("accesstoken", null);
        this.kioskid = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
        Toast.makeText(EventListActivity.this, "onResume\n"+kioskid, Toast.LENGTH_LONG).show();
        Toast.makeText(EventListActivity.this, "onResume\n"+accesstoken, Toast.LENGTH_LONG).show();


        // loading the comments via AsyncTask
        new LoadEvents().execute();
    }


    /**
     * Retrieves recent Events from the server.
     */
    public void updateJSONdata() {

        arrayEventList = new ArrayList<HashMap<String, String>>();

        JSONParser jParser = new JSONParser();

        JSONObject jsonObj = jParser.getJSONFromUrl(EVENT_LIST_URL);

        try {

            jaEvents = jsonObj.getJSONArray(TAG_EVENT_LIST);

            // looping through all events according to the json object returned
            for (int i = 0; i < jaEvents.length(); i++) {
                JSONObject c = jaEvents.getJSONObject(i);

                // gets the content of each tag
                String eventID = c.getString(TAG_EVENT_ID);
                String eventName = c.getString(TAG_EVENT_NAME);

                // creating new HashMap
                HashMap<String, String> map = new HashMap<String, String>();

                map.put(TAG_EVENT_ID, eventID);
                map.put(TAG_EVENT_NAME, eventName);

                arrayEventList.add(map);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * Inserts the parsed data into the listview.
     */
    private void updateList() {
        ListAdapter adapter = new SimpleAdapter(this, arrayEventList,
                R.layout.single_event_layout, new String[] { TAG_EVENT_ID, TAG_EVENT_NAME}, new int[] { R.id.event_id, R.id.event_name });

        setListAdapter(adapter);

        ListView lv = getListView();    
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                // do something
            }
        });
    }

    public class LoadEvents extends AsyncTask<String, String, String> {

        JSONParser jParser = new JSONParser();

        // check for success tag
        int status;
        String accesstoken ;
        String kioskid ;


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EventListActivity.this);
            pDialog.setMessage("Loading Events...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        @Override
        protected String doInBackground(String... arg0) {


            this.accesstoken = sharedPref.getString("accesstoken", null);
            this.kioskid = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

            try {
                // building parameters for Logout
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                params.add(new BasicNameValuePair("accesstoken", accesstoken));
                params.add(new BasicNameValuePair("kioskid", kioskid));
                Log.d("request!", "Starting");

                // getting product details by HTTPRequest
                JSONObject json = jParser.makeHttpRequest(EVENT_LIST_URL,"POST",params);

                // checking your log for JSON response
                Log.d("Loding Events Attemp", json.toString());

                // assign status to JSON "status" tag
                status = json.getInt(TAG_STATUS);
                if (status == 1){
                    // print in console success message + JSON response message
                    Log.d("Events Loaded Successfully",json.toString());


                    updateJSONdata();

                    return json.getString(TAG_MESSAGE);
                }else{
                    // print in console failure message + JSON response message
                    Log.d("Faild loding Events!", json.getString(TAG_MESSAGE));

                    return json.getString(TAG_MESSAGE);

                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;

        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            pDialog.dismiss();
            updateList();
        }
    }
}

更新3

JSONParser类

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 {
            // Construct the client and the HTTP request.
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            // Execute the POST request and store the response locally.
            HttpResponse httpResponse = httpClient.execute(httpPost);

            // Extract data from the response.
            HttpEntity httpEntity = httpResponse.getEntity();

            // Open an inputStream with the data content.
            is = httpEntity.getContent();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // Create a BufferedReader to parse through the inputStream.
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);

            // Declare a string builder to help with the parsing.
            StringBuilder sb = new StringBuilder();
            // Declare a string to store the JSON object data in string form.
            String line = null;

            // Build the string until null.
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }

            // Close the input stream.
            is.close();
            // Convert the string builder data to an actual string.
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try to 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;
    }

    // function get json from url
    // by making HTTP POST or GET mehtod
    public JSONObject makeHttpRequest(String loginUrl, String method,
            List<NameValuePair> params) {
        // making HTTP Request
        try {
            // check for request method
            if(method == "POST"){
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(loginUrl);
                httpPost.setEntity(new UrlEncodedFormEntity(params));
                HttpResponse httpResponse = httpClient.execute(httpPost);

                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }else 
                // check for request method
                if(method == "GET"){
                    DefaultHttpClient httpClient = new DefaultHttpClient();
                    String paramString = URLEncodedUtils.format(params, "utf-8");
                    loginUrl += "?" + paramString;
                    HttpGet httpGet = new HttpGet(loginUrl);
                    HttpResponse httpResponse = httpClient.execute(httpGet);
                    HttpEntity httpEntity = httpResponse.getEntity();
                    is = httpEntity.getContent();
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException 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 (IOException e) {
                Log.d("Buffer Error","Error Converting Reesult "+e.toString());
            }

        // try parse the string to JSON Object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error Parsing data" + e.toString());
        }

        // return JSON String
        return jObj;
    }

}

single_event_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/gradient"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
    android:background="@drawable/post_border_style"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/box"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="2dp"
        android:background="@drawable/post_background_style"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:src="@drawable/tapway_event_logo" />

        <LinearLayout
            android:id="@+id/box"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:orientation="vertical"
            android:padding="5dp" >

            <TextView
                android:id="@+id/event_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:paddingBottom="2dip"
                android:paddingLeft="5dp"
                android:paddingTop="6dip"
                android:textColor="#333"
                android:textSize="16sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/event_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingBottom="2dip"
                android:paddingLeft="8dp"
                android:textColor="#888" >
            </TextView>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

event_list_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/gradient" >

    <LinearLayout
        android:id="@+id/top_layover"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:background="@drawable/blue_gradient"
        android:orientation="horizontal" >

        <TextView
            style="@style/BlackText"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="@string/event_list"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </LinearLayout>

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/top_layover"
        android:background="#fff"
        android:divider="@android:color/transparent"
        android:scrollbars="none" />

</RelativeLayout>

2 个答案:

答案 0 :(得分:0)

错误消息Value <!DOCTYPE> of type java.lang.String cannot be converted to JSONObject表示您没有从服务器获得JSON响应,而是标记文档,很可能是错误页面。

您可以尝试在Android外执行请求以检查它是否正常工作,或者您可以将您的流程分为两个步骤:

  1. 从Web服务获取文本响应到字符串,并Log它。
  2. 将该字符串解析为JSON
  3. 这样,在解析失败之前,您将获得响应日志,因此您将获得更多信息。

答案 1 :(得分:0)

感谢大家的回复

我发现了错误

实际上它只是传递错误参数的错误

实际上,在Web服务器中存在错误,应该有2种访问令牌 一个用于登录,另一个用于所选事件 但是当我选择一个事件时,实现会更改登录到事件访问令牌

的附件

之前我正在处理特定的事件ID而没有完成与事件相关的其他事情,这就是为什么我没有注意到这些变化

现已解决问题

长话短说 守则是正确的

再次感谢