当我的Android应用程序在我的服务器上调用我的API时,为什么会得到空响应?

时间:2016-04-12 14:18:32

标签: android json android-spinner

我有一个调用信息的android应用程序并将其显示为列表。

当您从微调器中选择日期时,我有一个微调器,您可以获得与该日期相关的信息。

在应用程序首次加载时,它会自动调用今天的信息。

这是我在我的主要活动中使用的代码,用于创建我的微调器并用元素填充它并处理每个项目的点击次数:

// Spinner element
spinner = (Spinner) v.findViewById(R.id.spinner);

// Spinner click listener
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
      public void onItemSelected(AdapterView<?> parent, View view,
                                       int position, long id) {
                // On selecting a spinner item
                //String item = parent.getItemAtPosition(position).toString();
                switch(position){
                    case 3:
                        if (JsonUtils.isNetworkAvailable(getActivity())) {
                            list.clear();
                            new MyTask().execute(Config.SERVER_URL + "/banko_api.php?d_o=-1");
                        } else {
                            Toast.makeText(getActivity(), getResources().getString(R.string.failed_connect_network), Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case 4:
                        if (JsonUtils.isNetworkAvailable(getActivity())) {
                            list.clear();
                            new MyTask().execute(Config.SERVER_URL + "/banko_api.php?d_o=0");
                        } else {
                            Toast.makeText(getActivity(), getResources().getString(R.string.failed_connect_network), Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case 5:
                        if (JsonUtils.isNetworkAvailable(getActivity())) {
                            list.clear();
                            new MyTask().execute(Config.SERVER_URL + "/banko_api.php?d_o=1");
                        } else {
                            Toast.makeText(getActivity(), getResources().getString(R.string.failed_connect_network), Toast.LENGTH_SHORT).show();
                        }
                        break;
                    default:
                        if (JsonUtils.isNetworkAvailable(getActivity())) {
                            list.clear();
                            new MyTask().execute(Config.SERVER_URL + "/banko_api.php?d_o=0");
                        } else {
                            Toast.makeText(getActivity(), getResources().getString(R.string.failed_connect_network), Toast.LENGTH_SHORT).show();
                        }
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });



        Calendar calendar = Calendar.getInstance();
        Date today = calendar.getTime();

        calendar.add(Calendar.DAY_OF_YEAR, -1);
        Date yesterday = calendar.getTime();

        calendar = Calendar.getInstance();

        calendar.add(Calendar.DAY_OF_YEAR, 1);
        Date tomorrow = calendar.getTime();


        DateFormat dateFormat = new SimpleDateFormat("dd/MM EEE");
        String todayAsString = dateFormat.format(today);
        String tomorrowAsString = dateFormat.format(tomorrow);
        String yesterdayAsString = dateFormat.format(yesterday);


        // Spinner Drop down elements
        List<String> categories = new ArrayList<String>();

        categories.add(yesterdayAsString);
        categories.add(todayAsString);
        categories.add(tomorrowAsString);

        // Creating adapter for spinner
        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(getContext(), R.layout.spinner_item, categories);


        dataAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        // attaching data adapter to spinner

        spinner.setAdapter(dataAdapter);

        spinner.setSelection(4);

问题:首次加载应用程序正在调用今天的数据(这是我的微调器中的默认选项)没有任何问题。 如果我在微调器中选择另一个元素,它也会毫无问题地调用相关数据。 现在,如果我想在微调器中选择返回今天的元素,即使启动时的应用程序从同一链接调用数据并获取数据,也不会从服务器带来任何数据。

我在日志中收到此消息: W/System.err: org.json.JSONException: Value [] of type org.json.JSONArray cannot be converted to JSONObject

我的Asynktask的onPostExcute包含以下代码:

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

            if (null != progressDialog && progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

            if (null == result || result.length() == 0) {
                Toast.makeText(getActivity(), getResources().getString(R.string.failed_connect_network), Toast.LENGTH_SHORT).show();
            } else {

                try {
                    Log.d("resultTT",result);
                    JSONObject mainJson = new JSONObject(result);
                    JSONArray jsonArray = mainJson.getJSONArray(JsonConfig.CATEGORY_ARRAY_NAME);
                    JSONObject objJson = null;
                    for (int i = 0; i < jsonArray.length(); i++) {

                        objJson = jsonArray.getJSONObject(i);
                        ItemMatch objItem = new ItemMatch();
                        objItem.setMatchId(objJson.getString(JsonConfig.Match_ID));
                        objItem.setMatchTournamentName(objJson.getString(JsonConfig.Match_LEAGUE_NAME));
                        objItem.setMatchTime(objJson.getString(JsonConfig.Match_TIME));
                        objItem.setMatchStatus(objJson.getString(JsonConfig.Match_STATUS));
                        objItem.setMatchLocalTeamName(objJson.getString(JsonConfig.Match_LOCALTEAM_NAME));
                        objItem.setMatchVisitorTeamName(objJson.getString(JsonConfig.Match_VISITORTEAM_NAME));
                        objItem.setMatchLocalTeamGoals(objJson.getString(JsonConfig.Match_LOCALTEAM_GOALS));
                        objItem.setMatchVisitorTeamGoals(objJson.getString(JsonConfig.Match_VISITORTEAM_GOALS));
                        objItem.setMatchBestOddPercent(objJson.getString(JsonConfig.Match_BEST_ODD_PERCENT));
                        objItem.setMatchBestOddResult(objJson.getString(JsonConfig.Match_BEST_ODD_RESULT));
                        list.add(objItem);
                    }

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


                for (int j = 0; j < list.size(); j++) {
                    object = list.get(j);

                    array_match_id.add(String.valueOf(object.getMatchId()));
                    str_match_id = array_match_id.toArray(str_match_id);

                    array_league_name.add(String.valueOf(object.getMatchTournamentName()));
                    str_league_name = array_league_name.toArray(str_league_name);

                    array_match_time.add(String.valueOf(object.getMatchTime()));
                    str_match_time = array_match_time.toArray(str_match_time);

                    array_match_status.add(String.valueOf(object.getMatchStatus()));
                    str_match_status = array_match_status.toArray(str_match_status);

                    array_match_localteam_name.add(object.getMatchLocalTeamName());
                    str_match_localteam_name = array_match_localteam_name.toArray(str_match_localteam_name);

                    array_match_visitorteam_name.add(object.getMatchVisitorTeamName());
                    str_match_visitorteam_name = array_match_visitorteam_name.toArray(str_match_visitorteam_name);

                    array_match_localteam_goals.add(object.getMatchLocalTeamGoals());
                    str_match_localteam_goals = array_match_localteam_goals.toArray(str_match_localteam_goals);

                    array_match_visitorteam_goals.add(object.getMatchVisitorTeamGoals());
                    str_match_visitorteam_goals = array_match_visitorteam_goals.toArray(str_match_visitorteam_goals);

                    array_match_best_odd_percent.add(object.getMatchBestOddPercent());
                    str_match_best_odd_percent = array_match_best_odd_percent.toArray(str_match_best_odd_percent);

                    array_match_best_odd_result.add(object.getMatchBestOddResult());
                    str_match_best_odd_result = array_match_best_odd_result.toArray(str_match_best_odd_result);
                }

                setAdapterToListView();
            }

在此代码的try部分中,您可以看到我记录结果以查看来自服务器的内容我只是得到这个:D/resultTT: []

并且正如您所见,try是在else部分内部,因此在本节的if语句中,我检查结果是null还是空;但是代码传递了它并输入了else语句,但仍显示返回的结果数组为空。

我想要一些帮助来找到这个空的返回数组背后的原因,即使它在启动时加载正常。为什么在我选择微调器中的任何元素然后回到默认(今天)元素后它不能获取信息?

更新:这是我的php side-server api代码

<?php

    include_once ('includes/variables.php');

    DEFINE ('DB_HOST', $host);
    DEFINE ('DB_USER', $user);   
    DEFINE ('DB_PASSWORD', $pass);
    DEFINE ('DB_NAME', $database);

    $mysqli = @mysql_connect (DB_HOST, DB_USER, DB_PASSWORD) OR die ('Could not connect to MySQL');
    @mysql_select_db (DB_NAME) OR die ('Could not select the database');

 ?>

<?php

    mysql_query("SET NAMES 'utf8'"); 
    $date_offset = mysql_real_escape_string($_GET[d_o]);
    //$date_offset = 0;
    if(empty($date_offset) || $date_offset == "0")
    {
        $date_offset_value = "0";
        $query="SELECT a.*, m.match_id, m.match_time, m.en_tournament_name FROM app_banko a inner join matches_of_comments m on m.match_id = a.match_id where a.date_offset = $date_offset_value limit 20";         
        $resouter = mysql_query($query);
    }
    else
    {
        $date_offset_value = $date_offset;  
        $query="SELECT a.*, m.match_id, m.match_time, m.en_tournament_name FROM app_banko a inner join matches_of_comments m on m.match_id = a.match_id where a.date_offset = $date_offset_value limit 20";         
        $resouter = mysql_query($query);
    }


    $set = array();

    $total_records = mysql_num_rows($resouter);
    if($total_records >= 1){

      while ($link = mysql_fetch_array($resouter, MYSQL_ASSOC)){

        $set['NewsApp'][] = $link;
      }
    }

     echo $val= str_replace('\\/', '/', json_encode($set)); 

?>

5 个答案:

答案 0 :(得分:4)

您的result字符串为空数组,但不是空字符串。空数组表示为以下字符串:

String result = "[]";

在这种情况下,result.length()等于2

解析JSON时,您需要知道解析的对象是Object类型还是Array类型。前者用大括号{}包裹,后者用方括号[]包裹。

以下一行:

JSONObject mainJson = new JSONObject(result);

应该是:

JSONArray mainJson = new JSONArray(result);

但我不能过分强调,如果你想要能够正确解析它,你需要知道你的API返回了什么。

编辑:

好吧,json_encode很难猜测是否应该使用JSON Array创建的空数组中创建JSON Object$set = array();。<登记/> 像在循环中一样向数组中添加对象使得json_encode显而易见的是它应该创建JSON Object。 我不知道你是否可以强制json_encode的行为,但最坏的情况是你可以检查自己数组是否为空,如果数组为空则返回""null

$set = array();

$total_records = mysql_num_rows($resouter);
if ($total_records >= 1) {
  while ($link = mysql_fetch_array($resouter, MYSQL_ASSOC)) {
    $set['NewsApp'][] = $link;
  }
  echo $val= str_replace('\\/', '/', json_encode($set)); 
} else {
  echo $val="";
}

答案 1 :(得分:4)

如果在期望对象时得到一个数组,那么对API的请求可能有问题。一种方法是弄清楚它在开发机器上设置Wireshark来嗅探和过滤流量。然后你可以看看你的请求是否有问题。

答案 2 :(得分:4)

response方法中onPostExecute参数的值可能包含字符串化 JSONArray ,而非 JSONObject

您始终可以使用以下方式对其进行测试:

try:
    JSONArray jsonArray = new JSONArray(result);
catch(JSONException e) {
    // String `result` is not an array. Parse it as a regular JSONObject.
}

测试wheter字符串是一个空的json数组(取决于它的格式,特别是当它可能包含一些白色字符时)检查它的长度可能是一个非常糟糕的主意。

这完全取决于如何确定您正在呼叫的API端点。

最后还有一个提示。如果您计划使用REST API,我强烈建议您使用:

  1. Retrofit - 允许您轻松定义访问API的接口,
  2. GSON - 自动转换Java模型的响应。

答案 3 :(得分:4)

请在try块状态下检查result.isEmpty(),这可能会解决您的问题。

答案 4 :(得分:4)

你无法直接获得字符串中的响应。它可以使用JSONObject和JSONArray。