【问题标题】:Android app works for 1 type of value of Json but not anotherAndroid 应用适用于 1 种类型的 Json 值,但不适用于另一种
【发布时间】:2018-02-05 17:27:16
【问题描述】:

我正在构建一个 android 应用程序,每当我向我的服务器发送一个 get 请求时,它都会返回 Json,例如:

{
    "status":"error",
    "error":"Username already exists."
}

或者当用户不存在时,电子邮件也不存在:

{
    "status":"ok",
    "cookie":"test16|1519060288|Jf8jEzJe8C7JJWmAxW6ViJbLKgsY1XuCH0OStT38vG2|d6489d623438870a08da717cc6f1851496c2e1e7c45557da7c8df8d1f80f1db4",
    "user_id":285
}

问题是,对于第二个 Json,一切正常,用户收到一封电子邮件,应用程序按其应有的方式运行。 但是当您尝试使用现有用户名注册时,一切都会崩溃, 从我的 logcat 中,我发现它在 BufferReader 声明行或这一行中崩溃:if (responseCode == HttpsURLConnection.HTTP_OK),如果我选择包含它。 到底是什么原因可能是我的代码接受了"status" = "ok" 的一种 Json,而不是当它等于“错误”时?

这是我的异步任务:

    public class Register extends AsyncTask<String, Void, RegisterData> {


    @Override
    protected void onPreExecute() {
        p= ProgressDialog.show(SignUpActivity.this,getString(R.string.Authenticating),getString(R.string.loadingPleaseWait),true);
        p.setCancelable(true);
        p.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        p.setMessage(getString(R.string.loadingDotDotDot));
        p.show();

    }

    @Override
    protected RegisterData doInBackground(String... params)
    {
        String str=params[0];
        String res=performPostCall(str);
        Log.d("ress", res);
        if (Response.matches(""))
        {
            register.cancel(true);
        }
        RegisterData regi = null;
        try
        {

            JSONObject json_data = new JSONObject(res);
            String Status = json_data.getString("status");
            String error = "null";
            if (Status.equals("ok"))
                error = "null";
            else
                error= json_data.getString("error");
            Log.d("coo", error);
            regi= new RegisterData(Status,error);
            Log.d("stat", regi.getStatus());
        }
        catch(JSONException e)
        {

        }
        Log.d("aa", res);
        return regi;
    }

    @Override
    protected void onPostExecute(RegisterData result) {
        Log.d("stat2", result.getStatus());

        if (result.getStatus().equals("ok")) {
            check = true;
            Toast.makeText(SignUpActivity.this, R.string.SuccessfulLogin, Toast.LENGTH_LONG).show();
            finish();
        }
        else
        {
            check = false;
            Toast.makeText(SignUpActivity.this, R.string.WrongUserOrPass, Toast.LENGTH_LONG).show();
        }
        p.dismiss();

    }
}

这是执行 http 请求的类:

    public String performPostCall(String requestURL) {

    URL url;
    Log.d("nugi", "Got Here 1");
    String response = "";
    try {
        String str=getPostDataString();
        Log.d("nugi", "Got Here 2");

        url = new URL(requestURL+str);
        Log.d("nugi", url.toString());

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(15000);
        conn.setConnectTimeout(15000);
        conn.setRequestMethod("GET");
        conn.setDoInput(true);
        conn.setDoOutput(true);

        int responseCode=conn.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            Log.d("nugi", "Got Here 3");
            String line;
            BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream(), "iso-8859-1"));
        Log.d("nugi", "Got Here 4");
        while ((line=br.readLine()) != null) {
                response+=line;
                Log.d("nugi", "Got Here 5");
            }
        Log.d("nugi", response);

        Response = response;
        }
        /*else {
            response="";
            Response = response;

        }*/
    } catch (Exception e) {
        e.printStackTrace();
    }

    return response;
}

这是我的 logcat 错误:

02-05 17:24:28.075 5378-5394/com.example.negev.peulibraryv201 E/Surface:getSlotFromBufferLocked:未知缓冲区:0xab38aea0 02-05 17:24:28.082 5378-5394/com.example.negev.peulibraryv201 E/Surface:getSlotFromBufferLocked:未知缓冲区:0xab38a5e0 02-05 17:24:28.332 5378-5378/com.example.negev.peulibraryv201 E/WindowManager: android.view.WindowLeaked: Activity com.example.negev.peulibraryv201.SignUpActivity 已泄露窗口 com.android.internal.policy。 PhoneWindow$DecorView{bd0880e V.E...... R......D 0,0-729,322} 最初添加在这里 在 android.view.ViewRootImpl.(ViewRootImpl.java:368) 在 android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299) 在 android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85) 在 android.app.Dialog.show(Dialog.java:319) 在 android.app.ProgressDialog.show(ProgressDialog.java:116) 在 android.app.ProgressDialog.show(ProgressDialog.java:99) 在 com.example.negev.peulibraryv201.SignUpActivity$Register.onPreExecute(SignUpActivity.java:156) 在 android.os.AsyncTask.executeOnExecutor(AsyncTask.java:604) 在 android.os.AsyncTask.execute(AsyncTask.java:551) 在 com.example.negev.peulibraryv201.SignUpActivity.onClick(SignUpActivity.java:87) 在 android.view.View.performClick(View.java:5198) 在 android.view.View$PerformClick.run(View.java:21147) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5417) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

