Вопрос

[edit] Allow me to apologise for the convoluted and amateurish nature of the code. I've been trying to develop for Android for the past three months (before that I spent a good three months getting familiar with basic Java) and while I have the concepts of Activities, button pclicks and other basic stuff, getting into networking and AsyncTasks etc. so soon has been challening. Thanks to everyone for helping me out.

The application crashes when trying to enter data in the database. I am posting the LogCat below.

This is the class that extends SQLiteOpenHelper:

package com.example.jsonbourne;

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

public class DatabaseTask extends SQLiteOpenHelper {

private static final int DB_VERSION = 1;
private static final String DB_NAME = "Examplebase";
private static final String TABLE_USER = "User";

public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_SURNAME = "surname";
public static final String COLUMN_AGE = "age";

public DatabaseTask(Context context) {
    super(context, DB_NAME, null, DB_VERSION);

}

@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_USER_TABLE = "CREATE TABLE" + TABLE_USER + "("
            + COLUMN_ID + "INTEGER PRIMARY KEY" + COLUMN_NAME + " TEXT"
            + COLUMN_SURNAME + "TEXT" + COLUMN_AGE + "INTEGER" + ")";
    db.execSQL(CREATE_USER_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS" + TABLE_USER);
    onCreate(db);
}

public void addUser(User user) {
    ContentValues cvalues = new ContentValues();

    cvalues.put(COLUMN_NAME, user.getName());
    cvalues.put(COLUMN_SURNAME, user.getSurname());
    cvalues.put(COLUMN_AGE, user.getAge());

    SQLiteDatabase db = this.getWritableDatabase();

    db.insert(TABLE_USER, null, cvalues);
    db.close();

}

}

This is part of the AsyncTask in an Activity called GetJson:

                    for (int i = 0; i < jArray.length(); i++) {
                        JSONObject json = jArray.getJSONObject(i);
                        s = json.getString("name") + " "
                                + json.getString("surname") + " "
                                + ", Age:" + json.getString("age") + "\n";


                        JSONObject jsonExample = jArray.getJSONObject(0);
                        String name = jsonExample.getString("name");
                        String surname = jsonExample.getString("surname");
                        int age = jsonExample.getInt("age");



                        User userExample = new User(name, surname, age);



                        DatabaseTask dbtaskExample = new DatabaseTask(GetJson.this);
                        dbtaskExample.addUser(userExample);

As soon as the application tries to add the User instance in the database, I get a force close of the app. From my research on the subject, it seems like the context I pass to the DB class must be the problem.

LogCat follows:

03-11 03:10:41.347: W/dalvikvm(1396): threadid=11: thread exiting with uncaught  
exception (group=0xb1a33ba8)
03-11 03:10:41.367: E/AndroidRuntime(1396): FATAL EXCEPTION: AsyncTask #1
03-11 03:10:41.367: E/AndroidRuntime(1396): Process: com.example.jsonbourne, PID: 1396
03-11 03:10:41.367: E/AndroidRuntime(1396): java.lang.RuntimeException: An error occured  
while executing doInBackground()
03-11 03:10:41.367: E/AndroidRuntime(1396):     at   
android.os.AsyncTask$3.done(AsyncTask.java:300)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at  
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at  
java.lang.Thread.run(Thread.java:841)
03-11 03:10:41.367: E/AndroidRuntime(1396): Caused by: java.lang.NullPointerException
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
com.example.jsonbourne.DatabaseTask.addUser(DatabaseTask.java:50)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
com.example.jsonbourne.GetJson$1.doInBackground(GetJson.java:121)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
com.example.jsonbourne.GetJson$1.doInBackground(GetJson.java:1)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
android.os.AsyncTask$2.call(AsyncTask.java:288)
03-11 03:10:41.367: E/AndroidRuntime(1396):     at 
java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-11 03:10:41.367: E/AndroidRuntime(1396):     ... 4 more

I have tried to understand why I get a NullPointerException but the GetJson activity is declared in the manifest and, as far as I understand, I don't have to declare the DatabaseTask class in the manifest since it's not an Activity.

Any help would be hugely appreciated!

[edit] Adding the GetJson.java source code and the User.java source code as well as the UserList source code. I have removed the URL and IP codes from the GetJson.java file and replaced them with descriptions but rest assured that they send data back:

package com.example.jsonbourne;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

public class GetJson extends Activity {

    public ArrayList<String> sarray = new ArrayList<String>();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getData();

    }

    public ArrayList<String> getData() {

        try {
            new AsyncTask<Void, Void, Void>() {

                @Override
                protected Void doInBackground(Void... params) {

                    try {

                        URL jsonURL = new URL(URL TO CONNECT TO);

                        HttpURLConnection connection = (HttpURLConnection) jsonURL
                                .openConnection();

                        connection.connect();

                        int responseCode = connection.getResponseCode();
                        String responseC = Integer.toString(responseCode);

                        Log.d("CONNECTION STATUS RESPONSE", responseC);

                        InputStream inputStream = connection.getInputStream();

                        Reader reader = new InputStreamReader(inputStream);

                        int contentLength = connection.getContentLength();

                        char[] charArray = new char[contentLength];

                        reader.read(charArray);

                        String responseData = new String(charArray);

                        Log.d("RESPONSE DATA", responseData);

                        // second stage

                        String result = "";
                        InputStream isr = null;

                        HttpClient httpClient = new DefaultHttpClient();
                        HttpPost httppost = new HttpPost(
                                JSON.PHP URL);
                        HttpResponse response = httpClient.execute(httppost);
                        HttpEntity entity = response.getEntity();
                        isr = entity.getContent();

                        BufferedReader readerz = new BufferedReader(
                                new InputStreamReader(isr, "iso-8859-1"));
                        StringBuilder sb = new StringBuilder();
                        String line = null;

                        while ((line = readerz.readLine()) != null) {
                            sb.append(line + "\n");
                        }

                        isr.close();
                        result = sb.toString();

                        String s = "";

                        JSONArray jArray = new JSONArray(result);

                        for (int i = 0; i < jArray.length(); i++) {
                            JSONObject json = jArray.getJSONObject(i);
                            s = json.getString("name") + " "
                                    + json.getString("surname") + " "
                                    + ", Age:" + json.getString("age") + "\n";


                            JSONObject jsonExample = jArray.getJSONObject(0);
                            String name = jsonExample.getString("name");
                            String surname = jsonExample.getString("surname");
                            int age = jsonExample.getInt("age");



                            User userExample = new User(name, surname, age);



                            DatabaseTask dbtaskExample = new DatabaseTask(GetJson.this);
                            dbtaskExample.getWritableDatabase();
                            dbtaskExample.addUser(userExample);

                            Log.d("USER", userExample.toString());

                            Log.d("INSIDE FOR LOOP", s + "\n");
                            sarray.add(s);
                        }

                        // sarray.add(s);
                        Log.d("YEAH", s);

                    } catch (MalformedURLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        Log.d("NETWORK", "NETWORK ERROR");
                    } catch (JSONException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return null;

                }

            }.execute();
        } catch (Exception e) {
        }

        return sarray;

    }
}

This is the User.java code:

package com.example.jsonbourne;

public class User {

    private String name;
    private String surname;
    private int age;

    public User(String name, String surname, int age) {
        this.name = name;
        this.surname = surname;
        this.age = age;

    }

    public  String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public  int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return this.name + " " + this.surname + ", age " +  this.age ;
    }

}

Finally, here is the UserList.java class that gets the data from GetJson and adapts them to a ListView:

package com.example.jsonbourne;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class UserList extends Activity {

    @Override
    public void onCreate(Bundle firebug) {
        super.onCreate(firebug);
        setContentView(R.layout.list_user);

        ListView lv = (ListView) findViewById(R.id.listv);



        GetJson gj = new GetJson();

        ArrayList<String> al = gj.getData();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        }





        ArrayAdapter<String> adapter = new ArrayAdapter<String>(UserList.this,
                android.R.layout.simple_list_item_1, al);

        lv.setAdapter(adapter);
        Toast.makeText(this, "Synchronization complete", Toast.LENGTH_SHORT).show();
    }

}
Это было полезно?

Решение

public class GetJson extends Activity

and

new GetJson()

is the problematic combination. You cannot instantiate activities with new. Doing so will render them useless e.g. as a Context and that's what causes the NPE when this badly created activity is attempted to be used as a Context.

To fix it, remove the extends Activity and pass in a valid Context wherever it's needed.

For example,

private Context mContext;

// constructor
public GetJson(Context c) {
  mContext = c;
}

// ...

  .. new DatabaseTask(mContext);

Also add the missing whitespace between keywords and identifiers to the SQL in onCreate():

String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USER + "("
        + COLUMN_ID + " INTEGER PRIMARY KEY" + COLUMN_NAME + " TEXT"
        + COLUMN_SURNAME + " TEXT" + COLUMN_AGE + " INTEGER" + ")";

and onUpgrade():

db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);

Другие советы

You need to call getWritableDatabase() on db object

Try this

DatabaseTask dbtaskExample = new DatabaseTask(GetJson.this);
dbtaskExample.getWritableDatabase() ;
dbtaskExample.addUser(userExample);

When you call:

DatabaseTask dbtaskExample = new DatabaseTask(GetJson.this);
                        dbtaskExample.addUser(userExample);

Your query causes the error,

String CREATE_USER_TABLE = "CREATE TABLE" + TABLE_USER + "("
            + COLUMN_ID + "INTEGER PRIMARY KEY" + COLUMN_NAME + " TEXT"
            + COLUMN_SURNAME + "TEXT" + COLUMN_AGE + "INTEGER" + ")";  

you need spaces between table names, column names and datatypes and comma before the next column name......so your query should be:

String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USER + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY, " + COLUMN_NAME + " TEXT, "
            + COLUMN_SURNAME + " TEXT, " + COLUMN_AGE + " INTEGER" + ")";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top