Android应用程序在复制数据库时崩溃

时间:2015-08-28 18:31:12

标签: android database sqlite

我有一个工作正常的应用程序。我不得不更新数据库,这需要删除数据库并重建数据库。我删除了数据库就好了。但是我无法读取并重建新数据库。错误日志如下:

08-28 13:03:33.932  32378-32378/com.bkane56.practice.practiceapp D/AndroidRuntime﹕ Shutting down VM
08-28 13:03:33.933  32378-32378/com.bkane56.practice.practiceapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.bkane56.practice.practiceapp, PID: 32378
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.bkane56.practice.practiceapp/com.bkane56.practice.practiceapp.ListStopsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2250)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
            at android.app.ActivityThread.access$800(ActivityThread.java:155)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
            at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:268)
            at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
            at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
            at com.bkane56.practice.practiceapp.MetroLinkDatabaseHelper.createdatabase(MetroLinkDatabaseHelper.java:67)
            at com.bkane56.practice.practiceapp.MetroLinkDatabaseHelper.<init>(MetroLinkDatabaseHelper.java:54)
            at com.bkane56.practice.practiceapp.MetroLinkDatabaseHelper.getInstance(MetroLinkDatabaseHelper.java:40)
            at com.bkane56.practice.practiceapp.ListStopsActivity.<init>(ListStopsActivity.java:27)
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.Class.newInstance(Class.java:1606)
            at android.app.Instrumentation.newActivity(Instrumentation.java:1089)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2240)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
            at android.app.ActivityThread.access$800(ActivityThread.java:155)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)

数据库帮助程序中出现问题(在Debug上崩溃)。具体如下:

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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;


public class MetroLinkDatabaseHelper extends SQLiteOpenHelper {

    private Context mycontext;
    private String stopName;
    private String sqlQueryTimes;
    private String sqlQueryDepart;
    private static MetroLinkDatabaseHelper myInstance;

    private static String DB_PATH = "data/data/com.bkane56.practice.practiceapp/databases/";
    private static String DB_NAME = "metrolink2.db";
    public static SQLiteDatabase myDataBase;


    public static synchronized MetroLinkDatabaseHelper getInstance(Context context) {

//        Using a singleton to minmize the chance of opening multiple
//        decreasing any chance of memory leak
        if(myInstance == null) {
            myInstance = new MetroLinkDatabaseHelper(context);
        }
        return myInstance;
    }


