0

I am trying to create a graph from my sqlite values for example here Date vs Weight. Later on I will add Date vs Fat etc. But the apps forced close by the phone with these Logcat:

08-19 21:58:50.313 25858-25858/example.christopher.bd E/AndroidRuntime: FATAL EXCEPTION: main Process: example.christopher.bd, PID: 25858 java.lang.RuntimeException: Unable to start activity ComponentInfo{example.christopher.bd/example.christopher.bd.VIewGraph}: java.lang.NullPointerException: Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference at com.jjoe64.graphview.series.DataPoint.(DataPoint.java:45) at example.christopher.bd.VIewGraph.onCreate(VIewGraph.java:48) at android.app.Activity.performCreate(Activity.java:7136) at android.app.Activity.performCreate(Activity.java:7127) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

activity to show the graph:

package example.christopher.bd;

import android.database.Cursor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class VIewGraph extends AppCompatActivity {

    LineGraphSeries<DataPoint> series;
    DatabaseHelper mDatabaseHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_graph);
        mDatabaseHelper = new DatabaseHelper(this);

        String y;
        Float z;
        Date d1;
        Cursor data = mDatabaseHelper.readEntry();
        int rows = data.getCount();
        data.moveToFirst();

        GraphView graph = (GraphView) findViewById(R.id.graph11);
        series = new LineGraphSeries<DataPoint>();

        for(int i = 0;  i <rows; i++){
            data.moveToNext();
            String x = data.getString(2);
            y = data.getString(3);
            z = Float.parseFloat(y);
            Date date1 = null;
            try {
                date1 = new SimpleDateFormat("dd/MM/yyyy").parse(x);
            } catch (Exception e) {
                e.printStackTrace();
            }

            series.appendData(new DataPoint(date1, z), true, 25);
        }
        graph.addSeries(series);

        graph.getGridLabelRenderer().setNumHorizontalLabels(3);
        graph.getGridLabelRenderer().setHumanRounding(false);

    }
}

Here is the code for databasehelper

package example.christopher.bd;


import android.app.DatePickerDialog;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.icu.util.Calendar;
import android.util.Log;
import android.view.View;
import android.widget.TextView;


public class DatabaseHelper extends SQLiteOpenHelper{

private static final String TAG = "DatabaseHelper";

private static final String TABLE_NAME = "BodyData";
private static final String COL1 = "ID";
private static final String COL2 = "tdate";
private static final String COL2a = "ttime";
private static final String COL3 = "weight";
private static final String COL4 = "fat";
private static final String COL5 = "hydration";
private static final String COL6 = "muscle";
private static final String COL7 = "bone";
//private static final String COL8 = "time";

private TextView mDisplayDate;
private DatePickerDialog.OnDateSetListener mDateSetListener;

public DatabaseHelper(Context context) {
    super(context, TABLE_NAME, null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {
    String createTable = " CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, tdate string, ttime string, weight float, fat float, hydration float, muscle float, bone float)";
    //String createTable = " CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, tday integer, tmonth integer, tyear integer, weight float, fat float, hydration float, muscle float, bone float)";
    db.execSQL(createTable);
}

@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
    db.execSQL(" DROP TABLE IF EXISTS " + TABLE_NAME);
    onCreate(db);
}
public boolean addData(String tdate, String ttime, String weight, String fat, String hydration, String muscle, String bone) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.put(COL2, tdate);
    contentValues.put(COL2a, ttime);
    contentValues.put(COL3, weight);
    contentValues.put(COL4, fat);
    contentValues.put(COL5, hydration);
    contentValues.put(COL6, muscle);
    contentValues.put(COL7, bone);
    //contentValues.put(COL8, time);
    long result = db.insert(TABLE_NAME,null ,contentValues);
    if(result == -1)
        return false;
    else
        return true;

}

public Cursor getData(){
    SQLiteDatabase db = this.getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_NAME;
    Cursor data = db.rawQuery(query, null);
    return data;
}

public void deleteAll()
{
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_NAME,null,null);
    db.execSQL("delete from "+ TABLE_NAME);
    db.close();
}

