MainActivity
public class MainActivity extends AppCompatActivity {
private final String TAG = this.getClass().getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
//ToolBar
mToolbar = findViewById(R.id.mToolbar);
setSupportActionBar(mToolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(R.string.library);
}
//Method call permission
checkUserPermission();
scanSongs(false);
}
/**
* Starts the background process of scanning the songs.
*
* @param forceScan If we should scan again. You should set
* this to true if you want to scan again
* the database.
* Otherwise, leave it `false` so we don't
* rescan the songs when this Activity
* is created again for some reason.
*/
void scanSongs(boolean forceScan) {
// Loading all the songs from the device on a different thread.
// We'll only actually do it if they weren't loaded already
//
// See the implementation right at the end of this class.
if ((forceScan) || (! Main.songs.isInitialized())) {
Toast.makeText(MainActivity.this,
"Scanning songs on the device",
Toast.LENGTH_LONG);
new ScanSongs().execute();
}
}
@Override
protected void onStart() {
super.onStart();
//Main.startMusicService(this);
}
public class ScanSongs extends AsyncTask<String, Integer, String> {
/**
* The action we'll do in the background.
*/
@Override
protected String doInBackground(String... params) {
try {
// Will scan all songs on the device
Main.songs.getSongs(MainActivity.this, "external");
return "Finished scanning songs";
}
catch (Exception e) {
Log.e("Couldn't execute task", e.toString());
return "Error occurred when scanning songs";
}
}
/**
* Called once the background processing is done.
*/
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(MainActivity.this,
result,
Toast.LENGTH_LONG).show();
}
}
歌曲列表类
这是我从设备中获取所有歌曲的类。
public class SongList {
private final String TAG = this.getClass().getName();
public ArrayList<QuerySongs> songList = new ArrayList<QuerySongs>();
/**
* Flag that tells if successfully scanned all songs.
*/
private boolean scannedSongs;
/**
* Flag that tells if we're scanning songs right now.
*/
private boolean scanningSongs;
/**
* Tells if we've successfully scanned all songs on
* the device.
*
* This will return `false` both while we're scanning
* for songs and if some error happened while scanning.
*/
public boolean isInitialized() {
return scannedSongs;
}
/**
* Tells if we're currently scanning songs on the device.
*/
public boolean isScanning() {
return scanningSongs;
}
public void getSongs(Context context, String location){
Uri songUri = ((location == "external")?
MediaStore.Audio.Media.INTERNAL_CONTENT_URI:
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
Uri genresUri = ((location == "external")?
MediaStore.Audio.Genres.INTERNAL_CONTENT_URI:
MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI);
Uri playListUri = ((location == "external")?
MediaStore.Audio.Playlists.INTERNAL_CONTENT_URI:
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI);
// Checking for flags so we don't get called twice
if (scanningSongs)
return;
scanningSongs = true;
//Query devices for files (This class provides applications access to the content model.)
ContentResolver contentResolver = context.getContentResolver();
//This interface provides random read-write access to the result set returned by a database query.
Cursor myCursor;
//This is the information i want to get from all the songs on my device.
//Columns for audio file that show up in multiple tables.
String SONG_ID = MediaStore.Audio.Media._ID;
String SONG_DATA = MediaStore.Audio.Media.DATA;
String SONG_ALBUM = MediaStore.Audio.Media.ALBUM;
String SONG_TITLE = MediaStore.Audio.Media.TITLE;
String SONG_ARTIST = MediaStore.Audio.Media.ARTIST;
//This is what i'll retrieve from the song table.
String[] songColumns = {
SONG_ID,
SONG_DATA,
SONG_ALBUM,
SONG_TITLE,
SONG_ARTIST,
};
//Show music files only (IS_MUSIC returns Non-zero if the audio file is music).
final String musicOnly = MediaStore.Audio.Media.IS_MUSIC+"=1";
myCursor = contentResolver.query(songUri, songColumns, musicOnly, null, null);
if (myCursor != null && myCursor.moveToFirst()) {
int songId = myCursor.getInt(myCursor.getColumnIndexOrThrow(SONG_ID));
String songData = myCursor.getString(myCursor.getColumnIndexOrThrow(SONG_DATA));
String songTitle = myCursor.getString(myCursor.getColumnIndexOrThrow(SONG_TITLE));
String songArtist = myCursor.getString(myCursor.getColumnIndexOrThrow(SONG_ARTIST));
String songAlbum = myCursor.getString(myCursor.getColumnIndexOrThrow(SONG_ALBUM));
do {
QuerySongs querySongs = new QuerySongs(songId, songData);
querySongs.setTitle(songTitle);
querySongs.setArtist(songArtist);
querySongs.setAlbum(songAlbum);
//Add the song to the global ArrayList 'songList'.
songList.add(querySongs);
} while (myCursor.moveToNext());
}else{
//What to do if no songs are found?
Log.e(TAG, "No songs found on the device!");
}
myCursor.close();
scannedSongs = true;
scanningSongs = false;
}
public void destroy() {
songList.clear();
}
/**
*
* @return Alphabetically sorted list with all the artists from the songs on the device.
*/
public ArrayList<String> getArtist(){
ArrayList<String> artists = new ArrayList<String >();
for (QuerySongs querySongs: songList){
String artist = querySongs.getArtist();
if (artist!=null && !artist.contains(artist)){
artists.add(artist);
}
}
//Using Collection.sort static operation we can sort ArrayList elements in ascending order.
Collections.sort(artists);
return artists;
}
包含我应用中所有基本逻辑的主类
public class Main {
/**
* All the songs on the device.
*/
public static SongList songs = new SongList();
/**
* Contains the songs that are going to be shown to
* the user on a particular menu.
*
* @note IGNORE THIS - don't mess with it.
*
* Every `ActivityMenu*` uses this temporary variable to
* store subsections of `SongList` and set `ActivityListSongs`
* to display it.
*/
public static ArrayList<QuerySongs> songList = null;
/**
* The MediaPlayerService which plays our songs.
*/
public static MediaPlayerService mediaPlayerService = null;
/**
* Flag that checks if our service is bound or not.
*/
public static Boolean serviceBound;
/**
* TAG to get the class name ( helps for logging;
* Log.v(); // Verbose
* Log.d(); // Debug
* Log.i(); // Info
* Log.w(); // Warning
* Log.e(); // Error
* )
*/
private final String TAG = this.getClass().getName();
/**
* The connection to the MediaPlayerService.
* We've bound to Service, cast the IBinder and get Service instance
* onServiceConnected --> Service is bound. (TRUE)
* onServiceDisconnected --> Service is unbound. (FALSE)
*/
public static ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
mediaPlayerService = binder.getService();
mediaPlayerService.setList(Main.songs.songList);
serviceBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
private static Intent serviceIntent = null;
public static void startMusicService(Context context){
if (serviceIntent == null && mediaPlayerService == null){
serviceIntent = new Intent(context, MediaPlayerService.class);
context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
context.startService(serviceIntent);
}else{
}
}
public static void stopMusicService(Context context){
if (serviceIntent != null){
context.stopService(serviceIntent);
serviceIntent = null;
mediaPlayerService = null;
}
}
public static void destroy(){
songs.destroy();
}
}
摘要问题
因此,当我启动应用程序时,它会显示一个吐司,在后台扫描歌曲时发生错误。 我在MainActivity(Class ScanSongs)中扫描歌曲。 所以问题是nullpointerexception,但我不知道为什么它会导致nullpointer? 这意味着我的SongList类getSongs存在问题。 我一直在工作几个小时找到我的问题,但仍然没有找到它。
有人能帮助我吗?
logcat的; 06-11 00:24:30.793 3158-3366 / com.vince_mp3player.mp3player E /无法执行任务:java.lang.NullPointerException:尝试在一个上调用虚方法'int java.lang.Object.hashCode()' null对象引用 06-11 00:24:30.793 3158-3366 / com.vince_mp3player.mp3player W / System.err:java.lang.NullPointerException:尝试在空对象上调用虚方法'int java.lang.Object.hashCode()'参考 06-11 00:24:30.799 3158-3366 / com.vince_mp3player.mp3player W / System.err:at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:915) 在com.vince_mp3player.mp3player.SongList.getSongs(SongList.java:149) 在com.vince_mp3player.mp3player.activities.MainActivity $ ScanSongs.doInBackground(MainActivity.java:146) 在com.vince_mp3player.mp3player.activities.MainActivity $ ScanSongs.doInBackground(MainActivity.java:136) 在android.os.AsyncTask $ 2.call(AsyncTask.java:304) 在java.util.concurrent.FutureTask.run(FutureTask.java:237) 在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:243) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:607) 在java.lang.Thread.run(Thread.java:761)
提前致谢,
文斯