    private MetroLinkDatabaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.mycontext = context;
        boolean dbexist = checkdatabase();
        if (dbexist) {
        } else {
            System.out.println("Database doesn't exist");
            try {
                createdatabase();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    //      Create (copy the original in assets) if not exist using copydatabase
    public void createdatabase() throws IOException {
        boolean dbexist = checkdatabase();
        if (dbexist) {
        } else {
            this.getReadableDatabase();
            try {
                copydatabase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    //     Check if the Android database has been created from attached database
    private boolean checkdatabase() {
        boolean checkdb = false;
        try {
            String myPath = DB_PATH + DB_NAME;
            File dbfile = new File(myPath);
            checkdb = dbfile.exists();
            if (!checkdb) {
                System.out.println("THE DATA BASE DOES NOT EXIST");
            }
        } catch (SQLiteException e) {
            System.out.println("Database doesn't exist");
        }

        return checkdb;
    }

    //    copies the data from the metroLink db in assets to data/data....metrolink.db
    public void copydatabase() throws IOException {

        // Open your local db as the input stream
        InputStream myinput = mycontext.getAssets().open(DB_NAME);
        String outfilename = DB_PATH + DB_NAME;

        // Open the empty db as the output stream
        OutputStream myoutput = new FileOutputStream(outfilename);

        // buffered reader to write new database
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myinput.read(buffer)) > 0) {
            myoutput.write(buffer, 0, length);
        }
        // Close the streams
        myoutput.flush();
        myoutput.close();
        myinput.close();
    }

    public static SQLiteDatabase open() {
        // Open the database
        String mypath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(mypath, null,
                SQLiteDatabase.OPEN_READONLY);
        return myDataBase;
    }

    public synchronized void close() {
        super.close();
        myDataBase.close();

    }

    public void delete() {
        //Delete Existing Database
        File mypath = new File(DB_PATH + DB_NAME);
        myDataBase.close();
        System.out.println("DELETING THE EXISTING DATABASE");
        myDataBase.deleteDatabase(mypath);
    }

当我调试时,它会转到:

this.getReadableDatabase();

行然后跳回到getInstance然后下一步崩溃整个事情。

我不认为它在listStopsActivity中,但无论如何我都会包含它:

package com.bkane56.practice.practiceapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextClock;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;


public class ListStopsActivity extends Activity {

    private Spinner lvMetroStop;
    private MetroLinkDatabaseHelper myHelper =
            MetroLinkDatabaseHelper.getInstance(this);
    private String routeColor;
    private String direction;
    private String stop;
    private ListView stopTimes;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_stops);

        populateStopsDb();

    }

    private void openDB() {

      myHelper.open();
    }

    private void closeDB() {
        myHelper.close();
    }


    private void populateStopsDb() {

        lvMetroStop = (Spinner) findViewById(R.id.metroStopList);
        List<String> metroStop = myHelper.getAllStops();

        // Create ArrayAdapter using the planet list.
        ArrayAdapter<String> listAdapter = new ArrayAdapter<>(this, R.layout.simplerow, metroStop);
        lvMetroStop.setAdapter(listAdapter);
    }

    public void populateTimesDB() {

        String dateTime = (new SimpleDateFormat("EEEE HH:mm:ss").format(Calendar.getInstance().getTime()));
        String[] dayTime = dateTime.split(" ");
        String weekDay = dayTime[0];
        String time = dayTime[1];

        String query = "SELECT st.arrival_time FROM routes r" +
                " JOIN trips t on t.route_id = r.route_id JOIN calendar c on c.service_id =t.service_id" +
                " JOIN stop_times st on st.trip_id = t.trip_id JOIN stops s on s.stop_id = st.stop_id" +
                " WHERE r.route_id LIKE \"12594" + routeColor + "\" AND s.stop_name LIKE \"" + stop +
                "\" AND t.direction_id = \"" + direction + "\" AND st.arrival_time >= \"" + time +
                "\" AND c." + weekDay + " = 1 ORDER BY st.arrival_time LIMIT 3;";

        stopTimes = (ListView) findViewById(R.id.lvStopTimes);
        List<String> metroStopTimes = myHelper.getStopTimes(query);

        // Create ArrayAdapter using the planet list.
        ArrayAdapter<String> listAdapter = new ArrayAdapter<>(this,
                R.layout.stop_time, metroStopTimes);
        stopTimes.setAdapter(listAdapter);

    }

    public void getStopName(View view) {

        lvMetroStop = (Spinner) findViewById(R.id.metroStopList);
        stopTimes = (ListView) findViewById(R.id.lvStopTimes);
        TextView stopName = (TextView) findViewById(R.id.tvStopVar);
        Button getStop = (Button) findViewById(R.id.btnGetTimest);
        TextClock myClock = (TextClock) findViewById(R.id.textClock);
        TextView thisStop = (TextView) findViewById(R.id.stop_time);
        Button reset = (Button) findViewById(R.id.btnGetNew);
        TextView header = (TextView) findViewById(R.id.open_stops_header);
        RadioGroup eastWest = (RadioGroup) findViewById(R.id.rgEastWest);
        RadioGroup redBule = (RadioGroup) findViewById(R.id.rgRedBlue);
        TextView blueRed = (TextView) findViewById(R.id.tvRouteColor);
        TextView westEast = (TextView) findViewById(R.id.tvDirection);
        RadioButton red = (RadioButton) findViewById(R.id.rbRed);
        RadioButton blue = (RadioButton) findViewById(R.id.rbBlue);
        RadioButton east = (RadioButton) findViewById(R.id.rbEast);
        RadioButton west = (RadioButton) findViewById(R.id.rbWest);


        header.setText("The Next 3 Stop Times Are");

//        gets the text from the list view (spinner)
        stop = lvMetroStop.getSelectedItem().toString();
        stopName.setText(stop);

//        set Visibilities
        stopTimes.setVisibility(View.VISIBLE);
        reset.setVisibility(View.VISIBLE);
        thisStop.setVisibility(View.VISIBLE);
        stopName.setVisibility(View.VISIBLE);
        myClock.setVisibility(View.VISIBLE);
        lvMetroStop.setVisibility(View.INVISIBLE);
        getStop.setVisibility(View.INVISIBLE);
        eastWest.setVisibility(View.INVISIBLE);
        redBule.setVisibility(View.INVISIBLE);
        blueRed.setVisibility(View.INVISIBLE);
        westEast.setVisibility(View.INVISIBLE);
        header.setText("The Current Time Is:");


//        set East/West and Red/Blue
        if (red.isChecked()) {
            routeColor = "R";
        } else {
            routeColor = "B";
        }
        if (east.isChecked()) {
            direction = "0";
        } else {
            direction = "1";
        }

        populateTimesDB();

    }

    public void resetGetStopName(View view) {

        TextView stopName = (TextView) findViewById(R.id.tvStopVar);
        TextClock myClock = (TextClock) findViewById(R.id.textClock);
        Button getStop = (Button) findViewById(R.id.btnGetTimest);
        TextView thisStop = (TextView) findViewById(R.id.stop_time);
        Button reset = (Button) findViewById(R.id.btnGetNew);
        TextView header = (TextView) findViewById(R.id.open_stops_header);
        RadioGroup eastWest = (RadioGroup) findViewById(R.id.rgEastWest);
        RadioGroup redBule = (RadioGroup) findViewById(R.id.rgRedBlue);
        TextView blueRed = (TextView) findViewById(R.id.tvRouteColor);
        TextView westEast = (TextView) findViewById(R.id.tvDirection);
        stopTimes = (ListView) findViewById(R.id.lvStopTimes);

//        set the header text and change visibility
        header.setText(R.string.open_list_of_stops);
        lvMetroStop.setVisibility(View.VISIBLE);
        getStop.setVisibility(View.VISIBLE);
        eastWest.setVisibility(View.VISIBLE);
        redBule.setVisibility(View.VISIBLE);
        blueRed.setVisibility(View.VISIBLE);
        westEast.setVisibility(View.VISIBLE);
        stopName.setVisibility(View.INVISIBLE);
        myClock.setVisibility(View.INVISIBLE);
        reset.setVisibility(View.INVISIBLE);
        thisStop.setVisibility(View.INVISIBLE);
        stopTimes.setVisibility(View.INVISIBLE);
        header.setText("Choose Your Station From List");

    }

    private final String[] RED_STOPS = new String[]{
            "LAMBERT MAIN TRML METROLINK STATION",
            "LAMBERT EAST TRML METROLINK STATION",
            "NORTH HANLEY METROLINK STATION",
            "UMSL NORTH METROLINK STATION",
            "ROCK ROAD METROLINK STATION",
            "WELLSTON METROLINK STATION",
            "DELMAR METROLINK STATION",
            "MEMORIAL HOSPITAL METROLINK STATION",
            "SWANSEA METROLINK STATION",
            "BELLEVILLE METROLINK STATION",
            "COLLEGE METROLINK STATION",
            "SHILOH-SCOTT METROLINK STATION"};

    private final String[] BLUE_STOPS = new String[]{
            "RICHMOND HEIGHTS METROLINK STATION",
            "CLAYTON METROLINK STATION",
            "BRENTWOOD METROLINK STATION",
            "MAPLEWOOD METROLINK STATION",
            "SUNNEN METROLINK STATION",
            "SHREWSBURY METROLINK STATION",
            "FORSYTH METROLINK STATION",
            "UMSL SOUTH METROLINK STATION",
            "SKINKER METROLINK STATION"};


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_list_stops, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

任何建议都将不胜感激。

编辑:对不起@Lal,我检查了一个不同的分支。正确的行号67是:

this.getReadableDatabase();

道歉。

1 个答案:

答案 0 :(得分:0)

感谢@CommonsWare在另一篇文章中我得到了答案。我在ListAllStops中活动的onCreate之前调用了MetrolinkDatabaseHelper:

private MetroLinkDatabaseHelper myHelper =
        MetroLinkDatabaseHelper.getInstance(this);

变量需要声明为类变量并在super.onCreate之后分配:

谢谢@CommonsWare。