public Cursor readEntry(){
    SQLiteDatabase db = this.getWritableDatabase();

    String[] allColumns = new String[]{
            DatabaseHelper.COL1,
            DatabaseHelper.COL2,
            DatabaseHelper.COL2a,
            DatabaseHelper.COL3,
            DatabaseHelper.COL4,
            DatabaseHelper.COL5,
            DatabaseHelper.COL6,
            DatabaseHelper.COL7,
    };

    Cursor c = db.query(DatabaseHelper.TABLE_NAME, allColumns, null, null, null, null, null);
    if (c != null) {
        c.moveToFirst();
    }
    return c;
}
}

activity to log the data (date, weight etc)

package example.christopher.bd;

import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.icu.util.Calendar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

public class Logging extends AppCompatActivity {

private static final String TAG = "Logging";

DatabaseHelper mDatabaseHelper;
EditText editWeight, editFat, editHydration, editMuscle, editBone, editTime, editASD;
private Button button2;
private TextView mDisplayDate, mDisplayTime;
private DatePickerDialog.OnDateSetListener mDateSetListener;
private TimePickerDialog.OnTimeSetListener mTimeSetListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_logging);
    button2 = (Button) findViewById(R.id.button2);
    mDisplayDate = (TextView) findViewById(R.id.tvDate);
    mDatabaseHelper = new DatabaseHelper(this);
    mDisplayTime = (TextView) findViewById(R.id.tvTime);

    editWeight = (EditText) findViewById(R.id.editWeight);
    editFat = (EditText) findViewById(R.id.editFat);
    editHydration = (EditText) findViewById(R.id.editHydration);
    editMuscle = (EditText) findViewById(R.id.editMuscle);
    editBone = (EditText) findViewById(R.id.editBone);

    mDisplayDate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH);
            int day = cal.get(Calendar.DAY_OF_MONTH);

            DatePickerDialog dialog = new DatePickerDialog(
                    Logging.this,
                    android.R.style.Theme_Holo_Light_Dialog_MinWidth,
                    mDateSetListener,
                    year,month,day);
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            dialog.show();

        }
    });

    mDateSetListener = new DatePickerDialog.OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker datePicker, int year, int month, int day) {
            month = month + 1;
            Log.d(TAG, "onDateSet: mm/dd/yyyy: " + day + "/" + month + "/" + year);

            String date = day + "/" + month + "/" + year;
            mDisplayDate.setText(date);
        }
    };

    mDisplayTime.setOnClickListener(new View.OnClickListener() {
                                        @Override
                                        public void onClick(View view) {
                                            Calendar mTime = Calendar.getInstance();
                                            int mHour = mTime.get(Calendar.HOUR_OF_DAY);
                                            int mMinute = mTime.get(Calendar.MINUTE);

                                            TimePickerDialog timePickerDialog = new TimePickerDialog(Logging.this,
                                                    new TimePickerDialog.OnTimeSetListener() {

                                                        @Override
                                                        public void onTimeSet(TimePicker view, int hourOfDay,
                                                                              int minute) {

                                                            mDisplayTime.setText(hourOfDay + ":" + minute);
                                                        }
                                                    }, mHour, mMinute, true);
                                            timePickerDialog.show();
                                        }
                                    });

    LogData();
}

public void LogData(){
    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            boolean isInserted = mDatabaseHelper.addData(
                    mDisplayDate.getText().toString(),
                    mDisplayTime.getText().toString(),
                    editWeight.getText().toString(),
                    editFat.getText().toString(),
                    editHydration.getText().toString(),
                    editMuscle.getText().toString(),
                    editBone.getText().toString()
            );
            if (isInserted == true)
                Toast.makeText(Logging.this, "Data Inserted", Toast.LENGTH_LONG).show();
            else
                Toast.makeText(Logging.this, "Data not Inserted", Toast.LENGTH_LONG).show();
        }
    });
}


}

Can anyone help me?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

2 Answers2

0

