繁体   English   中英

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

[英]Android app crashing while copying database

我有一个运行良好的应用程序。 我必须更新数据库,这需要删除数据库并重建数据库。 我删除数据库就好了。 但是,我无法读取和重建新数据库。 错误日志如下:

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();

我很抱歉。

感谢@CommonsWare在另一个帖子上,我得到了答案。 我在ListAllStops中的活动的onCreate之前调用MetrolinkDatabaseHelper:

private MetroLinkDatabaseHelper myHelper =
        MetroLinkDatabaseHelper.getInstance(this);

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

谢谢@CommonsWare。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM