Can't fetch data from SQLite database in AS - java

I'm creating a Quiz app in Android Studio, and so I created a Database that contains the questions. In the helper class I have a method getAllQuestions that transfers the questions from the database to an array list, so then I can extract the Questions in Main and setText in Buttons. However, while I run my app the buttons and the Question are empty, without the app throwing exceptions like nullpointer if the list itself was empty.
DB_Helper methods:
private void addQuestions(QuestionsDataBase Questions)
{
ContentValues cv = new ContentValues();
cv.put(QuestionTable.Column_Question,Questions.getQuestion());
cv.put(QuestionTable.Column_Option1,Questions.getOption1());
cv.put(QuestionTable.Column_Option2,Questions.getOption2());
cv.put(QuestionTable.Column_Option3,Questions.getOption3());
cv.put(QuestionTable.Column_Option4,Questions.getOption4());
cv.put(QuestionTable.Column_Correct_Ans,Questions.getQuestion());
db.insert(QuestionTable.Table_Name,null,cv);
}
public ArrayList getAllQuestions(){
ArrayList<QuestionsDataBase> questionsList = new ArrayList<>();
db = getReadableDatabase();
String[] Projection ={
QuestionTable._ID,
QuestionTable.Column_Question,
QuestionTable.Column_Option1,
QuestionTable.Column_Option2,
QuestionTable.Column_Option3,
QuestionTable.Column_Option4,
QuestionTable.Column_Correct_Ans
};
Cursor c = db.query(QuestionTable.Table_Name,
Projection,
null,
null,
null,
null,
null);
if(c.moveToFirst()){
do{
QuestionsDataBase questions = new QuestionsDataBase();
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Question)));
questions.setOption1(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option1)));
questions.setOption2(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option2)));
questions.setOption3(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option3)));
questions.setOption4(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option4)));
questions.setCorrectAns(c.getInt(c.getColumnIndexOrThrow(QuestionTable.Column_Correct_Ans)));
questionsList.add(questions);
questionsList.add(questions);
}while(c.moveToNext());
}
c.close();
return questionsList;
}
Methods in MainActivity:
private void fecthDB(){
DB_Helper db = new DB_Helper(this);
questionList = db.getAllQuestions();
startQuiz();
}
private void startQuiz()
{
questionTotalCount = questionList.size(); // the total amount of questions in the current quizactivity( is set to 10)
Collections.shuffle(questionList); // shuffle the questions form the database that are stored in QuestionList
showQuestions();
nextbutton.setOnClickListener(view -> {
if(!answered){
if(option1.isChecked() || option2.isChecked() || option3.isChecked() || option4.isChecked())
QuizOperations();
}
});
}
private void showQuestions() // Showing the question and the options from database
{
rbGroup.clearCheck();
if(questionCounter< questionTotalCount) // if not all the questions yet answered set text to new questions
{
currentQuestions = questionList.get(questionCounter);
questionCount.setText(currentQuestions.getQuestion());
option1.setText(currentQuestions.getOption1());
option2.setText(currentQuestions.getOption2());
option3.setText(currentQuestions.getOption3());
option4.setText(currentQuestions.getOption4());
questionCounter ++; // +1 to question counter
answered = false; // tye quiz is not yet completely answered while the current question is smaller then total
nextbutton.setText("Next");
questionCount.setText("Questions: " + questionCounter + "/" + questionTotalCount); // how many questions answered out of 10
}
else{// if all the questions are answered
handler.postDelayed(() -> {
Intent intent = new Intent(getApplicationContext(),QuizActivity.class); // open the next activity
}, 500); // wait for a half second
}
}

I believe you want to set other fields on your QuestionsDataBase object here rather than setQuestion() for each column in the database query:
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option1)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option2)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option3)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Option4)));
questions.setQuestion(c.getString(c.getColumnIndexOrThrow(QuestionTable.Column_Correct_Ans)));
Thanks, edited it. Now it shows the options, but doesn't show the question itself.
You are setting text to questionCount twice where the later overwrites the first one. Maybe the first one should set the question textview instead.

Related

