如何修复FATAL EXCEPTION:AsyncTask#1 doinbackground?

时间:2016-09-16 03:17:01

标签: android android-asynctask

我是Android编程的新手,我无法确定哪个触发了错误。有人可以向我解释错误以及如何摆脱错误吗?

我有这个错误:

09-16 10:09:05.529: E/AndroidRuntime(26221): FATAL EXCEPTION: AsyncTask #1
09-16 10:09:05.529: E/AndroidRuntime(26221): java.lang.RuntimeException: An error occured while executing doInBackground()
09-16 10:09:05.529: E/AndroidRuntime(26221):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.lang.Thread.run(Thread.java:841)
09-16 10:09:05.529: E/AndroidRuntime(26221): Caused by: java.lang.NullPointerException
09-16 10:09:05.529: E/AndroidRuntime(26221):    at com.databaseaar.Login_new$AttemptLogin.doInBackground(Login_new.java:82)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at com.databaseaar.Login_new$AttemptLogin.doInBackground(Login_new.java:1)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
09-16 10:09:05.529: E/AndroidRuntime(26221):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
09-16 10:09:05.529: E/AndroidRuntime(26221):    ... 4 more
09-16 10:09:06.459: E/WindowManager(26221): Activity com.databaseaar.Login_new has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{42c25fb0 V.E..... R......D 0,0-684,192} that was originally added here
09-16 10:09:06.459: E/WindowManager(26221): android.view.WindowLeaked: Activity com.databaseaar.Login_new has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{42c25fb0 V.E..... R......D 0,0-684,192} that was originally added here
09-16 10:09:06.459: E/WindowManager(26221):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:452)
09-16 10:09:06.459: E/WindowManager(26221):     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:258)
09-16 10:09:06.459: E/WindowManager(26221):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:73)
09-16 10:09:06.459: E/WindowManager(26221):     at android.app.Dialog.show(Dialog.java:287)
09-16 10:09:06.459: E/WindowManager(26221):     at com.databaseaar.Login_new$AttemptLogin.onPreExecute(Login_new.java:66)
09-16 10:09:06.459: E/WindowManager(26221):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
09-16 10:09:06.459: E/WindowManager(26221):     at android.os.AsyncTask.execute(AsyncTask.java:534)
09-16 10:09:06.459: E/WindowManager(26221):     at com.databaseaar.Login_new$1.onClick(Login_new.java:49)
09-16 10:09:06.459: E/WindowManager(26221):     at android.view.View.performClick(View.java:4475)
09-16 10:09:06.459: E/WindowManager(26221):     at android.view.View$PerformClick.run(View.java:18786)
09-16 10:09:06.459: E/WindowManager(26221):     at android.os.Handler.handleCallback(Handler.java:730)
09-16 10:09:06.459: E/WindowManager(26221):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-16 10:09:06.459: E/WindowManager(26221):     at android.os.Looper.loop(Looper.java:137)
09-16 10:09:06.459: E/WindowManager(26221):     at android.app.ActivityThread.main(ActivityThread.java:5419)
09-16 10:09:06.459: E/WindowManager(26221):     at java.lang.reflect.Method.invokeNative(Native Method)
09-16 10:09:06.459: E/WindowManager(26221):     at java.lang.reflect.Method.invoke(Method.java:525)
09-16 10:09:06.459: E/WindowManager(26221):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
09-16 10:09:06.459: E/WindowManager(26221):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
09-16 10:09:06.459: E/WindowManager(26221):     at dalvik.system.NativeStart.main(Native Method)

这是我的类Login_new和asynctask:

的代码
package com.databaseaar;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


     public class Login_new extends Activity implements OnClickListener{
        private EditText user, pass;
        private Button bLogin;
        private ProgressDialog pDialog;

        JSONParser jsonParser = new JSONParser(); 

        private static final String LOGIN_URL = "http://xxxx.com/login_new2.php"; 
        private static final String TAG_SUCCESS = "success"; 
        private static final String TAG_MESSAGE = "message";
        public static final String KEY_USERNAME ="username";

        protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.login2);
            user = (EditText)findViewById(R.id.ET_email); 
            pass = (EditText)findViewById(R.id.ET_password);
            bLogin = (Button)findViewById(R.id.btnLogin); 
            //bLogin.setOnClickListener(Login_new.this); 

        bLogin.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            // TODO Auto-generated method stub 
            switch (v.getId()) { 
            case R.id.btnLogin:
                new AttemptLogin().execute();
            default:
                break;
            }}
            });
        }

        class AttemptLogin extends AsyncTask<String, String, String> {
            // public static final String KEY_USERNAME = null;
            boolean failure = false;

             protected void onPreExecute() {
                 super.onPreExecute(); 
                 pDialog = new ProgressDialog(Login_new.this); 
                 pDialog.setMessage("Attempting for login..."); 
                 pDialog.setIndeterminate(false); 
                 pDialog.setCancelable(true); 
                 pDialog.show(); 
             }

            @Override
            protected String doInBackground(String... args) {
                int success;
                String username = user.getText().toString(); 
                String password = pass.getText().toString();
                try {
                    List<NameValuePair> params = new ArrayList<NameValuePair>(); 
                    params.add(new BasicNameValuePair("username", username)); 
                    params.add(new BasicNameValuePair("password", password));

                     Log.d("request!", "starting");

                     JSONObject json = jsonParser.makeHttpRequest(LOGIN_URL, "POST", params);
                     Log.d("Login attempt", json.toString());

                    // success tag for json 
                     success = json.getInt(TAG_SUCCESS); 
                     if (success == 1) { 
                         Log.d("Successfully Login!", json.toString()); 

                     Intent ii = new Intent(Login_new.this,MainActivity.class);
                     ii.putExtra(KEY_USERNAME, username);
                     finish();
                     startActivity(ii);

                     return json.getString(TAG_MESSAGE);
                     }else {

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

        protected void onPostExecute(String message) {
            pDialog.dismiss(); 
            if (message != null){ 
                Toast.makeText(Login_new.this, message, Toast.LENGTH_LONG).show(); 
                } 
            } }}

PHP代码:

       <?php
 $con=mysqli_connect("xxxx","xxxx","xxxx","xxxx");

  $password=$_POST["password"];
  $username=$_POST["username"];

if (!empty($_POST)) { 
if (empty($_POST['username']) || empty($_POST['password'])) {
$response["success"] = 0;
$response["message"] = "One or both of the fields are empty .";
}
$query = " SELECT * FROM login WHERE username = '$username'and password='$password'";

$sql1=mysql_query($query);
$row = mysql_fetch_array($sql1);

if (!empty($row)) {
$response["success"] = 1;
 $response["message"] = "You have been sucessfully login";
 die(json_encode($response));
 }else{
 $response["success"] = 0;
 $response["message"] = "invalid username or password ";
 die(json_encode($response));
 }}
  else{
  $response["success"] = 0;
  $response["message"] = " One or both of the fields are empty ";
    die(json_encode($response));
    }
mysql_close();
?>

我的JSON httpRequest

public JSONObject makeHttpRequest(String url, String method, List<NameValuePair> params) {
    // Making HTTP Request
    try {
        // check for request method
        if (method == "POST") {
            // request method is POST
            // defaultHTTPClient
            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 (method == "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 parse the string to a JSON object
    try {
        jsonObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    return jsonObj;
}

新错误日志cat:

    09-08 08:30:14.854: E/Response(2297): <br />
09-08 08:30:14.854: E/Response(2297): <b>Deprecated</b>:  mysql_query(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in <b>/home/u747670603/public_html/login_new2.php</b> on line <b>14</b><br />
09-08 08:30:14.854: E/Response(2297): <br />
09-08 08:30:14.854: E/Response(2297): <b>Warning</b>:  mysql_query(): Access denied for user 'u747670603'@'10.2.1.25' (using password: NO) in <b>/home/u747670603/public_html/login_new2.php</b> on line <b>14</b><br />
09-08 08:30:14.854: E/Response(2297): <br />
09-08 08:30:14.854: E/Response(2297): <b>Warning</b>:  mysql_query(): A link to the server could not be established in <b>/home/u747670603/public_html/login_new2.php</b> on line <b>14</b><br />
09-08 08:30:14.854: E/Response(2297): <br />
09-08 08:30:14.854: E/Response(2297): <b>Warning</b>:  mysql_fetch_array() expects parameter 1 to be resource, boolean given in <b>/home/u747670603/public_html/login_new2.php</b> on line <b>15</b><br />
09-08 08:30:14.854: E/Response(2297): {"success":0,"message":"invalid username or password "}

4 个答案:

答案 0 :(得分:2)

正如Crash转储所示,它是在onPreExecute()方法中启动的progressDialog的问题。但是在doInBackground()方法中,在某些条件下启动一个活动而不关闭progressDialog。这导致崩溃转储中显示的窗口泄漏。

应该使用doInBackground()来完成网络或其他更难的任务。不应在此方法中调用与UI相关的API,因为此方法在不同的线程上运行(不在主GUI线程上)。因此,我建议您将启动新活动的代码移至onPostExecute()方法,并在启动新活动之前解除progressDialog。

以下是示例代码。

class AttemptLogin extends AsyncTask<String, String, String> {
    // public static final String KEY_USERNAME = null;
    boolean failure = false;
    String username, password;

     protected void onPreExecute() {
         super.onPreExecute(); 
         pDialog = new ProgressDialog(Login_new.this); 
         pDialog.setMessage("Attempting for login..."); 
         pDialog.setIndeterminate(false); 
         pDialog.setCancelable(true); 
         pDialog.show();

        username = user.getText().toString(); 
        password = pass.getText().toString(); 
     }

    @Override
    protected String doInBackground(String... args) {
        int success;

        try {
            List<NameValuePair> params = new ArrayList<NameValuePair>(); 
            params.add(new BasicNameValuePair("username", username)); 
            params.add(new BasicNameValuePair("password", password));

             Log.d("request!", "starting");

             return jsonParser.makeHttpRequest(LOGIN_URL, "POST", params).toString();
         } catch (Exception e) {
                return null;
         }
}

protected void onPostExecute(String message) {
    pDialog.dismiss(); 

    if (message != null) {
        Toast.makeText(Login_new.this, message, Toast.LENGTH_LONG).show(); 

        try {
             JSONObject object = new JSONObject(message);

             // success tag for json 
             int success = object.getInt(TAG_SUCCESS); 
             if (success == 1) { 
                 Log.d("Successfully Login!", json.toString()); 
                 Intent ii = new Intent(Login_new.this,MainActivity.class);
                 ii.putExtra(KEY_USERNAME, username);
                 startActivity(ii);
                 finish();
             }
         } catch (JSONException 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();

    /*
     * This line will print the server response. 
     * Check this response and make changes to the PHP&MySQL accordingly.
     * Post this response for further help
     */
    Log.e ("Response", json);
} catch (Exception e) {
    Log.e("Buffer error", "Error converting result" + e.toString());
}

修改 这是一个示例PHP登录脚本(在使用它们之前添加$ username,$ password赋值语句)     的login.php

require_once('Database.php');

$db = new Database();

$stmt = $db->prepare("SELECT * FROM login where username = :username AND password = :password");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();

if ($stmt->rowCount() == 1) {
       $result['status'] = 1;
       $result['msg'] = "Successfully logged in";
} else {
       $result['status'] = 0;
       $result['msg'] = "Invalid login credentials";
}

echo json_encode($result);

创建一个新的PHP类文件Database.php在其中添加以下代码。

<?php

class Database extends PDO {
    function __construct() {
        parent::__construct('mysql:host=localhost;dbname=dbName', 'username', 'password');     
        parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
}

不要忘记在上面的类构造函数中更改主机名,数据库名称,用户名和密码。

答案 1 :(得分:0)

为什么在开始活动之前完成()

Intent ii = new Intent(Login_new.this,MainActivity.class);
                     ii.putExtra(KEY_USERNAME, username);
                     finish();
                     startActivity(ii);

您的代码应

 Intent ii = new Intent(Login_new.this,MainActivity.class);
                         ii.putExtra(KEY_USERNAME, username);

                       startActivity(ii);

并在后期执行中执行完成();

像这样做你的代码。

 public class Login_new extends Activity implements OnClickListener{
    private EditText user, pass;
    private Button bLogin;
    private ProgressDialog pDialog;

    JSONParser jsonParser = new JSONParser(); 

    private static final String LOGIN_URL = "http://xxxx.com/login_new2.php"; 
    private static final String TAG_SUCCESS = "success"; 
    private static final String TAG_MESSAGE = "message";
    public static final String KEY_USERNAME ="username";

    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.login2);
        user = (EditText)findViewById(R.id.ET_email); 
        pass = (EditText)findViewById(R.id.ET_password);
        bLogin = (Button)findViewById(R.id.btnLogin); 
        //bLogin.setOnClickListener(Login_new.this); 

    bLogin.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
        // TODO Auto-generated method stub 
        switch (v.getId()) { 
        case R.id.btnLogin:
            new AttemptLogin().execute();
        default:
            break;
        }}
        });
    }

    class AttemptLogin extends AsyncTask<String, String, Boolean> {
        // public static final String KEY_USERNAME = null;
        boolean failure = false;

         protected void onPreExecute() {
             super.onPreExecute(); 
             pDialog = new ProgressDialog(Login_new.this); 
             pDialog.setMessage("Attempting for login..."); 
             pDialog.setIndeterminate(false); 
             pDialog.setCancelable(true); 
             pDialog.show(); 
         }

        @Override
        protected String doInBackground(String... args) {
            int success;
            String username = user.getText().toString(); 
            String password = pass.getText().toString();
            try {
                List<NameValuePair> params = new ArrayList<NameValuePair>(); 
                params.add(new BasicNameValuePair("username", username)); 
                params.add(new BasicNameValuePair("password", password));

                 Log.d("request!", "starting");

                 JSONObject json = jsonParser.makeHttpRequest(LOGIN_URL, "POST", params);
                 Log.d("Login attempt", json.toString());

                // success tag for json 
                 success = json.getInt(TAG_SUCCESS); 
                 if (success == 1) { 
                     Log.d("Successfully Login!", json.toString()); 

                 Intent ii = new Intent(Login_new.this,MainActivity.class);
                 ii.putExtra(KEY_USERNAME, username);
               startActivity(ii);
                 failure = false;
                 return json.getString(TAG_MESSAGE);
                 }else {

                   return json.getString(TAG_MESSAGE); 
               }
               } catch (JSONException e) {
                   e.printStackTrace();
            }
               return failur; 
    }

    protected void onPostExecute(boolean fail) {
        pDialog.dismiss(); 
        if (message == true){ 
            finish();
            Toast.makeText(Login_new.this, message, Toast.LENGTH_LONG).show(); 
            } 
        } }}

答案 2 :(得分:0)

原因是json.toString()有时根据您的服务器代码为空,因此您将获得NullPointerException。

删除该行

 Log.d("Login attempt", json.toString());
 Log.d("Successfully Login!", json.toString()); 

答案 3 :(得分:0)

将以下代码放在onPostExecute()而不是doInBackground()

Intent ii = new Intent(Login_new.this,MainActivity.class);
             ii.putExtra(KEY_USERNAME, username);
             finish();
             startActivity(ii);

原因是您正在尝试完成当前的activity并尝试启动新的activity,而progressdialog仍然显示这就是显示泄露的窗口错误的原因。并且doInBackground()方法也期待String作为回报。