音乐服务总是返回null

时间:2017-04-21 12:37:25

标签: android service audio-player android-music-player

我已经制作了一个音乐列表和一个在后台播放音乐的服务但是当我点击列表中的音乐时它总是返回null

我以前从未使用音乐服务,所以我可能在这里做错了 我在采用者中传递错误的位置还是其他什么?

服务

public class MusicService extends Service implements
        MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
        MediaPlayer.OnCompletionListener {

    //media player
    private MediaPlayer player;
    //song list
    private ArrayList<SongModel> songs;
    //current position
    private int songPosn;
    //binder
    private final IBinder musicBind = new MusicBinder();
    //title of current song
    private String songTitle = "";
    //notification id
    private static final int NOTIFY_ID = 1;
    //shuffle flag and random
    private boolean shuffle = false;
    private Random rand;

    public void onCreate() {
        //create the service
        super.onCreate();
        //initialize position
        songPosn = 0;
        //random
        rand = new Random();
        //create player
        player = new MediaPlayer();
        //initialize
        initMusicPlayer();
    }

    public void initMusicPlayer() {
        //set player properties
        player.setWakeMode(getApplicationContext(),
                PowerManager.PARTIAL_WAKE_LOCK);
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        //set listeners
        player.setOnPreparedListener(this);
        player.setOnCompletionListener(this);
        player.setOnErrorListener(this);
    }

    //pass song list
    public void setList(ArrayList<SongModel> theSongs) {
        songs = theSongs;
    }

    //binder
    public class MusicBinder extends Binder {
        public MusicService getService() {
            return MusicService.this;
        }
    }

    //activity will bind to service
    @Override
    public IBinder onBind(Intent intent) {
        return musicBind;
    }

    //release resources when unbind
    @Override
    public boolean onUnbind(Intent intent) {
        player.stop();
        player.release();
        return false;
    }

    //play a song
    public void playSong() {
        //play
        player.reset();
        //get song
        SongModel playSong = songs.get(songPosn);
        //get title
        songTitle = playSong.getSongTitle();
        //get id
        long currSong = playSong.getmSongID();
        //set uri
        Uri trackUri = ContentUris.withAppendedId(
                android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                currSong);
        //set the data source
        try {
            player.setDataSource(getApplicationContext(), trackUri);
        } catch (Exception e) {
            Log.e("MUSIC SERVICE", "Error setting data source", e);
        }
        player.prepareAsync();
    }

    //set the song
    public void setSong(int songIndex) {
        Log.e("click", " service" + songIndex);
        for (int i = 0; i < songs.size(); i++) {
            Log.e("click", songs.get(i).getArtistname() + "  " + songs.get(i).getmSongID());
        }
        songPosn = songIndex;
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        //check if playback has reached the end of a track
        if (player.getCurrentPosition() > 0) {
            mp.reset();
            playNext();
        }
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        Log.v("MUSIC PLAYER", "Playback Error");
        mp.reset();
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        //start playback
        mp.start();
        //notification
        Intent notIntent = new Intent(this, MainActivity.class);
        notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendInt = PendingIntent.getActivity(this, 0,
                notIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification.Builder builder = new Notification.Builder(this);

        builder.setContentIntent(pendInt)
                .setSmallIcon(R.mipmap.ic_play_circle_filled_black_24dp)
                .setTicker(songTitle)
                .setOngoing(true)
                .setContentTitle("Playing")
                .setContentText(songTitle);
        Notification not = builder.build();
        startForeground(NOTIFY_ID, not);
    }

    //playback methods
    public int getPosn() {
        return player.getCurrentPosition();
    }

    public int getDur() {
        return player.getDuration();
    }

    public boolean isPng() {
        return player.isPlaying();
    }

    public void pausePlayer() {
        player.pause();
    }

    public void seek(int posn) {
        player.seekTo(posn);
    }

    public void go() {
        player.start();
    }

    //skip to previous track
    public void playPrev() {
        songPosn--;
        if (songPosn < 0) songPosn = songs.size() - 1;
        playSong();
    }

    //skip to next
    public void playNext() {
        if (shuffle) {
            int newSong = songPosn;
            while (newSong == songPosn) {
                newSong = rand.nextInt(songs.size());
            }
            songPosn = newSong;
        } else {
            songPosn++;
            if (songPosn >= songs.size()) songPosn = 0;
        }
        playSong();
    }

    @Override
    public void onDestroy() {
        stopForeground(true);
    }

    //toggle shuffle
    public void setShuffle() {
        if (shuffle) shuffle = false;
        else shuffle = true;
    }}

活动类

public static MusicService musicSrv;
    private Intent playIntent;
    private boolean musicBound=false;

    public static ArrayList<SongModel> songList;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        load();
    @Override
    protected void onStart() {
        super.onStart();
        if(playIntent==null){
            playIntent = new Intent(this, MusicService.class);
            bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
            startService(playIntent);
        }
    }

private ServiceConnection musicConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
        //get service
        musicSrv = binder.getService();
        //pass list
        musicSrv.setList(songList);
        musicBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        musicBound = false;
    }
};

    private void initLayout() {
        final Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        final String[] cursor_cols = {MediaStore.Audio.Media._ID,
                MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM,
                MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.ALBUM_ID,
                MediaStore.Audio.Media.DURATION};
        final String where = MediaStore.Audio.Media.IS_MUSIC + "=1";
        final Cursor cursor = getContentResolver().query(uri,
                cursor_cols, where, null, null);


        while (cursor.moveToNext()) {
            String artist = cursor.getString(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
            String album = cursor.getString(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
            String track = cursor.getString(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
            String data = cursor.getString(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
            Long albumId = cursor.getLong(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));

            int duration = cursor.getInt(cursor
                    .getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));

            Uri sArtworkUri = Uri
                    .parse("content://media/external/audio/albumart");
            Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);

            Log.e("art", albumArtUri.toString());
            /*Bitmap bitmap = null;
            try {
                bitmap = MediaStore.Images.Media.getBitmap(
                        getActivity().getContentResolver(), albumArtUri);
                bitmap = Bitmap.createScaledBitmap(bitmap, 30, 30, true);

            } catch (FileNotFoundException exception) {
                exception.printStackTrace();
                bitmap = BitmapFactory.decodeResource(getActivity().getResources(),
                        R.mipmap.ic_music_note_black_24dp);
            } catch (IOException e) {

                e.printStackTrace();
            }*/

            SongModel audioListModel = new SongModel();
            audioListModel.setArtistname(artist);
            //  audioListModel.setBitmap(bitmap);
            audioListModel.setmSongTitle(album);
            audioListModel.setmSongTitle(track);
            audioListModel.setData(data);
            audioListModel.setmSongID(albumId);
            audioListModel.setSongLength(String.valueOf(duration));
            audioListModel.setUri(String.valueOf(albumArtUri));
            Log.e("data", "artist :" + artist + "  album  " + album + "  track  " + track + "  data  " + data + "  " + "albumId  " + albumId
                    + "  " + "duration  " + duration + " art:  " + albumArtUri);

            songList.add(audioListModel);

        }

    }


    private class GetAudioListAsynkTask extends AsyncTask<Void, Void, Boolean> {

        private Context context;

        public GetAudioListAsynkTask(Context context) {

            this.context = context;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                initLayout();

                return true;
            } catch (Exception e) {
                return false;

            }

        }

        @Override
        protected void onPostExecute(Boolean result) {
            Collections.sort(songList, new Comparator<SongModel>() {
                public int compare(SongModel a, SongModel b) {
                    return a.getSongTitle().compareTo(b.getSongTitle());
                }
            });

        }
    }

    public void load() {
        songList = new ArrayList<>();
        new GetAudioListAsynkTask(this).execute((Void) null);


    }

适配器类

@Override
public void onBindViewHolder(final Holder holder, final int position) {
    final SongModel songModel = list.get(holder.getAdapterPosition());
    Glide.with(holder.itemView.getContext()).load(songModel.getUri()).error(R.mipmap.ic_music_note_black_24dp).into(holder.imageView);
    holder.imageView.setImageURI(Uri.parse(songModel.getUri()));
    holder.artistname.setText(songModel.getArtistname());
    holder.duration.setText(songModel.getSongLength());
    holder.songname.setText(songModel.getSongTitle());
    holder.itemView.setTag(position);

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            songPicked(position);
        }
    });


}
 private void songPicked(int position) {
    musicSrv.setSong(position);
    musicSrv.playSong();
}

错误日志

    04-21 19:01:37.847 3983-29870/? E/DatabaseUtils: Writing exception to parcel
                                                 java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/audio/media/1 from pid=2608, uid=1000 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
                                                     at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:646)
                                                     at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:493)
                                                     at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:484)
                                                     at android.content.ContentProvider$Transport.openFile(ContentProvider.java:380)
                                                     at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:240)
                                                     at android.os.Binder.execTransact(Binder.java:453)


                                                 [ 04-21 19:01:37.847  2264:16266 D/         ]
                                                 openContentUri(content://media/external/audio/media/1) caught exception -1
04-21 19:01:37.847 2264-16266/? E/MediaPlayerService: Couldn't open fd for content://media/external/audio/media/1
04-21 19:01:37.847 19273-19273/? E/MediaPlayer: Unable to create media player
04-21 19:01:37.847 19273-19273/? E/MUSIC SERVICE: Error setting data source
                                                  java.io.IOException: setDataSource failed.: status=0x80000000
                                                      at android.media.MediaPlayer.nativeSetDataSource(Native Method)
                                                      at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1231)
                                                      at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1215)
                                                      at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1169)
                                                      at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1105)
                                                      at com.nowsip.musicplayer.service.MusicService.playSong(MusicService.java:118)
                                                      at com.nowsip.musicplayer.adapter.SongAdapter.songPicked(SongAdapter.java:86)
                                                      at com.nowsip.musicplayer.adapter.SongAdapter.access$000(SongAdapter.java:24)
                                                      at com.nowsip.musicplayer.adapter.SongAdapter$1.onClick(SongAdapter.java:52)
                                                      at android.view.View.performClick(View.java:5721)
                                                      at android.view.View$PerformClick.run(View.java:22620)
                                                      at android.os.Handler.handleCallback(Handler.java:739)
                                                      at android.os.Handler.dispatchMessage(Handler.java:95)
                                                      at android.os.Looper.loop(Looper.java:148)
                                                      at android.app.ActivityThread.main(ActivityThread.java:7409)
                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
04-21 19:01:37.847 19273-19273/? E/MediaPlayer: prepareAsync called in state 1
04-21 19:01:37.847 19273-19273/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   Process: com.nowsip.musicplayer, PID: 19273
                                                   java.lang.IllegalStateException
                                                       at android.media.MediaPlayer.prepareAsync(Native Method)
                                                       at com.nowsip.musicplayer.service.MusicService.playSong(MusicService.java:122)
                                                       at com.nowsip.musicplayer.adapter.SongAdapter.songPicked(SongAdapter.java:86)
                                                       at com.nowsip.musicplayer.adapter.SongAdapter.access$000(SongAdapter.java:24)
                                                       at com.nowsip.musicplayer.adapter.SongAdapter$1.onClick(SongAdapter.java:52)
                                                       at android.view.View.performClick(View.java:5721)
                                                       at android.view.View$PerformClick.run(View.java:22620)
                                                       at android.os.Handler.handleCallback(Handler.java:739)
                                                       at android.os.Handler.dispatchMessage(Handler.java:95)
                                                       at android.os.Looper.loop(Looper.java:148)
                                                       at android.app.ActivityThread.main(ActivityThread.java:7409)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
04-21 19:01:37.887 19790-19790/? E/Zygote: v2
04-21 19:01:37.887 2608-19795/? E/android.os.Debug: ro.product_ship = true
04-21 19:01:37.887 2608-19795/? E/android.os.Debug: ro.debug_level = 0x4f4c
04-21 19:01:37.887 2608-19795/? E/android.os.Debug: sys.mobilecare.preload = false
04-21 19:01:37.897 19790-19790/? E/Zygote: accessInfo : 0
04-21 19:01:37.897 2608-2803/? E/Qmage: isQIO : stream is not a QIO file
04-21 19:01:38.457 11589-11589/? E/Qmage: isQIO : stream is not a QIO file
04-21 19:01:38.497 11589-11589/? E/Qmage: isQIO : stream is not a QIO file
04-21 19:01:38.497 11589-11589/? E/Qmage: isQIO : stream is not a QIO file

2 个答案:

答案 0 :(得分:0)

确认当您的onServiceConnected方法被调用并且您在服务中设置了歌曲列表时,那时您的songList是否已经过了?

我的意思是当你在线下打电话时,你的歌曲列表可能为空。

    //pass list
    musicSrv.setList(songList);

如果在initLayout方法完成之前连接了服务。

<强>更新

根据以下错误日志行,您需要在清单文件中添加READ_EXTERNAL_STORAGE权限。

  

java.lang.SecurityException:Permission Denial:read   com.android.providers.media.MediaProvider uri   content:// media / external / audio / media / 1 from pid = 2608,uid = 1000   需要android.permission.READ_EXTERNAL_STORAGE,或   grantUriPermission()

使用文件FileDescriptor设置数据源:

//play a song
public void playSong() {
    //play
    player.reset();
    //get song
    SongModel playSong = songs.get(songPosn);
    //get title
    songTitle = playSong.getSongTitle();
    //get id
    long currSong = playSong.getmSongID();
    //set uri
    Uri trackUri = ContentUris.withAppendedId(
            android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
            currSong);
    //set the data source
    try {
        String filePath = getPathFromContentUri(context, trackUri);
        File file = new File(filePath);
        FileInputStream inputStream = new FileInputStream(file);    
        player.setDataSource(inputStream.getFD());
        inputStream.close();
    } catch (Exception e) {
        Log.e("MUSIC SERVICE", "Error setting data source", e);
    }
    player.prepareAsync();
}


public static String getPathFromContentUri(Context context, Uri contentUri) {
    String[] proj = { MediaStore.Audio.Media.DATA };
    Cursor cursor = context.getContentResolver().query(contentUri,
            proj, null, null, null);
    cursor.moveToFirst();

    String path = cursor.getString(cursor
            .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));

    cursor.close();
    return path;
}

结帐this answer了解详情。它可能对你有帮助。

答案 1 :(得分:0)

这不是音乐服务问题,即权限问题

首先,你需要为android manifest提供服务名称 喜欢

之后如果您运行6.0或更高版本,则需要在第一次运行应用程序时请求用户写入读取外部存储的权限 在棒棒糖或套件kat或其他在安装时给予许可但在棉花糖或更多的情况下你手动询问用户

检查一下 Storage permission error in Marshmallow