How to resolve "no such column: date_addedDESC" error? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 months ago.
Improve this question
My audio player on phone is showing "SQLite exception" and crashed. It needs external storage permission but I don't have a memory card. How to resolve this error?
Exception:
android.database.sqlite.SQLiteException: no such column: date_addedDESC (Sqlite code 1 SQLITE_ERROR): , while compiling: SELECT _id, _display_name, duration, _size, album_id FROM audio WHERE ((is_pending=0) AND (is_trashed=0) AND (volume_name IN ( 'external_primary' ))) AND (date_addedDESC), (OS error - 2:No such file or directory)
Main activity :
private void fetchPlayer() {
//define a list to carry players
List<player> mPlayer = new ArrayList<> ();
Uri mediaStoreUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mediaStoreUri = MediaStore.Audio.Media.getContentUri (MediaStore.VOLUME_EXTERNAL);
}else{
mediaStoreUri = MediaStore.Audio.Media. EXTERNAL_CONTENT_URI;
}
// define projection
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.ALBUM_ID,
};
// order
String sortOrder = MediaStore.Audio.Media.DATE_ADDED + " DESC ";
// get the players
try (Cursor cursor = getContentResolver ().query (mediaStoreUri,projection,sortOrder,null,null)) {
// cache cursor indices
int idColumn = cursor.getColumnIndexOrThrow (MediaStore.Audio.Media._ID);
int nameColumn = cursor.getColumnIndexOrThrow (MediaStore.Audio.Media.DISPLAY_NAME);
int durationColumn = cursor.getColumnIndexOrThrow (MediaStore.Audio.Media.DURATION);
int sizeColumn = cursor.getColumnIndexOrThrow (MediaStore.Audio.Media.SIZE);
int albumColumn = cursor.getColumnIndexOrThrow (MediaStore.Audio.Media.ALBUM_ID);
//clear the previous loaded before adding loading again
while (cursor.moveToNext ()){
//get the values of a column for a given audio file
long id = cursor.getLong(idColumn );
String name = cursor.getString (nameColumn);
int duration = cursor.getInt (durationColumn);
int size = cursor.getInt (sizeColumn);
long albumId = cursor.getLong (albumColumn);
// player Uri
Uri uri = ContentUris.withAppendedId (MediaStore.Audio.Media.EXTERNAL_CONTENT_URI , id );
// album artwork uri
Uri albumArtWorkUri = ContentUris.withAppendedId (Uri.parse("content:// media/external/audio/albumart") , albumId);
// remove mp3 extension from players name
name = name.substring (0 , name.lastIndexOf ("."));
//player item
player player = new player (name , uri , albumArtWorkUri , size , duration , id );
//add player item to play list
mPlayer.add(player);
}
//display player
showPlayers(mPlayer);
}
}
private void showPlayers(List<player> mPlayer){
if(mPlayer.size () == 0){
Toast.makeText (this , "No Players" , Toast.LENGTH_SHORT ).show ();
return;
}
// save players
allPlayer.clear ();
allPlayer.addAll (mPlayer);
//update the tools bar title
String title = getResources ().getString (R.string.app_name) + "." + mPlayer.size ();
Objects.requireNonNull (getSupportActionBar ()).setTitle (title);
//layout manager
LinearLayoutManager layoutManager = new LinearLayoutManager (this);
recyclerView.setLayoutManager (layoutManager);
//players adapter
playerAdapter = new playerAdapter (this , mPlayer);
//set the adapter to recycleView
recyclerView.setAdapter (playerAdapter);
}
}
SortOrder is last parameter:
Cursor cursor = getContentResolver ().query (mediaStoreUri,projection,null,null,sortOrder)
ok I solve it's problem I just space in sortOrder variable and I just click:
1- Build
2- then Clean Project
3- and Rebuild Project
String sortOrder = MediaStore.Audio.Media.DATE_ADDED + " DESC ";
maybe to help any Developer

updating a tuple in a sqlite table in android studio

before voting down please read my question , which I have searched a lot but I couldn't find the answer yet, so I would appreciate if you give me hand to overcome the problem.
Actually I need to update a tuple in a table named "Demographics". But it seems my code does not work correctly, and in fact after running the app , I got the result "0" for updating which means nothing get updated.
12-21 12:34:54.190 2351-2367/? D/Update Result:: =0
I guess my problem is due to not pointing to the right row of the table based on Primary key. Actually when a user Register to my app the following things should happen:
1- Create a tuple in "Demographics" table --> username, password and email will be inserted. An auto increment primary key also constructed and inserted.
2- user logins , then he can complete rest of information in "Demographics" table. --> this MODIFICATION is the "update" process which I', asking.
Would you please tell me if the following codes are wrong or have any implicit error?
DemographicsCRUD.java
public long UpdateDemographics(Demographics_to demoId) {
//SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DataBaseHelper.lastName, demoId.getD_lastName());
values.put(DataBaseHelper.firstName, demoId.getD_firstName());
values.put(DataBaseHelper.dateOfBirth, demoId.getD_dateOfBirth())
long result = database.update(dbHelper.Demographics_Table, values,
WHERE_ID_EQUALS,
new String[]{String.valueOf(demoId.getD_patientID())});
Log.d("Update Result:", "=" + result);
// db.close();
return result;
}
here is where I call the above code:
private void updateDemographicsTable()
{
ep_demoId = new Demographics_to();
String ep_na = ep_name.getText().toString();
String ep_fa = ep_family.getText().toString();
.
.
.
ep_demoId.setD_dateOfBirth(ep_bd);
ep_demoId.setD_firstName(ep_na);
ep_demoId.setD_lastName(ep_fa);
}
#Override
protected Long doInBackground(Void... arg0) {
long result = ep_demoCRUD.UpdateDemographics(ep_demoId);
return result;
}
#Override
protected void onPostExecute(Long result) {
if (activityWeakRef.get() != null
&& !activityWeakRef.get().isFinishing()) {
if (result != -1)
Toast.makeText(activityWeakRef.get(), "Information Updated!",
Toast.LENGTH_LONG).show();
}}
Looks like whatever you are passing in as the patientID does not have a matching record in the database or the dataobject "Demographics_to" has the patient ID set incorrectly.

