"Attempted to access a cursor after it has been closed" - android

I cannot understand this problem. I have tried to get the solution from other stackoverflow questions but failed to get the solution. I was not getting this error before. However, now I don't know what's wrong with the code stated below. Please help me with this. I'm stuck with this problem.
public void getAlbumsLists() {
final Uri uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
final String _id = MediaStore.Audio.Albums._ID;
final String album = MediaStore.Audio.Media.ALBUM;
final String album_name = MediaStore.Audio.AlbumColumns.ALBUM;
final String artist = MediaStore.Audio.AlbumColumns.ARTIST;
final String tracks = MediaStore.Audio.AlbumColumns.NUMBER_OF_SONGS;
// final String data=MediaStore.Audio.Albums.ALBUM_ID; // NO
// final String id1=MediaStore.Audio.Albums.ALBUM_ID;
final String tit = MediaStore.Audio.Albums.ALBUM; //NO
final String nam = MediaStore.Audio.Albums.ALBUM_KEY; // NO
final String typ = MediaStore.Audio.Media.MIME_TYPE; // NO
final String art = MediaStore.Audio.Albums.ALBUM_ART; //<<<< CAN GET
final String artstkey = MediaStore.Audio.Artists.ARTIST_KEY; //<<<< CAN GET
final String frstyr = MediaStore.Audio.AlbumColumns.FIRST_YEAR; //<<<< CAN GET
final String lstyr = MediaStore.Audio.AlbumColumns.LAST_YEAR; //<<<< CAN GET
final String artstid = "artist_id"; //<<<< CAN GET
final String[] columns = {"*"};
Cursor cursor = getActivity().getContentResolver().query(uri, columns, null, null, null);
// Lists the columns in the cursor
for (String s : cursor.getColumnNames()) {
Log.d("COLUMNS", "Column = " + s);
}
while (cursor.moveToNext()) {
String id = (cursor.getString(cursor.getColumnIndex(_id)));
String name = cursor.getString(cursor.getColumnIndex(album_name));
String artist2 = cursor.getString(cursor.getColumnIndex(artist));
String nr = cursor.getString(cursor.getColumnIndex(tracks));
String x = (cursor.getString(cursor.getColumnIndex(album)));
//String data1=cursor.getString(cursor.getColumnIndexOrThrow(data)); //<<<< NOT A COLUMN
// String id2=cursor.getString(cursor.getColumnIndex(data));
//String title=cursor.getString(cursor.getColumnIndex(tit)); //<<<< NOT A COLUMN
//String name1=cursor.getString(cursor.getColumnIndex(nam)); //<<<< NOT A COLUMN
//String type=cursor.getString(cursor.getColumnIndex(typ)); //<<<< NOT A COLUMN
// AVAIALABLE COLUMNS
String artwork = cursor.getString(cursor.getColumnIndex(art)); //<<<< ADDED
String artistkey = cursor.getString(cursor.getColumnIndex(artstkey)); //<<<< ADDED
String artistid = cursor.getString(cursor.getColumnIndex(artstid)); //<<<< ADDED
String minyear = cursor.getString(cursor.getColumnIndex(frstyr));
String maxyear = cursor.getString(cursor.getColumnIndex(lstyr));
s = new albumInfo(id, name, artist2, nr, artwork, x); // EXCLUDED
albumList.add(s);
cursor.close();
recyclerView1.setAdapter(albumAdapter); // EXCLUDED
}
}

Move cursor.close(); outside the while loop.
Edited..
First time after the while loop iterates the cursor is closed so you need to put it outside while.

I can suggest three improvement scenarios.
You need to move the cursor to first before accessing it for fetching data from the cursor.
You need to close the cursor when nothing is returned or the cursor is null.
Move the cursor close outside of your while loop.
So I would like to recommend you to rewrite the code like following.
// After you have fetched the data from cursor
if(cursor == null) return;
if(cursor.size() == 0) {
cursor.close();
return;
}
for (String s : cursor.getColumnNames()) {
Log.d("COLUMNS", "Column = " + s);
}
// Move the cursor to the first position.
cursor.moveToFirst();
do {
String id = (cursor.getString(cursor.getColumnIndex(_id)));
String name = cursor.getString(cursor.getColumnIndex(album_name));
String artist2 = cursor.getString(cursor.getColumnIndex(artist));
String nr = cursor.getString(cursor.getColumnIndex(tracks));
String x = (cursor.getString(cursor.getColumnIndex(album)));
// ... Other code
} while (cursor.moveToNext());
recyclerView1.setAdapter(albumAdapter); // EXCLUDED
// Move the cursor outside of while loop
cursor.close();

