2012-03-29 11 views
0

Ich habe endlich meine Login-Anwendung mit meiner Online-Datenbank funktioniert. Ich folgte this Tutorial. Während ich es debuggte und es mit meinem Online-SQL-dB funktionierte, vermied ich das Problem von NetworkonMainThreadException, indem ich meine MinSDK auf '3' heruntersetzte. Offensichtlich erhalte ich den Fehler erneut, wenn ich ihn wieder auf 13+ stoße. Wie also könnte ich diese Klassen überarbeiten, um die Ausnahme zu vermeiden? Es scheint, als müsste ich viel mehr als ein oder zwei einfache Methoden modifizieren, richtig?Code nacharbeiten, um NetworkonMainThreadException zu vermeiden

Neben LoginActivity gibt es auch RegisterActivity und DashboardActivity, aber diese sind LoginActivity sehr ähnlich.

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; 
    } 

} 

DatabaseHandler:

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

Fazit ist, dass Sie Ihren Code in einen separaten Thread verschieben müssen. Sie können dies mithilfe einer von Ihnen erstellten AsyncTask-Klasse erreichen, die den gesamten Netzwerkcode in der doInBackground-Methode enthält. Dann wird alles, was mit der Benutzeroberfläche zu tun hat, in Ihrer onPostExecute-Methode aufgerufen. Es gibt viele gute Beispiele zum Erstellen einer AsyncTask – dymmeh

Antwort

1

Sie sollten nichts auf dem Main (UI) -Thread tun, das viel Zeit in Anspruch nimmt oder eine unsichere Zeit benötigt, wie zum Beispiel Netzwerkarbeit. Sie müssen Ihre Quelle ändern, damit jede Netzwerkaktivität in einen anderen Thread gelangt. Eine sehr gute Lösung hierfür ist die Verwendung von AsyncTask. Auf diese Weise wird jede Abfrage oder was auch immer Sie ausführen möchten, im Hintergrund ausgeführt und blockiert nicht die Benutzeroberfläche, wodurch diese Ausnahme nicht erzeugt wird. Hier wird beschrieben:

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

Beachten Sie, dass selbst wenn Sie erfolgreich sind, die Vernetzung auf dem UI-Thread zu tun, Ihre Anwendung wird höchstwahrscheinlich einfrieren.

+0

Oh ja, ich kann die Langsamkeit erkennen, wenn ich loggen oder registrieren, sichtbar. Ich wusste von Anfang an, dass ich AsyncTask verwenden müsste, wie ich es in meinem Android-Buch erfahren habe, das auf Honeycomb basiert. Ich denke, meine Frage ist, finde ich einen Weg, um all diesen Code in eine einzige Methode, DoInBackground? – Davek804

+0

Grundsätzlich haben AsyncTask 3 Hauptmethoden, onPreExecute, doInBackGround und onPostExecute. In der Regel sollten Sie die Initialisierung durchführen und die erforderlichen Daten vom Benutzeroberflächenthread in onPreExecute abrufen. Sie sollten das Netzwerk und die Verarbeitung in den Daten im DoInBackground ausführen, und Sie sollten interagieren und die Ergebnisse in onPostExecute festlegen. Ich denke, es gibt keinen strengen Algorithmus, um einfachen Code in AsyncTasks zu konvertieren, da jeder Code anders ist und etwas anderes macht, also müssen Sie etwas nacharbeiten :) – hundeva

Verwandte Themen