扫描设备上的歌曲时的NPE

时间:2018-06-11 00:16:42

标签: java android android-asynctask nullpointerexception

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)

提前致谢,

文斯

0 个答案:

没有答案