2012-03-29 84 views
0

我終於得到了我的登錄應用程序與我的在線數據庫一起工作。我跟着this教程。在調試它並使其與我的在線SQL dB一起工作時,通過將我的minSDK設置爲'3',我避免了NetworkonMainThreadException的問題。很顯然,當我將它恢復到13+時,我再次收到錯誤。那麼我怎麼能夠重新修改這些類來避免這種異常呢?看起來我需要修改很多不止一個或兩個簡單的方法,對嗎?重做代碼以避免NetworkonMainThreadException

除了LoginActivity之外,還有RegisterActivity和DashboardActivity,但它們與LoginActivity非常相似。

LoginActivity:

package com.davekelley; 

import java.util.HashMap; 

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

import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 

import library.DatabaseHandler; 
import library.UserFunctions; 

public class LoginActivity extends Activity { 
    Button btnLogin; 
    Button btnLinkToRegister; 
    EditText inputEmail; 
    EditText inputPassword; 
    TextView loginErrorMsg; 

    // JSON Response node names 
    private static String KEY_SUCCESS = "success"; 
    private static String KEY_ERROR = "error"; 
    private static String KEY_ERROR_MSG = "error_msg"; 
    private static String KEY_UID = "uid"; 
    private static String KEY_NAME = "name"; 
    private static String KEY_EMAIL = "email"; 
    private static String KEY_CREATED_AT = "created_at"; 
    private String re; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.login); 

     // Importing all assets like buttons, text fields 
     inputEmail = (EditText) findViewById(R.id.loginEmail); 
     inputPassword = (EditText) findViewById(R.id.loginPassword); 
     btnLogin = (Button) findViewById(R.id.btnLogin); 
     btnLinkToRegister = (Button) findViewById(R.id.btnLinkToRegisterScreen); 
     loginErrorMsg = (TextView) findViewById(R.id.login_error); 

     // Login button Click Event 
     btnLogin.setOnClickListener(new View.OnClickListener() { 

      public void onClick(View view) { 
       String email = inputEmail.getText().toString(); 
       String password = inputPassword.getText().toString(); 
       UserFunctions userFunction = new UserFunctions(); 
       JSONObject json = userFunction.loginUser(email, password); 

       // check for login response 
       try { 
        if (json.getString(KEY_SUCCESS) != null) { 
         loginErrorMsg.setText(""); 

         String res = json.getString(KEY_SUCCESS); 
         re = res; 
         if(Integer.parseInt(res) == 1){ 
          // user successfully logged in 
          // Store user details in SQLite Database 
          DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
          JSONObject json_user = json.getJSONObject("user"); 

          // Clear all previous data in database 
          userFunction.logoutUser(getApplicationContext()); 
          db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));       

          // Launch Dashboard Screen 
          Intent dashboard = new Intent(getApplicationContext(), DashboardActivity.class); 

          // Close all views before launching Dashboard 
          dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
          startActivity(dashboard); 

          // Close Login Screen 
          finish(); 
         }else{ 
          // Error in login 
          loginErrorMsg.setText("Incorrect username/password"); 
         } 
        } 
       } catch (NullPointerException e) { 
        e.printStackTrace(); 

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

      } 
     }); 

     // Link to Register Screen 
     btnLinkToRegister.setOnClickListener(new View.OnClickListener() { 

      public void onClick(View view) { 
       Intent i = new Intent(getApplicationContext(), 
         RegisterActivity.class); 
       startActivity(i); 
       finish(); 
      } 
     }); 
    } 
} 

UserFunctions:

package library; 
import java.util.ArrayList; 
import java.util.List; 

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

import android.content.Context; 

public class UserFunctions { 

    private JSONParser jsonParser; 

    // Testing in localhost using wamp or xampp 
    // use http://10.0.2.2/ to connect to your localhost ie http://localhost/ 
    private static String loginURL = "http://davidjkelley.net/android_api/"; 
    private static String registerURL = "http://davidjkelley.net/android_api/"; 

    private static String login_tag = "login"; 
    private static String register_tag = "register"; 

    // constructor 
    public UserFunctions(){ 
     jsonParser = new JSONParser(); 
    } 

    /** 
    * function make Login Request 
    * @param email 
    * @param password 
    * */ 
    public JSONObject loginUser(String email, String password){ 
     // Building Parameters 
     List<NameValuePair> params = new ArrayList<NameValuePair>(); 
     params.add(new BasicNameValuePair("tag", login_tag)); 
     params.add(new BasicNameValuePair("email", email)); 
     params.add(new BasicNameValuePair("password", password)); 
     JSONObject json = jsonParser.getJSONFromUrl(loginURL, params); 
     // return json 
     // Log.e("JSON", json.toString()); 
     return json; 
    } 

    /** 
    * function make Login Request 
    * @param name 
    * @param email 
    * @param password 
    * */ 
    public JSONObject registerUser(String name, String email, String password){ 
     // Building Parameters 
     List<NameValuePair> params = new ArrayList<NameValuePair>(); 
     params.add(new BasicNameValuePair("tag", register_tag)); 
     params.add(new BasicNameValuePair("name", name)); 
     params.add(new BasicNameValuePair("email", email)); 
     params.add(new BasicNameValuePair("password", password)); 

     // getting JSON Object 
     JSONObject json = jsonParser.getJSONFromUrl(registerURL, params); 
     // return json 
     return json; 
    } 

    /** 
    * Function get Login status 
    * */ 
    public boolean isUserLoggedIn(Context context){ 
     DatabaseHandler db = new DatabaseHandler(context); 
     int count = db.getRowCount(); 
     if(count > 0){ 
      // user logged in 
      return true; 
     } 
     return false; 
    } 

    /** 
    * Function to logout user 
    * Reset Database 
    * */ 
    public boolean logoutUser(Context context){ 
     DatabaseHandler db = new DatabaseHandler(context); 
     db.resetTables(); 
     return true; 
    } 

} 

數據庫處理器:

package library; 

import java.util.HashMap; 

import android.content.ContentValues; 
import android.content.Context; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 

public class DatabaseHandler extends SQLiteOpenHelper { 

    // All Static variables 
    // Database Version 
    private static final int DATABASE_VERSION = 1; 

    // Database Name 
    private static final String DATABASE_NAME = "android_api"; 

    // Login table name 
    private static final String TABLE_LOGIN = "login"; 

    // Login Table Columns names 
    private static final String KEY_ID = "id"; 
    private static final String KEY_NAME = "name"; 
    private static final String KEY_EMAIL = "email"; 
    private static final String KEY_UID = "uid"; 
    private static final String KEY_CREATED_AT = "created_at"; 

    public DatabaseHandler(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    // Creating Tables 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
     String CREATE_LOGIN_TABLE = "CREATE TABLE " + TABLE_LOGIN + "(" 
       + KEY_ID + " INTEGER PRIMARY KEY," 
       + KEY_NAME + " TEXT," 
       + KEY_EMAIL + " TEXT UNIQUE," 
       + KEY_UID + " TEXT," 
       + KEY_CREATED_AT + " TEXT" + ")"; 
     db.execSQL(CREATE_LOGIN_TABLE); 
    } 