Related

androids studio sqlite issue with selectionArgs argument

I have the following function in android studio, which is supposed to return a sqlite cursor.
The problem comes in the selectionArgs argument. Whenever I am passing more than one value to it, it returns a cursor with 0 records.
public Cursor getCursor(String strListWhere, String strTable, String strCols) {
String strColsToReturn = mySqliteHandler.getWhereColNamesFromJsonString(strListWhere);
String strArgs = mySqliteHandler.getWhereColArgsFromJsonString(strListWhere);
Log.d(TAG, "qqqq9: " + strArgs);
String strTableName = strTable;
String[] strColumnsToReturn = { strCols };
String strSelectWhere = strColsToReturn ;
String[] strSelectArgs = { strArgs };
Cursor csrResult = sqLiteDatabase.query(true, strTableName, strColumnsToReturn, strSelectWhere, strSelectArgs, null, null, null, null);
Log.d(TAG, "qqqq9: " + csrResult.getCount());
return csrResult;
}
The value in strColsToReturn is animal_class = ? and province_name = ?
The value in strArgs is Bird, KwaZulu-Natal
So I want it to be animal_class = 'Bird' and province_name = 'KwaZulu-natal'
When I only pass one value it works, for example
The value in strColsToReturn is animal_class = ?
The value in strArgs is Bird
Can anyone assist?
EDIT: the following code works:
public Cursor getCursor(String strListWhere, String strTable, String strCols) {
String strColsToReturn = mySqliteHandler.getWhereColNamesFromJsonString(strListWhere);
List<String> arrWhere = new ArrayList<String>();
arrWhere = mySqliteHandler.getWhereArray(strListWhere);
String[] finalValue = new String[ arrWhere.size() ];
arrWhere.toArray( finalValue );
String strTableName = strTable;
String[] strColumnsToReturn = { strCols };
String strSelectWhere = strColsToReturn ;
Cursor csrResult = sqLiteDatabase.query(true, strTableName, strColumnsToReturn, strSelectWhere, finalValue, null, null, null, null);
return csrResult;
}
The value for strColumnsToReturn should be an array with the names of the columns that you want returned, like:
new String[] {column1, column2, column3}
where column1, column2, column3 are strings.
The value for strSelectWhere should be the string:
"animal_class = ? and province_name = ?"
and the value of strSelectArgs should be a string array with the parameters that you pass to each of the ? placeholders of strSelectWhere:
new String {"Bird", "KwaZulu-Natal"}
You can find more here

Get events from public google calendar Android

I would like to have a calendar view that would present all of the events of a public google calendar.
I have an OAuth 2.0 client ID for my user and my calendar is set to PUBLIC.
Then I went trough the Calendar Provider tutorial (https://developer.android.com/guide/topics/providers/calendar-provider.html) and use this code:
public class MainActivity extends Activity {
// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[]{
CalendarContract.Calendars._ID, // 0
CalendarContract.Calendars.ACCOUNT_NAME, // 1
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, // 2
CalendarContract.Calendars.OWNER_ACCOUNT // 3
};
// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = CalendarContract.Calendars.CONTENT_URI;
String selection = "((" + CalendarContract.Calendars.ACCOUNT_NAME + " = ?) AND ("
+ CalendarContract.Calendars.ACCOUNT_TYPE + " = ?) AND ("
+ CalendarContract.Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[]{"****#gmail.com", "google.com",
"****#gmail.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
// Use the cursor to step through the returned records
while (cur.moveToNext()) {
long calID = 0;
String displayName = null;
String accountName = null;
String ownerName = null;
// Get the field values
calID = cur.getLong(PROJECTION_ID_INDEX);
displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
}
}
}
Unfortunately, the Cursor stayed empty. I was also trying to define the ACCOUNT_TYPE to "LOCAL", but it didn't work.
Target SDK set to 21, and i have all the necessary permissions.
How can I retrieve the events of my calendar? Please help /:

sqlite update method using Cursor

Hi I am creating an sqlite helper file for my android project. I have found a couple of tutorials on doing this but i am having an issue with retrieving values from the sqlite database. I get the following error message:"Can not resolve constructor"
Event getEvent(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_EVENTS, new String[] { KEY_ID, KEY_EVENTNAME, KEY_EVENTTIME,
KEY_EVENTDATE, KEY_EVENTLOCATION, KEY_EVENTADDRESS1, KEY_EVENTADDRESS2, KEY_EVENTCITY, KEY_EVENTSTATE, KEY_EVENTZIP, KEY_EVENTTYPE },
KEY_ID + "=?", new String[] {String.valueOf(id)}, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Event event = new Event(Integer.parseInt(cursor.getString(0)), cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4),
cursor.getString(5), cursor.getString(6),cursor.getString(7), cursor.getString(8), cursor.getString(9),
cursor.getString(10), cursor.getString(11));
//return event
return event;
}
The error is in the statement that starts with Event event = new Event....
I am not sure do if i need a cursor.getString(n) for each table column?
Any help would be great.
Thanks.
adding event file
//empty contructor
public Event(){
}
public Event(int id, String _eventName, String _eventTime, String _eventDate, String _eventLocation, String _eventAddress1, String _eventAddress2, String _eventCity, String _eventState, int _eventZip, String _eventType) {
this._id = id;
this._eventName = _eventName;
this._eventTime = _eventTime;
this._eventDate = _eventDate;
this._eventLocation = _eventLocation;
this._eventAddress1 = _eventAddress1;
this._eventAddress2 = _eventAddress2;
this._eventCity = _eventCity;
this._eventState = _eventState;
this._eventZip = _eventZip;
this._eventType = _eventType;
}
public Event(String _eventName, String _eventTime, String _eventDate, String _eventLocation, String _eventAddress1, String _eventAddress2, String _eventCity, String _eventState, int _eventZip, String _eventType) {
this._eventName = _eventName;
this._eventTime = _eventTime;
this._eventDate = _eventDate;
this._eventLocation = _eventLocation;
this._eventAddress1 = _eventAddress1;
this._eventAddress2 = _eventAddress2;
this._eventCity = _eventCity;
this._eventState = _eventState;
this._eventZip = _eventZip;
this._eventType = _eventType;
}
Thanks #Selvin and #Pier That was part of the issue I had too many parameters and the other part was I didn't realize that you need cursor.getInt() instead cursor.getString for integers.
Thanks again

Get all tracks from MediaStore

I try to get all tracks from MediaStore.
Cursor cursor = managedQuery(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, null, null, null, null);
while (cursor.moveToNext())
{
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.AudioColumns._ID));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST));
int duration = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION));
}
cursor.close();
But I can't read values from cursor. When I run this code
MediaStore.Audio.AudioColumns.TITLE,
MediaStore.Audio.AudioColumns.ALBUM,
MediaStore.Audio.AudioColumns.ARTIST and
MediaStore.Audio.AudioColumns.DURATION
constants is null.
Which constants I must use to get values in result above?
set up columns and uri to return:
final String track_id = MediaStore.Audio.Media._ID;
final String track_no = MediaStore.Audio.Media.TRACK;
final String track_name = MediaStore.Audio.Media.TITLE;
final String artist = MediaStore.Audio.Media.ARTIST;
final String duration = MediaStore.Audio.Media.DURATION;
final String album = MediaStore.Audio.Media.ALBUM;
final String composer = MediaStore.Audio.Media.COMPOSER;
final String year = MediaStore.Audio.Media.YEAR;
final String path = MediaStore.Audio.Media.DATA;
final String date_added = MediaStore.Audio.Media.DATE_ADDED;
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
To get all tracks:
public Cursor getTrackTrackcursor(Context context, Cursor cursor) {
// gets all tracks
ContentResolver cr = context.getContentResolver();
final String[] columns = { track_id, track_no, artist, track_name,
album, duration, path, year, composer };
cursor = cr.query(uri, columns, null, null, null);
return cursor;
}
now loop through the cursor and extract the string values according to the columns returned.
You can only extract columns which have been returned by the cursor so an error would occur as I did not return NUMBER_OF_SONGS. You would have to ensure this is also returned by the cursor
For example:
String stralbum = (c.getString(cursor
.getColumnIndex(MediaStore.Audio.Albums.ALBUM)));
String strartist = (cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Albums.ARTIST)));
String stryear = (cursor.getString(cusrsor
.getColumnIndex(MediaStore.Audio.Albums.FIRST_YEAR)));
String strnosongs = (cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Albums.NUMBER_OF_SONGS)));
You are 99% correct but your uri needs the column layout. Hope this helps

