So, I have this error in user crash report for my app. Here's the report:
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at rs.androidaplikacije.zastaveigradovi.Kviz10Hard.nextQuestionGrad(Kviz10Hard.)
at rs.androidaplikacije.zastaveigradovi.Kviz10Hard.access$1(Kviz10Hard.)
at rs.androidaplikacije.zastaveigradovi.Kviz10Hard$2.run(Kviz10Hard.java:68)
at android.os.Handler.handleCallback(Handler.)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.)
at android.app.ActivityThread.main(ActivityThread.)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.)
at dalvik.system.NativeStart.main(Native Method)
And here's the mentioned code:
private void nextQuestionGrad() {
flag.setVisibility(View.GONE);
dodatnoPitanje.setVisibility(View.VISIBLE);
TestAdapter mDbHelper = new TestAdapter(this);
DataBaseHelper myDbHelper = new DataBaseHelper(this);
if(!myDbHelper.checkDataBase()){
mDbHelper.createDatabase();
}
try{
mDbHelper.open();
Cursor c = mDbHelper.getTestDataGradovi(mCurrentID);
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));
tacanOdg = c.getString(2);
Collections.shuffle(labels);
dodatnoPitanje.setText(c.getString(1));
bOdgovor1.setText(labels.get(0).option);
bOdgovor1.setTag(labels.get(0));
bOdgovor1.setOnClickListener(clickListenerGrad);
bOdgovor2.setText(labels.get(1).option);
bOdgovor2.setTag(labels.get(1));
bOdgovor2.setOnClickListener(clickListenerGrad);
bOdgovor3.setText(labels.get(2).option);
bOdgovor3.setTag(labels.get(2));
bOdgovor3.setOnClickListener(clickListenerGrad);
bOdgovor4.setText(labels.get(3).option);
bOdgovor4.setTag(labels.get(3));
bOdgovor4.setOnClickListener(clickListenerGrad);
score.setText("Score: " + brojacTacnihOdgovora);
}finally{
mDbHelper.close();
}
}
And part of my adapter class I'm using for this class:
public Cursor getTestDataGradovi(long id){
try{
String sql ="SELECT * FROM tblGradovi WHERE _ID = " + id;
Cursor c = mDb.rawQuery(sql, null);
if (c!=null){
c.moveToNext();
}
return c;
}catch (SQLException mSQLException){
Log.e(TAG, "getTestData >>"+ mSQLException.toString());
throw mSQLException;
}
}
Can someone tell me where's the problem? The error line (Kviz10Hard.) is here:
labels.add(new Answer(c.getString(2), true));
Before trying to get any data from a Cursor object you need to iterate the result or get the first one if the cursor contains only one value. For example to iterate between all result you should do something like this :
String sql = "SELECT * FROM myTable";
Cursor cursor = mDbHelper.rawQuery(sql, null);
if(cursor != null){
if(cursor.getCount() > 0){
for(cursor.move(0);cursor.moveToNext();cursor.isAfterLast()){
// get your data here
}
}
cursor.close(); // close your cursor when you don't need it anymore
}
or another way to do this it :
String sql = "SELECT * FROM myTable";
Cursor cursor = mDbHelper.rawQuery(sql, null);
if(cursor != null){
if(cursor.getCount() > 0){
do {
// get value
} while(cursor.moveToNext());
}
cursor.close(); // close your cursor when you don't need it anymore
}
or if you are pretty sure that the result should be only one object depending on your sql statement you should call cursor.moveToFirst(); before accessing anything from your Cursor like this :
String sql = "SELECT * FROM myTable";
Cursor cursor = mDbHelper.rawQuery(sql, null);
if(cursor != null){
cursor.moveToFirst();
String myString = cursor.getString(cursor.getColumnIndex("title"));
cursor.close(); // close your cursor when you don't need it anymore
}
Edit:
If you really want to create function like this in your database class I would do something like this :
public static Cursor getUserTitles(int userId){
String sql = "SELECT * FROM myTable WHERE userId=?";
return mDbHelper.rawQuery(sql, new String[]{Integer.toString(userId)});
}
Second Edit:
Change your getTestDataGradovi to :
public Cursor getTestDataGradovi(long id){
String sql ="SELECT * FROM tblGradovi WHERE _ID=?";
return mDb.rawQuery(sql, new String[]{Integer.toString(id)});
}
and add c.moveToFirst(); , after Cursor c = mDbHelper.getTestDataGradovi(mCurrentID);
You are not checking that the Cursor contains any results. You need to check the return value of c.moveToNext(), or check c.getCount() or something similar.
Related
in my project after user sign up , i want to display the username in next page
so, this line works but with only first user sign up if another user sign up it will display the first username.
displName =findViewById(R.id.displayName);
displName.setText(database.getAllNote().get(0).getUserName());
my database
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public void openDatabase() {
db = this.getWritableDatabase();}
#SuppressLint("Range")
public List<UserTasks> getAllNote(){
List<UserTasks> listNote = new ArrayList<>();
Cursor cur = null;
db.beginTransaction();
try{
cur = db.query(TABLE_NAME, null, null, null, null, null, null, null);
if(cur != null){
if(cur.moveToFirst()){
do{
UserTasks note = new UserTasks();
note.setUser_id(cur.getInt(cur.getColumnIndex(UID)));
note.setUserName(cur.getString(cur.getColumnIndex(UserName)));
note.setPassword(cur.getString(cur.getColumnIndex(Password)));
note.setNote(cur.getString(cur.getColumnIndex(Note)));
note.setStatus(cur.getInt(cur.getColumnIndex(STATUS)));
note.setDate(cur.getString(cur.getColumnIndex(date)));
note.setTitle(cur.getString(cur.getColumnIndex(titleChe)));
note.setDecs(cur.getString(cur.getColumnIndex(desc)));
note.setDay(cur.getString(cur.getColumnIndex(day)));
listNote.add(note);
}
while(cur.moveToNext());
}
}
}
finally {
db.endTransaction();
assert cur != null;
cur.close();
}
return listNote;
}
how i can fix this small issue? pls help
You always get the first sign up user because you always retrieve table index 0
displName.setText(database.getAllNote().get(0).getUserName());
So I suggest you to use SharedPreference to increment the count of signup user.
When user successfully signup you have to increase the number of user
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0);
Int countUser = pref.getInt("count_user", 0); // getting Integer
Editor editor = pref.edit();
editor.putInt("count_user", countUser+1);
editor.apply();
After that, change your displName.setText to this:
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0);
Int countUser = pref.getInt("count_user", 0); // getting Integer
displName.setText(database.getAllNote().get(countUser).getUserName());
You will always get latest signup username.
I am looking to read a set of image files from the sdcard/download directory. I am getting content://media/external_primary/downloads as the URI string when calling
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
} else {
collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
}
I am using the Cursor interface to iterate through the directory but for some reason, my cursor is returning with a size of 0. I do not know what I am doing wrong to make this happen but below is the code that I have so far. Looking for some direction.
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
} else {
collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
}
String[] projection = {
MediaStore.MediaColumns._ID,
MediaStore.MediaColumns.TITLE
};
try {
Cursor cursor = getApplicationContext().getContentResolver().query(collection, projection, null, null, null);
// Cache column indices.
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID);
int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads.TITLE);
while (cursor.moveToNext()) {
// Get values of columns for a given video.
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID));
String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME));
Uri contentUri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, id);
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageURI(contentUri);
}
} catch (Exception e) {
e.printStackTrace();
}
Snippet to the directory structure
https://i.stack.imgur.com/ELkQw.png
I have following code which reads my phone and gets information of the music files in my phone
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String[] projectionSongs = {MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DURATION};
Cursor cursor = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projectionSongs,
selection, null, null);
Now I want to same information from assets folder itself.
I am trying
Uri uri = Uri.parse("file:///assets/");
Cursor cursor = mContext.getContentResolver().query(uri, projectionSongs,
selection, null, null);
But it is not working. There is no information in cursor. However I have some mp3 files in assets folder.
public void playBeep() {
try {
if (m.isPlaying()) {
m.stop();
m.release();
m = new MediaPlayer();
}
AssetFileDescriptor descriptor = getAssets().openFd("your_audio_file_name.mp3");
m.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
m.prepare();
m.setVolume(1f, 1f);
m.setLooping(true);
m.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Hope this will help u. Thank you
I came across the solution of this problem through Cursor,
public class MainActivity extends AppCompatActivity {
void example() {
List<File> localAudioFiles = new LinkedList<>();
Uri contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media.DATA};
// The problem is that it contains a list of files as of the moment
// when the operating system has been rebooted.
try (Cursor cursor = getContentResolver().query(
contentUri,
projection,
MediaStore.Audio.Media.IS_MUSIC + " != 0",
null,
null);) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
while (cursor.moveToNext()) {
String audio = cursor.getString(column_index);
localAudioFiles.add(new File(audio));
}
} catch (RuntimeException ex) {
}
}
}
but as far as I understand, its state needs to be updated compulsorily, because files added through the AVD file manager are not detected in this way until the device is rebooted.
How can I forcefully update the state of the entity Cursor?
Is the solution worth it, or is it not better than recursively traversing all the directories?
I'm having issues creating a valid sql query.
Im trying to check if a value, title is present in my db.
Here is the method in my adapter class that creates the query.
public Cursor byTitle(String title) throws SQLException {
Cursor mCursor = db.query(true, DATABASE_TABLE, new String[] {
KEY_URL
},
"title" + "=" +title,
null,
null,
null,
null,
null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
And its called onClick with
holder.fb.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final FDBAdapter db = new FDBAdapter(ctx);
title = holder.itemName.getText().toString();
db.open();
Cursor c = db.byTitle(title);
if (c.getCount()>0) {
while (c.moveToNext()) {
Toast.makeText(ctx, "yup! " + c.getString(0), Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(ctx, "nope! " + holder.itemName.getText().toString(), Toast.LENGTH_LONG).show();
}
c.close();
db.close();
}
});
My error is
android.database.sqlite.SQLiteException: near "Rootz": syntax error: , while compiling: SELECT DISTINCT url FROM favs WHERE title=[Guide] Rootz Wiki's List of ROMs / Kernels / Tweaks / Theme's / Radios LTE Edition
I've tried putting quotes around title like "\""+title+"\"" but that wasn't working for me either. How can I make this a valid db query?
Can you try this, might work.
Cursor mCursor = db.query(true, DATABASE_TABLE, new String[] {
KEY_URL
},
"title=?",
title,
null,
null,
null,
null);
Not familiar with SQLite, but I'd try single quotes, like this:
"title" + "='" + title + "'",