    // Upgrading database 
    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // Drop older table if existed 
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOGIN); 

     // Create tables again 
     onCreate(db); 
    } 

    /** 
    * Storing user details in database 
    * */ 
    public void addUser(String name, String email, String uid, String created_at) { 
     SQLiteDatabase db = this.getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put(KEY_NAME, name); // Name 
     values.put(KEY_EMAIL, email); // Email 
     values.put(KEY_UID, uid); // Email 
     values.put(KEY_CREATED_AT, created_at); // Created At 

     // Inserting Row 
     db.insert(TABLE_LOGIN, null, values); 
     db.close(); // Closing database connection 
    } 

    /** 
    * Getting user data from database 
    * */ 
    public HashMap<String, String> getUserDetails(){ 
     HashMap<String,String> user = new HashMap<String,String>(); 
     String selectQuery = "SELECT * FROM " + TABLE_LOGIN; 

     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(selectQuery, null); 
     // Move to first row 
     cursor.moveToFirst(); 
     if(cursor.getCount() > 0){ 
      user.put("name", cursor.getString(1)); 
      user.put("email", cursor.getString(2)); 
      user.put("uid", cursor.getString(3)); 
      user.put("created_at", cursor.getString(4)); 
     } 
     cursor.close(); 
     db.close(); 
     // return user 
     return user; 
    } 

    /** 
    * Getting user login status 
    * return true if rows are there in table 
    * */ 
    public int getRowCount() { 
     String countQuery = "SELECT * FROM " + TABLE_LOGIN; 
     SQLiteDatabase db = this.getReadableDatabase(); 
     Cursor cursor = db.rawQuery(countQuery, null); 
     int rowCount = cursor.getCount(); 
     db.close(); 
     cursor.close(); 

     // return row count 
     return rowCount; 
    } 

    /** 
    * Re crate database 
    * Delete all tables and create them again 
    * */ 
    public void resetTables(){ 
     SQLiteDatabase db = this.getWritableDatabase(); 
     // Delete All Rows 
     db.delete(TABLE_LOGIN, null, null); 
     db.close(); 
    } 

} 

JSONParser:

package library; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import java.util.List; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.json.JSONException; 
import org.json.JSONObject; 

import android.util.Log; 

public class JSONParser { 

    static InputStream is = null; 
    static JSONObject jObj = null; 
    static String json = ""; 

    // constructor 
    public JSONParser() { 

    } 

    public JSONObject getJSONFromUrl(String url, List<NameValuePair> params) { 

     // Making HTTP request 
     try { 
      // 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(); 

     } 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"); 
       Log.v("err", line); 
      } 
      is.close(); 
      json = sb.toString(); 
      //this is the error 
      Log.e("JSON", "json"); 
     } 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; 

    } 
} 
+0

底線是你需要將你的代碼移動到一個單獨的線程中。您可以使用您創建的AsyncTask類來完成此操作,該類包含doInBackground方法中的所有網絡代碼。然後,在您的onPostExecute方法中將調用任何與UI相關的內容。有很多很好的例子來創建一個AsyncTask – dymmeh 2012-03-29 21:44:00

回答

1

您不應該在主要(UI)線程上做任何事情,這需要花費很多時間,或者需要不確定的時間,比如聯網。你將不得不修改你的源代碼,所以每個網絡活動都有不同的線索。一個非常好的解決方案是使用AsyncTask。這樣,每個查詢或任何你想做的事情,都會在後臺執行,而不會阻塞UI,因此不會產生該異常。這是詳細:

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

請注意,即使你成功做UI線程上的網絡,你的應用程序很可能會凍結。

+0

哦,是的,我可以檢測到緩慢,當我登錄或登記,明顯。我從一開始就知道我需要使用AsyncTask,因爲我在基於Honeycomb的Android書中瞭解到了它。我想我的問題是,我是否找到一種方法將所有這些代碼合併到一個方法doInBackground中? – Davek804 2012-03-29 21:52:56

+0

基本上,AsyncTask有3個主要方法,onPreExecute,doInBackGround和onPostExecute。通常,您將需要執行初始化,從onPreExecute中的UI線程獲取必要的數據,您應該在doInBackground中執行網絡和數據處理,並且應該在onPostExecute中交互並設置結果。我認爲沒有嚴格的算法將簡單的代碼轉換爲AsyncTasks,因爲每個代碼都是不同的,並且做了不同的事情,所以你將不得不做一些重做:) – hundeva 2012-03-30 06:26:35