我正在编写一个小应用程序来检索Android创建的播放列表中的所有项目,并能够按特定顺序对列表进行排序。我想要做的是这种实际上保存回数据库,或更新播放列表文件。作为Android开发的相对新手,我不确定这是什么方法。
这是我的代码:
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import java.util.List;
public class PlaylistSongActivity extends AppCompatActivity {
final String SONG_ID_KEY = MediaStore.Audio.AudioColumns._ID;
final String SONG_ARTIST_KEY = MediaStore.Audio.AudioColumns.ARTIST;
final String SONG_ALBUM_KEY = MediaStore.Audio.AudioColumns.ALBUM;
final String SONG_TITLE_KEY = MediaStore.Audio.AudioColumns.TITLE;
final String SONG_TRACK_NO_KEY = MediaStore.Audio.AudioColumns.TRACK;
final String CASE_INSENTIVE = " COLLATE NOCASE ";
final String[] PLAYLIST_QUERY_COLUMNS = {SONG_ID_KEY, SONG_ARTIST_KEY, SONG_TITLE_KEY, SONG_ALBUM_KEY, SONG_TRACK_NO_KEY};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playlist);
// Spinner values
final Spinner playlistSettingsDropdown = (Spinner) findViewById(R.id.playlistSettingsDropdown);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.playlist_settings_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
playlistSettingsDropdown.setAdapter(adapter);
playlistSettingsDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
sortGrid(pos);
}
public void setId(int pos) {
playlistSettingsDropdown.setSelection(pos);
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
});
// Song grid
ListView playlistSongsView = getSongGrid();
final Cursor playlistSongs = createPlaylistCursor(null);
PlaylistSongCursor playlistSongsAdapter = new PlaylistSongCursor(playlistSongsView.getContext(), playlistSongs);
playlistSongsView.setAdapter((playlistSongsAdapter));
}
public void sortGrid(int sortType) {
ListView songGrid = getSongGrid();
PlaylistSongCursor songGridAdapter = (PlaylistSongCursor) songGrid.getAdapter();
String sort = SONG_ARTIST_KEY + CASE_INSENTIVE + " ASC," +
SONG_ALBUM_KEY + CASE_INSENTIVE + " ASC," +
SONG_TRACK_NO_KEY + " ASC";
switch (sortType) {
case 1:
sort = SONG_ARTIST_KEY + CASE_INSENTIVE + " DESC," +
SONG_ALBUM_KEY + CASE_INSENTIVE + " DESC," +
SONG_TRACK_NO_KEY + " DESC";
}
songGridAdapter.changeCursor(createPlaylistCursor(sort));
}
public ListView getSongGrid() {
return (ListView) findViewById((R.id.playlistItems));
}
public Uri getPlaylistUri() {
int playlistId = getIntent().getExtras().getInt("playlistId");
return MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
}
public Cursor createPlaylistCursor(String sort) {
return getContentResolver().query(getPlaylistUri(), null, null, null, sort);
}
}
所以我从我传递的意图中获取列表的ID,从MediaStore
包中获取其URI,然后使用URI从查询中使用ContentProvider
获取Cursor。这一切都有效,播放列表的歌曲显示得很好,我的排序也很有效(尽管我欢迎对我正在做的事情进行批评)。问题是我如何使用光标保存回数据库,因此它会持续存在于其他音乐应用程序中? (BlackPlayer具有此功能及其按艺术家排序 - 专辑选项)
我在考虑几种方法,但我并不完全确定如何执行它们:
ContentValues
执行某些操作(从中检索
DatabaseUtils.cursorRowToContentValues
)getWritableDatabase
...不确定如何检索数据库本身File
,但因为它是URI
和SQLite
文件,我不确定如何保存File
这样的内容。 ..它必须采用特殊格式吗?有没有人有任何见解?
更新
我开始沿着使用bulkInsert的路线前进,但似乎它没有将ContentValues[]
插入我的数据库......这肯定会删除我的行,而我的retVal
包含要插入的项目数量,它不会插入...
myButton.setOnClickListener(new AdapterView.OnClickListener() {
public void onClick(View view) {
ListView songGrid = getSongGrid();
PlaylistSongCursor songGridAdapter = (PlaylistSongCursor) songGrid.getAdapter();
Cursor myCursor = songGridAdapter.getCursor();
ContentValues[] retVal = new ContentValues[myCursor.getCount()];
ContentValues map;
int i = 0;
if(myCursor.moveToFirst()) {
do {
map = new ContentValues();
DatabaseUtils.cursorRowToContentValues(myCursor, map);
retVal[i++] = map;
} while(myCursor.moveToNext());
}
// Empties db
getContentResolver().delete(getPlaylistUri(), null, null);
// Logs 2 (as that's how many items are in my list)
Log.d("BLA", String.valueOf(retVal.length));
final int retInt = getContentResolver().bulkInsert(getPlaylistUri(), retVal);
// Logs 0
Log.d("DONE", String.valueOf(retInt));
}
});
答案 0 :(得分:1)
查看ContentProvider的官方文档。基本上ContentProvider
隐藏了数据库,因此您可以使用URI(如果需要,可以ContentValues
)与之通信,但不能直接与数据库进行通信。
//Create empty values
ContentValues values= new ContentValues();
//put all you want to update
values.put(MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER, sort);
//call update method on ContentResolver
int rows = getContentResolver().update(
getPlaylistUri(), //uri to modify
values, //new values for
MediaStore.Audio.Playlists.Members.PLAYLIST_ID + "=?", //selection clause
new String[] {String.valueOf(playlistId)} //selection args
);
如果您不指定排序参数,我假设query
应根据此列对您的播放列表进行排序
return getContentResolver().query(getPlaylistUri(),
PLAYLIST_QUERY_COLUMNS, null, null, null);
根据ContentResolver
doc:
字符串:如何对行进行排序,格式为SQL ORDER BY子句 (不包括ORDER BY本身)。传递null将使用默认值 排序顺序,可能是无序的。
还有另一个选项 - 创建自己的数据库,它将使用order by
子句存储播放列表的ID,您可以自己维护(即您的项目中有关于播放列表或排序等的更复杂的逻辑)。 )。
修改强>
您确定myCursor
(映射到retVal
)是否包含插入所需的所有数据?您应确保所有必需的列在您要根据URI 插入的每一行的内容值中保留。您检索了(MediaStore.Audio.Playlists.Members)URI,其中包含光标所需的列。但是,您选择的列来自继承的MediaStore.Audio.AudioColumns
。它适用于query
,因为ContentProvider
可能只是加入一些音频表来获取这些。但是现在您想要将数据(根据URI)插入到MediaStore.Audio.Playlists.Members
中,但是您没有指定任何列,因为您所拥有的只是来自链接表(AudioColumns
)的数据。
query
- 选择您要从提供的列中选择的内容update
- 根据选择insert
- 为表格提供所有必需的值最后一件事,遗憾的是你不能强迫第三方提供者尊重DEFAULT_SORT_ORDER
。您可以尝试清除缓存,但我怀疑它会有所帮助。
答案 1 :(得分:0)
在qbeck获得了大量帮助后,我能够解决这个问题。我错过了一些重要的事情......为了保存回到播放列表The specified listener is invoked in the same manner as other operator functions, being passed the current datum d and index i, with the this context as the current DOM element.
,我必须确保它使用了与其架构相同的列...查看{{1} }属性,我可以收集表格的实际字段是什么...... Android Studio以粗体显示这些键,但现在回头看看,我认为这是{什么{ {3}}告诉我。
我使用这些信息来确定我需要更新this page值,所以我首先开始了Uri
的路线,但对于每一行,这对于大型列表需要相当长的时间,我达到某种Cursor undefined错误。然后我尝试删除数据库中的所有行并执行PLAY_ORDER
,这要快得多并且做了我需要它做的事情...现在我的列表在其他音乐应用程序中以此排序顺序出现。
MediaStore.Audio.Playlists.Members.*