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

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

Related

Can't fetch data from SQLite database in AS

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.

IllegalArgumentException: Invalid column DISTINCT bucket_display_name

I'm retrieving list of distinct folders list having video files with number of videos in each folder, and this is working fine in devices having Android P and below, but when I run on devices having Android Q the app crashes.
How can I make it work for devices running Android Q
java.lang.IllegalArgumentException: Invalid column DISTINCT
bucket_display_name
Logcat:
java.lang.IllegalArgumentException: Invalid column DISTINCT bucket_display_name
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
at android.content.ContentResolver.query(ContentResolver.java:944)
at android.content.ContentResolver.query(ContentResolver.java:880)
at android.content.ContentResolver.query(ContentResolver.java:836)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$MediaQuery.getAllVideo(VideoFolderFragment.java:364)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$VideosLoader.loadVideos(VideoFolderFragment.java:434)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$VideosLoader.access$1100(VideoFolderFragment.java:413)
at com.aisar.mediaplayer.fragments.VideoFolderFragment$5.run(VideoFolderFragment.java:189)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
My Code:
public class MediaQuery {
private Context context;
private int count = 0;
private Cursor cursor;
List<ModelVideoFolder> videoItems;
public MediaQuery(Context context) {
this.context = context;
}
public List<ModelVideoFolder> getAllVideo(String query) {
String selection = null;
String[] projection = {
"DISTINCT " + MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.BUCKET_ID
};
cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
query);
videoItems = new ArrayList<>();
ModelVideoFolder videoItem;
while (cursor.moveToNext()) {
videoItem = new ModelVideoFolder(
"" + cursor.getString(1),
"" + cursor.getString(0),
"",
"",
"" + getVideosCount(cursor.getString(1))
);
videoItems.add(videoItem);
}
return videoItems;
}
public int getVideosCount(String BUCKET_ID) {
int count = 0;
String selection = null;
String[] projection = {
MediaStore.Video.Media.BUCKET_ID,
};
Cursor cursor = getActivity().getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
null);
while (cursor.moveToNext()) {
if (BUCKET_ID.equals(cursor.getString(0))) {
//add only those videos that are in selected/chosen folder
count++;
}
}
return count;
}
}
This is due to the restrictions in Android Q.
In Android Q the projection must contain only valid column names without additional statements. Is not possible anymore to embed any type of SQL statement in the projection.
So, projections such as "DISTINCT " + YourColumName, or even trying to make a column alias such as "ExistingColumnName AS AnotherName" will always fail.
The workaround is to perform multiple queries (cursors) to get your required metrics, and construct with the results a CursorWrapper or MatrixCursor.
See the next issue link, where is stated this behavior as expected, since is part of the improved storage security model in Q:
https://issuetracker.google.com/issues/130965914
For your specific problem, a solution could be as next:
First query for a cursor to obtain the list of the BUCKET_ID values where all the videos are located. In the selection you can filter to target only video files by using MediaStore.Files.FileColumns.MEDIA_TYPE = MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO
With the retrieved cursor, iterate all the BUCKET_ID values to perform individual queries per bucket and retrieve the video records, from which you can resolve the count. While iterating keep track of each BUCKET_ID and skip any already queried. And don't forget to also perform the same MEDIA_TYPE filter selection, to avoid querying none-video files that may reside in the same bucket.
Try the next snippet based in your question code, I haven't test it but you may get an idea about how to proceed:
public static class MediaQuery
{
#NonNull
public static HashMap<String, ModelVideoFolder> get(#NonNull final Context context)
{
final HashMap<String, ModelVideoFolder> output = new HashMap<>();
final Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
final String[] projection = {MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.BUCKET_ID};
try (final Cursor cursor = context.getContentResolver().query(contentUri,
projection, null, null, null))
{
if ((cursor != null) && (cursor.moveToFirst() == true))
{
final int columnBucketName = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
final int columnBucketId = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_ID);
do
{
final String bucketName = cursor.getString(columnBucketName);
final String bucketId = cursor.getString(columnBucketId);
if (output.containsKey(bucketId) == false)
{
final int count = MediaQuery.getCount(context, contentUri, bucketId);
final ModelVideoFolder item = new ModelVideoFolder(
bucketName, bucketId, null, null, count);
output.put(bucketId, item);
}
} while (cursor.moveToNext());
}
}
return output;
}
private static int getCount(#NonNull final Context context, #NonNull final Uri contentUri,
#NonNull final String bucketId)
{
try (final Cursor cursor = context.getContentResolver().query(contentUri,
null, MediaStore.Video.Media.BUCKET_ID + "=?", new String[]{bucketId}, null))
{
return ((cursor == null) || (cursor.moveToFirst() == false)) ? 0 : cursor.getCount();
}
}
}
The DISTINCT keyword actually belongs to the SELECT statement, not to a column. For example SELECT DISTINCT Country, Name FROM CountriesTable. Therefore adding DISTINCT to a column projection is a hack which randomly worked in the previous Android versions and probably stopped working in Android 10 due to some changes. Since the ContentResolver doesn't allow raw queries, you just have to filter unique folders inside your code, e. g. by using a HashSet.
I was facing the same problem. DISTINCT keyword doesn't work in Android 10, use hashset for distinct.

Hashmap to link albumid with album name?

I'm trying to display the album names and album artwork from the songs on my device.
I tried using a comparator to sort the album names, but when i sort the album names the artwork doesn't match the album name.
How can i link the albumid with the matching artwork?
I use picasso to display the album art and.
I get the album art from MediaStore.Audio.Media.ALBUM_ID;
Then i tried using a hashmap to link albumid with album name.
But im getting this error;
E/Couldn't execute task: java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.database.Cursor.moveToFirst()' on a null object reference
// Creating the map "Album IDs" -> "Album Names"
albumIdToAlbumNameMap = new HashMap<>();
//This is what we'll ask of the albums
String[] albumColumns = {
SONG_ALBUMID,
SONG_ALBUM,
};
// Querying the album database
cursor = resolver.query(musicUri, albumColumns, null, null, null);
// Iterating through the results and filling the map.
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
albumIdToAlbumNameMap.put(cursor.getString(0), cursor.getString(1));
cursor.close();
// Map Song IDs to Album IDs
songIdToAlbumIdMap = new HashMap<>();
// For each album, we'll query the databases
for (String albumID : albumIdToAlbumNameMap.keySet()) {
Uri uri = MediaStore.Audio.Albums.getContentUri(albumID);
cursor = resolver.query(uri, new String[] { SONG_ID }, null, null, null);
// Iterating through the results, populating the map
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long currentSongID = cursor.getLong(cursor.getColumnIndex(SONG_ID));
songIdToAlbumIdMap.put(Long.toString(currentSongID), albumID);
}
cursor.close();
}
final String musicsOnly = MediaStore.Audio.Media.IS_MUSIC + "=1";
// Actually querying the system
cursor = resolver.query(musicUri, columns, musicsOnly, null, null);
if (cursor != null && cursor.moveToFirst())
{
// NOTE: I tried to use MediaMetadataRetriever, but it was too slow.
// Even with 10 songs, it took like 13 seconds,
do {
// Creating a song from the values on the row
QuerySongs song = new QuerySongs(cursor.getInt(cursor.getColumnIndex(SONG_ID)),
cursor.getString(cursor.getColumnIndex(SONG_FILEPATH)));
song.setTitle (cursor.getString(cursor.getColumnIndex(SONG_TITLE)));
song.setArtist (cursor.getString(cursor.getColumnIndex(SONG_ARTIST)));
song.setAlbumID (cursor.getInt(cursor.getColumnIndexOrThrow(SONG_ALBUMID)));
// Using the previously created genre maps
// to fill the current song genre.
String currentGenreID = songIdToGenreIdMap.get(Long.toString(song.getId()));
String currentGenreName = genreIdToGenreNameMap.get(currentGenreID);
String currentAlbumID = songIdToAlbumIdMap.get(Long.toString(song.getId()));
String currentAlbumName = albumIdToAlbumNameMap.get(currentAlbumID);
song.setGenre(currentGenreName);
song.setAlbum(currentAlbumName);
// Adding the song to the global list
songs.add(song);
}
while (cursor.moveToNext());
}
else
{
// What do I do if I can't find any songs?
}
cursor.close();
Here does the error occur
// Iterating through the results, populating the map
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long currentSongID = cursor.getLong(cursor.getColumnIndex(SONG_ID));
songIdToAlbumIdMap.put(Long.toString(currentSongID), albumID);
}
Seems like you need to fix your query input to avoid null in cursor.