ParseObject does not create a row in table in my Database

I'm using this code to actually let the user send a questionand 4 answers (it's a long story), and storage it on my game database. This is the code I used, after seeing the docs and just the table doesn't get updated. I don't really know why
private void sendQuestion() {
ParseUser currentUser = ParseUser.getCurrentUser();
String role = currentUser.get("Role").toString();
if(role.equals("Founder"))
{
String questionText = mQuestion.getText().toString();
String[] answers = new String[4];
for(int i = 0; i < 4; i++) {
answers[i] = mAnswers[i].getText().toString();
}
ParseObject question = new ParseObject("Questions");
question.put("lang", mSelectedLang);
question.put("question", questionText);
for(int i = 0; i < 4; i++) question.put("answer" + (i+1), answers[i]);
question.put("enabled", true);
question.put("from", currentUser);
question.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
Log.d("MyApp", "Done");
}
});
}else
Log.d("MyApp", "Not founder");
}
This is what I get from the Logs
05-27 19:57:21.063 2307-2307/*************** D/MyApp﹕ Send question button pressed
05-27 19:57:21.530 2307-2307/*************** D/MyApp﹕ Done
Says it's done but the Table Questions is not updated, as said. Pay attention that both "lang" and "from" are relations fields, so I put there object and not simple values like Strings or Integer.
Why doesn't the table get updated?
Here you can look the official docs to save an object https://www.parse.com/docs/android/guide#objects-saving-objects
I self resolved changing the rows type from 'Relation' to 'Pointer', as I read here https://parse.com/questions/expected-relation_user-but-got-_user (didn't find it because it was asked for iOS but it's not about the wrong code).
Now it works.
I think you should change
question.put("from", currentUser);
with something like:
question.put("from", currentUser.getId()); // pass id of user, not object itself

How to randomly set text to buttons from SQLite without repetition?

I have a db imported to assets, and i read from it and randomly set text to buttons and a texview, with code below:
mDbHelper.open();
Cursor c = mDbHelper.getTestData();
List<Answer> labels = new ArrayList<Answer>();
labels.add(new Answer(c.getString(2), true));
labels.add(new Answer(c.getString(3), false));
labels.add(new Answer(c.getString(4), false));
labels.add(new Answer(c.getString(5), false));
Collections.shuffle(labels);
question.setText(c.getString(1));
bOdgovor1.setText(labels.get(0).option);
bOdgovor1.setTag(labels.get(0));
bOdgovor1.setOnClickListener(clickListener);
bOdgovor2.setText(labels.get(1).option);
bOdgovor2.setTag(labels.get(1));
bOdgovor2.setOnClickListener(clickListener);
bOdgovor3.setText(labels.get(2).option);
bOdgovor3.setTag(labels.get(2));
bOdgovor3.setOnClickListener(clickListener);
bOdgovor4.setText(labels.get(3).option);
bOdgovor4.setTag(labels.get(3));
bOdgovor4.setOnClickListener(clickListener);
Here's my TestAdapter code for db:
public Cursor getTestData()
{;
try
{
String sql ="SELECT * FROM tblPitanja ORDER BY RANDOM() LIMIT 1";
Cursor mCur = mDb.rawQuery(sql, null);
if (mCur!=null)
{
mCur.moveToNext();
}
return mCur;
}
catch (SQLException mSQLException)
{
Log.e(TAG, "getTestData >>"+ mSQLException.toString());
throw mSQLException;
}
}
It works perfectly when it comes to setting questions to buttons, but questions repeat. How to avoid that?
there are more approaches to solve your problem:
execute the sql-statement (without limiting) at the beginning and move to the next entry of the cursor when a quesion is answered correctly
buffer the questions which where already answered
the second approach could be done as follows:
first, change your method and sql, including a where-clause:
public Cursor getTestData(String whereClause)
{;
try
{
String sql ="SELECT * FROM tblPitanja WHERE 1 = 1 " + whereClause + " ORDER BY RANDOM() LIMIT 1";
[...]
second, buffer the already answered questions in your game-class:
add a LinkedList to your game-class
LinkedList<Long> mAnsweredQuestions = new LinkedList<Long>();
add already answered questions to the LinkedList:
Cursor c = mDbHelper.getTestData(generateWhereClause());
mAnsweredQuestions.add(c.getLong(0));
List<Answer> labels = new ArrayList<Answer>();
[...]
add a function which generates the where-clause:
private String generateWhereClause(){
StringBuilder result = new StringBuilder();
for (Long l : mAnsweredQuestions){
result.append(" AND " + YOURID + " <> " + l);
}
return result.toString();
}
You could just save the Cursor objects into an ArrayList and then use contains to find out if that question was alredy asked. (Note: contains useses the equals method)
public class YourClass {
java.util.ArrayList<Long> cursorList = new java.util.ArrayList<Long>();
public void YourMethod {
Cursor c = mDbHelper.getTestData();
long l = c.getLong(0);
while(cursorList.contains(l))
{
Cursor c = mDbHelper.getTestData();
l = c.getLong(0);
}
cursorList.add(l);
}
}
The solution depends on your application logic. One of possible solutions is to remove "LIMIT 1" from your query and load all questions randomly sorted.
If your app does something like "show me next random question I have never seen before", you have to keep the list of already visited questions (in memory, or in DB - again depends on your application logic. For DB solution is as simple as add visited column to your database.
For this problem, Better you maintain the list of question(object or id) your asked. Before display any question to the user check the current question is in your array list or not. If current qus is in arraylist then you can call getTestData(), otherwise you can display the question and add id or qus object to the array list.

Calling a Method from button click

I'm new to java and I'm trying to run a method once a button is clicked and I am unsure if I'm on the right track. I am selecting 10 questions from a Sqlite database and would like to cycle through each question 0-9 everytime the button is clicked. Once all 10 questions are asked I will move to another activity. I have the app displaying the first question fine but I am having trouble calling the showQuestions method and increasing the questionNum int by one when the button is clicked and passing this onto the method. Any help would be appreciated!
This is the showQuestions method which I am trying to call.
public void showQuestions(Cursor cursor) {
cursor.moveToPosition(questionNum);
while (cursor.moveToNext()) {
// Collect String Values from Query
StringBuilder questiontxt = new StringBuilder("");
StringBuilder answertxt1 = new StringBuilder("");
StringBuilder answertxt2 = new StringBuilder("");
StringBuilder answertxt3 = new StringBuilder("");
StringBuilder answertxt4 = new StringBuilder("");
String question = cursor.getString(2);
String answer = cursor.getString(3);
String option1 = cursor.getString(4);
String option2 = cursor.getString(5);
String option3 = cursor.getString(6);
questiontxt.append(question).append("");
answertxt1.append(answer).append("");
answertxt2.append(option1).append("");
answertxt3.append(option2).append("");
answertxt4.append(option3).append("");
}
}
This is the code for the button which I am working on. There are 4 buttons.
public void onClick(View v) {
switch (v.getId()) {
case R.id.option1_button:
if (questionNum<9) {
questionNum ++;
}
Questions.this.showQuestions(null);
break;
}
And this is the XML code for the buttons.
<Button
android:id="#+id/option1_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/option3_button"/>
OnClick Listener for the button
View option1_button = findViewById(R.id.option1_button);
option1_button.setOnClickListener(this);
Database Query and Allocation to Cursor
//Get the questions and allocate them to the Cursor
public Cursor getQuestions() {
//Select Query
String loadQuestions = "SELECT * FROM questionlist ORDER BY QID LIMIT 10";
SQLiteDatabase db = questions.getReadableDatabase();
Cursor cursor = db.rawQuery(loadQuestions, null);
startManagingCursor(cursor);
return cursor;
}
Thanks in advance.
Questions.this.showQuestions(null);
Why you pass null to the showQuestions method?
Let me guess - it crashes with NullPointerException.
Did you tried
showQuestions(getQuestions())
EDIT:
Some general suggestions:
don't load the question every time when the button is clicked.
make some Question class containing all needed information for a question
when onCreate is invoked, open the database and load all needed questions in some Collection, like ArrayList<Question>
Every time when the user clicks a button, get the next Question element from the Collection and show it

Categories

Resources