It looks like you have made changes to the columns of the table (COL2a instead of COL8)
If this is the case, did you uninstall the app from the device/emulator where you test it?
If not you must.
The table schema dos not change every time you make changes in onCreate() of DatabaseHelper class. onCreate() is executed when the db does not exist.
Now a logical problem:
In your activity's onCreate() you execute:

data.moveToFirst();

So the cursor data is pointing at its 1st row.
Then in the 1st line of the for loop you execute:

data.moveToNext();

So the cursor data is pointing at its 2nd row (if there is a 2nd row).
So you miss the 1st row's data for sure.
But since the number of iterations is equal as the number of rows the last iteration will fetch null data!
Suggestion move data.moveToNext(); as the last statement of the for loop.

  • Your suggestion is implemented. Now, I have logged 4 rows of data but nothing shown in the GraphView only grid 0 to 1 on both X and Y axis. Here is the logcat 08-21 22:10:11.798 5545-5557/example.christopher.bd W/SQLiteConnectionPool: A SQLiteConnection object for database '/data/user/0/example.christopher.bd/databases/BodyData' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed. 08-21 22:10:11.798 5545-5557/example.christopher.bd W/System: A resource failed to call close. – Christopher Go Aug 21 '18 at 14:09
  • @ChristopherGo Your question was about a `java.lang.NullPointerException`. Now this is solved. You must post another question for the new issue, providing all the necessary code and data. –  Aug 21 '18 at 14:14
0

java.lang.NullPointerException: Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference

means that you are calling/the code you are using is calling getTime() on a Date object that is null.

In more detail

Attempt to invoke virtual method 'long java.util.Date.getTime()' on a null object reference at com.jjoe64.graphview.series.DataPoint.(DataPoint.java:45) at example.christopher.bd.VIewGraph.onCreate(VIewGraph.java:48)

means that this was initiated in VIewGraph.java on line 48.

Just above that there is a try-catch block to catch problems in parsing a date, but you don't check was the Date object non-null in the end. Any error is just ignored. You then feed this null Date object to series in series.appendData(new DataPoint(date1, z), true, 25);

A quick fix would be to change

try {
    date1 = new SimpleDateFormat("dd/MM/yyyy").parse(x);
} catch (Exception e) {
    e.printStackTrace();
}

series.appendData(new DataPoint(date1, z), true, 25);

..to...

try {
    date1 = new SimpleDateFormat("dd/MM/yyyy").parse(x);
    series.appendData(new DataPoint(date1, z), true, 25);
} catch (Exception e) {
    e.printStackTrace();
}
Markus Kauppinen
  • 3,025
  • 4
  • 20
  • 30
  • With your suggestion and mTak's suggestion, my apps now is not crashing but the graphview didn't show any point or line. Only grid with 0 to 1 on both X and Y axis. Here is the logcat 08-21 22:10:11.798 5545-5557/example.christopher.bd W/SQLiteConnectionPool: A SQLiteConnection object for database '/data/user/0/example.christopher.bd/databases/BodyData' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed. 08-21 22:10:11.798 5545-5557/example.christopher.bd W/System: A resource failed to call close. – Christopher Go Aug 21 '18 at 14:08
  • Alright, that's at least some progress. Of course you should check (maybe debug) if the date conversion ever works. If there's actually a bug there, you'll never get any data to the graph. The leaked connection might be more of a warning than a severe error, but of course you should close any resources you don't need anymore. I haven't played around with SQLite myself recently, so won't comment any more on that. – Markus Kauppinen Aug 21 '18 at 14:22
  • how can I check whether the date conversion is works or not? – Christopher Go Aug 21 '18 at 14:27
  • There's of course [debugging](https://developer.android.com/studio/debug/) and [logging](https://developer.android.com/studio/debug/am-logcat). You can set breakpoints or add logs to interesting branches of your code and if necessary add temporary code blocks just for the breakpoint or log. Breakpoints make sense for unexpected scenarios, like when the code enters the `catch` block and logging might make sense to demonstrate that the code works as you expect. If you have a log just _after_ `date1 = new SimpleDateFormat("dd/MM/yyyy").parse(x);` it's only printed out if there was no exception. – Markus Kauppinen Aug 21 '18 at 18:07