Why is Android's MediaStore.Audio.Album.ALBUM_ID causing an IllegalStateException error?

I'm trying to grab album information from MediaStore. I can get the name and artist very easily but for some reason the ALBUM_ID column is giving me an error when I try to access it.
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetString(Native Method)
at android.database.CursorWindow.getString(CursorWindow.java:450)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51 )
at android.database.CursorWrapper.getString(CursorWrapper.java:114)
at sage.musicplayer.MainActivity.getAlbumList(MainActivity.java:1540)
at sage.musicplayer.MainActivity.onCreate(MainActivity.java:238)
I can't seem to find a solution. Any help is appreciated! Below is the method I have to grab the album information and add them to an ArrayList.
public ArrayList<Album> getAlbumList() {
ArrayList<Album> temp = new ArrayList<>();
/*String[] proj = {MediaStore.Audio.Albums.ALBUM_ID,
MediaStore.Audio.Albums.ARTIST,
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Albums.NUMBER_OF_SONGS
};*/
Cursor albumCursor = getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, null, null, null, null);
if(albumCursor != null && albumCursor.moveToFirst()) {
int albumName = albumCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM);
int albumArtist = albumCursor.getColumnIndex(MediaStore.Audio.Albums.ARTIST);
int albumID = albumCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ID);
do {
String thisAlbumName = albumCursor.getString(albumName);
String thisAlbumArtist = albumCursor.getString(albumArtist);
String thisAlbumID = albumCursor.getString(albumID);//this line is giving me an error
temp.add(new Album(thisAlbumName, thisAlbumArtist, thisAlbumID));
}while(albumCursor.moveToNext());
}
return temp;
}
I too faced this issue. You can easily solve this issue by changing
int albumID = albumCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ID);
TO
int albumID = albumCursor.getColumnIndex(MediaStore.Audio.Albums._ID);
That is you need to use _ID whenever you want AlbumID of the Album. I have no idea why MediaStore developers used _ID instead of ALBUM_ID, etc stuff.

how to open a specific image in the android photo gallery ?

I have an android imageView.
I have set an OnClickListener to pick an image from Photo Gallery to be its src.
I now want to change the OnClick open this specific image in the photo gallery.
how do I do this? how to open a specific image in the photo gallery ?
You can query with particular photoID, from below code you got all image and it's id and from id you can find particular image.
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
imagecursor = getActivity().managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
this.count = imagecursor.getCount();
this.arrPath = new String[this.count];
ids = new int[count];
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i);
ids[i] = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
arrPath[i] = imagecursor.getString(dataColumnIndex);
}
find adapter code and set it in gridview from
get full photogallery code

Categories

Resources