首页 > 解决方案 > Android Studio:应用程序未保存到数据库/从数据库读取

问题描述

所以我的应用程序是一个二维码扫描仪。目前它将读取一个二维码并将其显示给用户。我想让它也将此结果保存到数据库中,然后继续从中读取。目前它没有最后两个,我正在努力找出导致问题的原因 - 保存到数据库或从数据库中读取。

我的数据库代码是这样的:

public class Database {
    private static final String DATABASE_NAME = "QRCodeScanner";
    private static final int DATABASE_VERSION = 1;
    private static final String TABLE_NAME = "codes";

    private OpenHelper mDbHelper;
    private SQLiteDatabase mDb;
    private final Context dbContext;

    private static final String DATABASE_CREATE =
            "CREATE TABLE " + TABLE_NAME + " (" +
                    "codeid INTEGER PRIMARY KEY AUTOINCREMENT, " +
                    "code TEXT NOT NULL);";

    public Database(Context ctx) {
        this.dbContext = ctx;
    }

    public Database open() throws SQLException {
        mDbHelper = new OpenHelper(dbContext);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        mDbHelper.close();
    }

    public boolean createUser(String code) {
        ContentValues initialValues = new ContentValues();
        initialValues.put("codes", code);

        return mDb.insert(TABLE_NAME, null, initialValues) > 0;
    }


    public ArrayList<String[]> fetchUser(String code) throws SQLException {

        ArrayList<String[]> myArray = new ArrayList<String[]>();

        int pointer = 0;

        Cursor mCursor = mDb.query(TABLE_NAME, new String[] {"codeid", "code",
                        }, "code LIKE '%" + code + "%'", null,
                null, null, null);

        int codeNameColumn = mCursor.getColumnIndex("code");


        if (mCursor != null){
            if (mCursor.moveToFirst()){
                do {
                    myArray.add(new String[3]);
                    myArray.get(pointer)[0] = mCursor.getString(codeNameColumn);
                    pointer++;
                } while (mCursor.moveToNext());
            } else {
                myArray.add(new String[3]);
                myArray.get(pointer)[0] = "NO RESULTS";
                myArray.get(pointer)[1] = "";
            }
        }

        return myArray;

    }

    public ArrayList<String[]> selectAll() {

        ArrayList<String[]> results = new ArrayList<String[]>();


        int counter = 0;

        Cursor cursor = this.mDb.query(TABLE_NAME, new String[] { "codeid", "codes" }, null, null, null, null, "codeid");

        if (cursor.moveToFirst()) {
            do {
                results.add(new String[3]);
                results.get(counter)[0] = cursor.getString(0);
                counter++;
            } while (cursor.moveToNext());
        }
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }

        return results;
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
        }

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

我的主要java代码是这个。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private Button Scan;
private ArrayList<String[]> viewall;
private TextView QR_output;
private IntentIntegrator ScanCode;
private ListView lv;
private ArrayList Search = new ArrayList();
ArrayList<String[]> searchResult;

Database dbh;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // this caused an error on earlier APKs which made the app switch from 17 to 27
    setContentView(R.layout.activity_main);

    // Defines the Scan button
    Scan = findViewById(R.id.Scan);
    // defines the output for text
    QR_output = findViewById(R.id.QR_Output);

    // looks for the user clicking "Scan"
    Scan.setOnClickListener(this);

    ScanCode = new IntentIntegrator(this);
    // Means the scan button will actually do something
    Scan.setOnClickListener(this);

    lv = findViewById(R.id.list);

    dbh = new Database(this);
    dbh.open();

}

public void displayAll(View v){

    Search.clear();
    viewall = dbh.selectAll();
    String surname = "", forename = "";

    for (int count = 0 ; count < viewall.size() ; count++) {
        code = viewall.get(count)[1];
        Search.add(surname + ", " + forename);
    }
    ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            Search);

    lv.setAdapter(arrayAdapter);
}




// will scan the qr code and reveal its secrets
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
    if (result != null) {
        // if an empty QR code gets scanned it returns a message to the user
        if (result.getContents() == null) {
            Toast.makeText(this, "This QR code is empty.", Toast.LENGTH_LONG).show();
        } else try {
            // converts the data so it can be displayed
            JSONObject obj = new JSONObject(result.getContents());
            // this line is busted and does nothing
            QR_output.setText(obj.getString("result"));
        } catch (JSONException e) {
            e.printStackTrace();
                String codes = result.getContents();
                boolean success = false;

                success = dbh.createUser(codes);
            // outputs the data to a toast
            Toast.makeText(this, result.getContents(), Toast.LENGTH_LONG).show();
        }
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

@Override
public void onClick(View view) {
    // causes the magic to happen (It initiates the scan)
    ScanCode.initiateScan();
}

}

标签: javaandroiddatabasesqlite

解决方案


您的问题很可能与该行有关initialValues.put("codes", code);,因为根据您的表定义,没有称为代码的列,而是列名似乎是代码

因此,使用initialValues.put("code", code);可以很好地解决问题。

附加的

强烈建议您在整个代码中为所有命名项(表、列、视图触发器等)定义并随后使用常量,因此值将始终相同。

例如

private static final String DATABASE_NAME = "QRCodeScanner";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "codes";
public static final String COLUMN_CODEID = "codeid"; //<<<<<<<<< example note making public allows the variable to be used elsewhere
public static final String COLUMN_CODE = "code";   //<<<<<<<<<< another example

private OpenHelper mDbHelper;
private SQLiteDatabase mDb;
private final Context dbContext;

private static final String DATABASE_CREATE =
        "CREATE TABLE " + TABLE_NAME + " (" +
                COLUMN_CODEID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + //<<<<<<<<<<
                COLUMN_CODE + " TEXT NOT NULL);"; //<<<<<<<<<<

........ other code omitted for brevity

public boolean createUser(String code) {
    ContentValues initialValues = new ContentValues();
    initialValues.put(COLUMN_CODE, code); //<<<<<<<<<< CONSTANT USED

    return mDb.insert(TABLE_NAME, null, initialValues) > 0;
}

在从 Cursor 提取数据时不使用硬编码的列偏移量,而是使用 Cursor getColumnIndex方法提供偏移量,您也可能会遇到更少的问题。

例如,而不是:-

results.get(counter)[0] = cursor.getString(0);

最好使用:-

results.get(counter)[0] = cursor.getString(cursor.getColumnIndex(COLUMN_CODEID));

推荐阅读