Get data from database Android

I have a page which can retrieve user data from database
but after whole day of trying, I am only able to get the table column name but not the value inside.
this is my code to create database
public static final String LASTLOGIN = "lastuser";
public static final String USER_ID = "suser_id";
public static final String USER_NAME = "suser_name";
public static final String USER_PASSWORD = "spassword";
public static final String PRIME_ID = "id";
private static final String TABLE_USER =
"create table "+ LASTLOGIN+" ("
+PRIME_ID+" integer primary key autoincrement, "
+ USER_ID + " text, "
+ USER_NAME +" text, "
+USER_PASSWORD+" text); ";
and here is the function implemented to get user data
public Cursor getuser()
{
String[] columns = new String[]{PRIME_ID, USER_NAME, USER_PASSWORD};
Cursor cursor = sqLiteDatabase.query(
LASTLOGIN, columns, null, null, null, null, PRIME_ID +" DESC");
Log.d("TAG", columns[1]);
return cursor;
}
and here is my code to display the result
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
cursor = mySQLiteAdapter.getuser();
String[] resultvalue = new String{
SQLiteAdapter.PRIME_ID,SQLiteAdapter.USER_NAME, SQLiteAdapter.USER_PASSWORD};
Toast.makeText(this, resultvalue[0]+resultvalue[1], Toast.LENGTH_LONG).show();
and the toast result only show the column name but not the value inside, is there any mistake i made? and I want to set limit to 1, but where to set it?
Thanks for helping me
the way you try reading the values is completly wrong.
you create an array
String[] resultvalue = new String[]{
SQLiteAdapter.PRIME_ID,
SQLiteAdapter.USER_NAME,
SQLiteAdapter.USER_PASSWORD};
after that you read the values 0 and 1 from this array.
Your toast works absolutly correctly becouse inside this array you define the column names!
If you want to show the values from your query do it this way:
while(cursor.moveToNext()){
Integer str1 = str 1 + cursor.getInteger(1);
String str2 =str2 + cursor.getString(2);
Toast.makeText(this, str1 + str2, Toast.LENGTH_LONG).show();
}
or a better way receiving the correct index:
cursor.getInteger( cursor.getColumnIndex(SQLiteAdapter.PRIME_ID) );
cursor.getString( cursor.getColumnIndex(SQLiteAdapter.USER_NAME) );
Please note when retrieving data from a database, you store it in a Cursor in the memory and hence can only access it using that particular Cursor object, which you have used in the following line of code.
Cursor cursor = mySQLiteAdapter.getuser();
The Following line retrieves the column names and not the values.
String[] resultvalue = new String[]{SQLiteAdapter.PRIME_ID,SQLiteAdapter.USER_NAME, SQLiteAdapter.USER_PASSWORD};
So the following is doing what you have asked it to do, retrieve column names not values
Toast.makeText(this, resultvalue[0]+resultvalue[1], Toast.LENGTH_LONG).show();
You need something like following:
if(cursor.getCount() != 0)
{
while(cursor.moveToNext())
{
resultvalue [0] = csr.getString(0);
resultvalue [1] = csr.getString(1);
//....
}
}
Hope this helps
here is my solution:
final String TABLE_NAME = "table_name";
String selectQuery = "SELECT Column FROM "+TABLE_NAME+" WHERE column='"+some_value+"'";
SQLiteDatabase db = this.openDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
String[] data = new String[cursor.getCount()];;
int i = 0;
if (cursor.moveToFirst()) {
do {
i=Integer.parseInt(cursor.getString(cursor.getColumnIndex("value")));
} while (cursor.moveToNext());
}
cursor.close();

Categories

Resources