Android MediaPlayer在完成之前调用onCompletion

时间:2017-07-28 10:21:58

标签: android service

我正在尝试实现从URL播放音乐的Android前台服务。 MediaPlayer正常播放并播放歌曲,但过了一会儿,当歌曲未完成时,它会调用onCompletion()。我设置了一个onErrorListener,但它没有被调用。

我做了什么:

  1. 检查了与网址的连接>行
  2. 检查歌曲持续时间>行
  3. 实施部分唤醒锁定> ?
  4. 该应用不会崩溃,MediaPlayer只是致电onCompletion,我不知道该怎么办。这里有服务和活动代码。提前致谢:

    SERVICE:

    public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener{
    
    //FILTER FOR BROADCASTS
    public final static String ACTION_FILTER = "ACTION_HHGROUPS";
    
    //MEDIA ACTIONS:
    public final static String ACTION_PLAY_ONE = "ACTION_PLAY_ONE";
    
    //FOREGROUND:
    public static boolean IS_FOREGROUND = false;
    public final static int FOREGROUND_SERVICE = 101;
    public final static String ACTION_START_FOREGROUND = "ACTION_START_FOREGROUND";
    public final static String ACTION_STOP_FOREGROUND = "ACTION_STOP_FOREGROUND";
    
    //EXTRAS:
    public final static String EXTRA_URL = "EXTRA_URL";
    
    private MediaPlayer mPlayer;
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        switch (intent.getAction()) {
            case ACTION_START_FOREGROUND:
                Log.v("SERVICIO", "ACTION_START_FOREGROUND");
                IS_FOREGROUND = true;
                showNotification();
                break;
            case ACTION_PLAY_ONE:
                Log.v("SERVICIO", "ACTION_PLAY_ONE");
                initializeMediaPlayer(
                    intent.getStringExtra(MusicService.EXTRA_URL);
                break;
            case ACTION_STOP_FOREGROUND:
                Log.v("SERVICIO", "ACTION_STOP_FOREGROUND");
                IS_FOREGROUND = false;
                stopForeground(true);
                stopSelf();
                break;
        }
        return Service.START_STICKY;
    }
    
    public void initializePlayer(String url) {
        if(mPlayer == null) {
            mPlayer = new MediaPlayer();
            mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
            mPlayer.setOnPreparedListener(this);
            mPlayer.setOnCompletionListener(this);
            mPlayer.setOnErrorListener(this);
            if(url != null && !url.isEmpty()) {
                try {
                    mPlayer.setDataSource(url);
                    mPlayer.prepareAsync();
                } catch (IOException e) {
                    Log.v("SERVICIO-MEDIA", "IOException");
                    e.printStackTrace();
                }
            }
        } else {
            try {
                mPlayer.reset();
                mPlayer.setDataSource(url);
                mPlayer.prepareAsync();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.e("SERVICIO", "OnTaskRemoved");
        if(IS_FOREGROUND)
            stopForeground(true);
        stopSelf();
    }
    
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        Log.v("SERVICIO", "onCompletion");
    }
    
    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        mediaPlayer.start();
        Log.v("SERVICIO-MEDIA", "onPrepared. Duration: " + mediaPlayer.getDuration());
    }
    
    @Override
    public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
        Log.v("SERVICIO", "onError");
        return true;
    }
    
    private void showNotification() {
        Intent notificationIntent = new Intent(this, PruebaActivity.class);
        notificationIntent.setAction(ACTION_NOTIFICATION_MAIN);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);
    
        Intent previousIntent = new Intent(this, MusicService.class);
        previousIntent.setAction(ACTION_NOTIFICATION_PREV);
        PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
                previousIntent, 0);
    
        Intent playIntent = new Intent(this, MusicService.class);
        playIntent.setAction(ACTION_NOTIFICATION_PLAY);
        PendingIntent pplayIntent = PendingIntent.getService(this, 0,
                playIntent, 0);
    
        Intent nextIntent = new Intent(this, MusicService.class);
        nextIntent.setAction(ACTION_NOTIFICATION_NEXT);
        PendingIntent pnextIntent = PendingIntent.getService(this, 0,
                nextIntent, 0);
    
        Intent deleteIntent = new Intent(this, MusicService.class);
        PendingIntent pdeleteIntent = PendingIntent.getService(this, 666,deleteIntent,
                PendingIntent.FLAG_CANCEL_CURRENT);
    
        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("Content title")
                .setTicker("This is a Ticker...")
                .setContentText("Context text")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .addAction(android.R.drawable.ic_media_previous, "Prev",
                        ppreviousIntent)
                .addAction(android.R.drawable.ic_media_play, "Play",
                        pplayIntent)
                .addAction(android.R.drawable.ic_media_next, "Next",
                        pnextIntent).build();
        startForeground(FOREGROUND_SERVICE, notification);
    }
    }
    

    活动:

    public class PruebaActivity extends AppCompatActivity implements View.OnClickListener {
    
    String url = "http://stream.hhgroups.com/1-Ey7w3haY2RtcqiutMX1SylvqnvkP1oFuKo4765uI6Dc-Isusko%20y%20Sbrv%20-%20Marionetas%20(Adelanto)%20-%20www.HHGroups.com/";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_prueba);
    
        findViewById(R.id.btnPlaySong).setOnClickListener(this);
        Button btnForeground = findViewById(R.id.btnStartForeground);
        btnForeground.setOnClickListener(this);
        if(MusicService.IS_FOREGROUND)
            btnForeground.setText("STOP FOREGROUND");
        else
            btnForeground.setText("START FOREGROUND");
    }
    
    @SuppressLint("SetTextI18n")
    @Override
    public void onClick(View view) {
        switch(view.getId()) {
            case R.id.btnStartForeground:
                if(MusicService.IS_FOREGROUND) {
                    Toast.makeText(PruebaActivity.this, "STOPPING FOREGROUND", Toast.LENGTH_SHORT).show();
                    startService(new Intent(PruebaActivity.this, MusicService.class)
                            .setAction(MusicService.ACTION_STOP_FOREGROUND));
                    ((Button)view).setText("START FOREGROUND");
                } else {
                    Toast.makeText(PruebaActivity.this, "SETTING FOREGROUND", Toast.LENGTH_SHORT).show();
                    startService(new Intent(PruebaActivity.this, MusicService.class)
                            .setAction(MusicService.ACTION_START_FOREGROUND));
                    ((Button)view).setText("STOP FOREGROUND");
                }
                break;
            case R.id.btnPlaySong:
                if(MusicService.IS_FOREGROUND) {
                    Log.v("SERVICIO-ACTIVITY", "btnPlaySong -> Foreground ON");
                    Toast.makeText(PruebaActivity.this, "PLAYING SONG", Toast.LENGTH_SHORT).show();
                    startService(new Intent(PruebaActivity.this, MusicService.class)
                            .setAction(MusicService.ACTION_PLAY_ONE)
                            .putExtra(MusicService.EXTRA_URL, url));
                } else {
                    Log.v("SERVICIO-ACTIVITY", "btnPlaySong -> Foreground OFF");
                    Toast.makeText(PruebaActivity.this, "SETTING FOREGROUND", Toast.LENGTH_SHORT).show();
                    startService(new Intent(PruebaActivity.this, MusicService.class)
                            .setAction(MusicService.ACTION_START_FOREGROUND));
                    Toast.makeText(PruebaActivity.this, "PLAYING SONG", Toast.LENGTH_SHORT).show();
                    startService(new Intent(PruebaActivity.this, MusicService.class)
                            .setAction(MusicService.ACTION_PLAY_ONE)
                            .putExtra(MusicService.EXTRA_URL, url));
                }
                break;
        }
    }
    }
    

1 个答案:

答案 0 :(得分:1)

看起来像服务器端问题。您的测试网址有“Content-Disposition:inline;”在响应标题中,这意味着它是下载而不是流式传输。

HTTP/1.1 200 OK
Date: Fri, 28 Jul 2017 18:20:20 GMT
Server: Apache
Cache-Control: max-age=2678400
Content-Length: 10562918
Content-Disposition: inline; filename="540b4a08d51bc718f1e7f30313af9526.mp3"
Keep-Alive: timeout=10, max=800
Connection: Keep-Alive
Content-Type: audio/mpeg

更改您的测试网址。