谢谢!

【问题讨论】:

  • 问题不是 Json 而是你的 Dialog。当您遇到错误时,您会尝试将其关闭
  • 什么意思?在哪里?并且不应该有任何错误 Json 应该始终写入 BufferReader 不是吗?谢谢!
  • 你的错误是E/WindowManager: android.view.WindowLeaked: Activity com.example.negev.peulibraryv201.SignUpActivity has leaked window
  • @Eselfar 当您的应用在到达驳回线之前崩溃时也会发生这种情况。所以这里可能发生的是,应用程序由于其他问题而崩溃,可能是NullPointer & 窗口被泄露。这就是为什么我要求 OP 检查 responseCode 以防出现错误和其他错误的日志

标签: java android android-studio


【解决方案1】:

根据我们在评论中的谈话,实际问题出在其他地方。您的 API 在返回错误时返回状态 404,而您的应用仅检查状态代码 200 (HTTP_OK)。你需要在这里处理一些东西,我没有测试过,但你可以在performPostCall中尝试以下操作:

        int responseCode=conn.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            Log.d("nugi", "Got Here 3");
            String line;
            BufferedReader br=new BufferedReader(new 
            InputStreamReader(conn.getInputStream(), "iso-8859-1"));
            Log.d("nugi", "Got Here 4");
            while ((line=br.readLine()) != null) {
                response+=line;
                Log.d("nugi", "Got Here 5");
            }
            Log.d("nugi", response);

            Response = response;
        } else {
            String line;
            BufferedReader br=new BufferedReader(new 
            InputStreamReader(conn.getErrorStream(), "iso-8859-1"));
            Log.d("nugi", "Got Here 4");
            while ((line=br.readLine()) != null) {
                response+=line;
                Log.d("nugi", "Got Here 5");
            }
            Log.d("nugi", response);

            Response = response;
        }

注意 conn.getErrorStream() 在 else 条件下。你可能需要玩它,因为我不记得了。现在的问题是,当状态不是 200 时,您将无法获取 inputStream 中的数据

【讨论】:

  • 非常感谢,确实是这个问题!
  • 顺便说一句,你的解决方案比我的好得多,我不知道你能做到这一点!我会删除我的,你的工作完美。
【解决方案2】:

您的问题可能是窗口泄漏。您正在调用finish,就在关闭进度之前,状态为OK

    if (result.getStatus().equals("ok")) {
        check = true;
        Toast.makeText(SignUpActivity.this, R.string.SuccessfulLogin, Toast.LENGTH_LONG).show();
        finish(); // <<<< finish() is called before dismissing the progress
    }
    else
    {
        check = false;
        Toast.makeText(SignUpActivity.this, R.string.WrongUserOrPass, Toast.LENGTH_LONG).show();
    }
    p.dismiss();

你可以这样做:

    if (result.getStatus().equals("ok")) {
        check = true;
        Toast.makeText(SignUpActivity.this, R.string.SuccessfulLogin, Toast.LENGTH_LONG).show();
        p.dismiss(); // <<<< call dismiss first 
        finish(); // <<<< then call finish()
    }
    else
    {
        check = false;
        Toast.makeText(SignUpActivity.this, R.string.WrongUserOrPass, Toast.LENGTH_LONG).show();
        p.dismiss();
    }

【讨论】:

  • 问题是当状态不是“ok”时项目失败,你怎么看?当状态为“ok”时,一切正常...谢谢!
【解决方案3】:

尝试替换:

d.dismiss();

通过

if (d.isShowing()){
   d.dismiss();
}

【讨论】:

    【解决方案4】:

    好的,在 Sandip Soni 的帮助下,我设法解决了这个问题,或者更准确地说,他做到了,所以功劳是他的。 问题是我的 api 在其响应代码整数中给出了 404,并且由于某种原因没有让我读取 Json。 解决方案是在此处添加“if”语句:

         int responseCode=conn.getResponseCode();
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            Log.d("nugi", "Got Here 3");
            String line;
            BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream(), "iso-8859-1"));
        Log.d("nugi", "Got Here 4");
        while ((line=br.readLine()) != null) {
                response+=line;
                Log.d("nugi", "Got Here 5");
            }
        Log.d("nugi", response);
    
        Response = response;
        }
        else { <<<<<<<<<<< //if statement here
            response="";
            Response = response;
    
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    return response;
    

    }

    然后检查它是否为空并激活显示“用户名或电子邮件已在使用中”的 toast。 非常感谢你们!这是一个非常棒的论坛。

    【讨论】:

      猜你喜欢
      • 2014-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多