com.kasungunathilaka.sarigama.service.PlayerService.java Source code

Java tutorial

Introduction

Here is the source code for com.kasungunathilaka.sarigama.service.PlayerService.java

Source

/*
 * </summary>
 * Source File   : PlayerService.java
 * Project      : Sarigama
 * Owner      : Kasun
 * </summary>
 *
 * <license>
 * Copyright 2016 Kasun Gunathilaka
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http:www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * </license>
 */

package com.kasungunathilaka.sarigama.service;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.kasungunathilaka.sarigama.R;
import com.kasungunathilaka.sarigama.business.URLBusiness;
import com.kasungunathilaka.sarigama.domain.Song;
import com.kasungunathilaka.sarigama.domain.URLDomain;
import com.kasungunathilaka.sarigama.ui.HomeActivity;
import com.kasungunathilaka.sarigama.util.PlayerQueue;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import cz.msebera.android.httpclient.Header;

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

    private static final int NOTIFICATION_ID = 9999;
    private static final int REQUEST_CODE = 100;
    private final IBinder playerBinder = new PlayerBinder();
    //region private members
    private MediaPlayer mainPlayer, slavePlayer;
    private LocalBroadcastManager localBroadcastManager;
    private PlayerQueue playerQueue = PlayerQueue.getInstance(this);
    private URLBusiness uRLBusiness;
    //endregion
    private boolean parentLoop = false;
    private boolean random = false;
    private PendingIntent startIntent;
    private PendingIntent playIntent;
    private PendingIntent previousIntent;
    private PendingIntent nextIntent;

    private NotificationIntentReceiver notificationIntentReceiver;

    private static void startIntent(Context context, Class<?> cls) {
        Intent intent = new Intent(context, cls);
        intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    //region overridden method
    @Override
    public IBinder onBind(Intent intent) {
        return playerBinder;
    }

    @Override
    public void onCreate() {
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        startIntent = PendingIntent.getBroadcast(PlayerService.this, REQUEST_CODE,
                new Intent(HomeActivity.ACTION_BRING_FRONT), PendingIntent.FLAG_UPDATE_CURRENT);
        playIntent = PendingIntent.getBroadcast(PlayerService.this, REQUEST_CODE,
                new Intent(HomeActivity.ACTION_PLAY), PendingIntent.FLAG_UPDATE_CURRENT);
        previousIntent = PendingIntent.getBroadcast(PlayerService.this, REQUEST_CODE,
                new Intent(HomeActivity.ACTION_PREV), PendingIntent.FLAG_UPDATE_CURRENT);
        nextIntent = PendingIntent.getBroadcast(PlayerService.this, REQUEST_CODE,
                new Intent(HomeActivity.ACTION_NEXT), PendingIntent.FLAG_UPDATE_CURRENT);
        notificationIntentReceiver = new NotificationIntentReceiver();
        registerReceiver(notificationIntentReceiver, new IntentFilter(HomeActivity.ACTION_PLAY));
        registerReceiver(notificationIntentReceiver, new IntentFilter(HomeActivity.ACTION_BRING_FRONT));
        registerReceiver(notificationIntentReceiver, new IntentFilter(HomeActivity.ACTION_NEXT));
        registerReceiver(notificationIntentReceiver, new IntentFilter(HomeActivity.ACTION_PREV));
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        if (mainPlayer != null) {
            mainPlayer.stop();
            mainPlayer.release();
        }
        mainPlayer = slavePlayer;
        localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARED));
        slavePlayer = null;
        mainPlayer.start();
        int position = playerQueue.getCurrentPosition();
        Song currentSong = playerQueue.getSongByPosition(position);
        setupNotification(currentSong, HomeActivity.NOTIFICATION_TYPE_PLAY);
        localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PLAY));
    }

    public void onCompletion(MediaPlayer mp) {
        localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_COMPLETED));
        this.seekTo(0);
        if (mp.isLooping()) {
            setPlayPause();
            localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARED));
        } else {
            next();
        }
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARE_ERROR));
        mp = null;
        next();
        return true;
    }
    //endregion

    public void onDestroy() {
        if (mainPlayer.isPlaying()) {
            mainPlayer.stop();
        }
        mainPlayer.release();
    }

    //region public methods
    public void startPlayer(int position) {
        try {
            localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARING));
            slavePlayer = new MediaPlayer();
            slavePlayer.setOnPreparedListener(this);
            slavePlayer.setOnErrorListener(this);
            slavePlayer.setOnCompletionListener(this);
            getSongData(position);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void stopPlayerQueue() {
        if (mainPlayer != null) {
            if (mainPlayer.isPlaying()) {
                mainPlayer.stop();
                mainPlayer.release();
                slavePlayer = null;
                mainPlayer = null;
            } else {
                mainPlayer.release();
                slavePlayer = null;
                mainPlayer = null;
            }
        } else {
            slavePlayer = null;
        }
    }

    public void setPlayPause() {
        if (mainPlayer != null) {
            if (mainPlayer.isPlaying()) {
                int position = playerQueue.getCurrentPosition();
                Song currentSong = playerQueue.getSongByPosition(position);
                setupNotification(currentSong, HomeActivity.NOTIFICATION_TYPE_PAUSE);
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PAUSE));
                mainPlayer.pause();
            } else {
                int position = playerQueue.getCurrentPosition();
                Song currentSong = playerQueue.getSongByPosition(position);
                setupNotification(currentSong, HomeActivity.NOTIFICATION_TYPE_PLAY);
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PLAY));
                mainPlayer.start();
            }
        } else {
            int position = playerQueue.getCurrentPosition();
            startPlayer(position);
        }
    }

    public boolean isPlaying() {
        if (mainPlayer == null) {
            return false;
        } else {
            return mainPlayer.isPlaying();
        }
    }

    public void seekTo(int progress) {
        if (mainPlayer != null) {
            mainPlayer.seekTo(progress);
        }
    }

    public void next() {
        try {
            setupNotification(null, HomeActivity.NOTIFICATION_TYPE_DISMISS);
            int position = playerQueue.getCurrentPosition();
            slavePlayer = new MediaPlayer();
            slavePlayer.setOnPreparedListener(this);
            slavePlayer.setOnErrorListener(this);
            slavePlayer.setOnCompletionListener(this);
            if (playerQueue.hasPosition((position + 1))) {
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARING));
                playerQueue.setCurrentPosition((position + 1));
                Song currentSong = playerQueue.getSongByPosition((position + 1));
                if (currentSong.getSongSource() == null) {
                    getSongData(playerQueue.getCurrentPosition());
                } else {
                    slavePlayer.setDataSource(currentSong.getSongSource());
                    slavePlayer.prepareAsync();
                }
            } else if (parentLoop) {
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARING));
                playerQueue.setCurrentPosition(0);
                Song currentSong = playerQueue.getSongByPosition(0);
                if (currentSong.getSongSource() == null) {
                    getSongData(playerQueue.getCurrentPosition());
                } else {
                    slavePlayer.setDataSource(currentSong.getSongSource());
                    slavePlayer.prepareAsync();
                }
            } else {
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_COMPLETED));
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_QUEUE_COMPLETED));
                this.seekTo(0);
                mainPlayer.stop();
                mainPlayer.release();
                mainPlayer = null;
                slavePlayer = null;
                playerQueue.setCurrentPosition(0);
                Toast.makeText(PlayerService.this, "Song queue end reached", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void previous() {
        try {
            int position = playerQueue.getCurrentPosition();
            slavePlayer = new MediaPlayer();
            slavePlayer.setOnPreparedListener(this);
            slavePlayer.setOnErrorListener(this);
            slavePlayer.setOnCompletionListener(this);
            if (playerQueue.hasPosition((position - 1))) {
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_PREPARING));
                playerQueue.setCurrentPosition((position - 1));
                Song currentSong = playerQueue.getSongByPosition((position - 1));
                if (currentSong.getSongSource() == null) {
                    getSongData(playerQueue.getCurrentPosition());
                } else {
                    slavePlayer.setDataSource(currentSong.getSongSource());
                    slavePlayer.prepareAsync();
                }
            } else {
                localBroadcastManager.sendBroadcast(new Intent(HomeActivity.ON_COMPLETED));
                this.seekTo(0);
                mainPlayer.stop();
                mainPlayer.release();
                mainPlayer = null;
                slavePlayer = null;
                playerQueue.setCurrentPosition(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public int getDuration() {
        if (mainPlayer == null) {
            return 0;
        } else {
            return mainPlayer.getDuration();
        }
    }

    public int getCurrentPosition() {

        if (mainPlayer == null) {
            return 0;
        } else {
            return mainPlayer.getCurrentPosition();
        }
    }

    public boolean isQueueOnLoop() {
        return parentLoop;
    }

    public void setQueueOnLoop(boolean loop) {
        this.parentLoop = loop;
    }

    public boolean isSongOnLoop() {
        if (mainPlayer != null) {
            return mainPlayer.isLooping();
        } else {
            return false;
        }
    }

    public void setSongOnLoop(boolean loop) {
        if (mainPlayer != null) {
            mainPlayer.setLooping(loop);
        }
    }

    public boolean isPlayerNull() {
        return mainPlayer != null;
    }

    public boolean isRandom() {
        return random;
    }
    //endregion

    public void setRandom(boolean random) {
        this.random = random;
    }

    //region private methods
    private void getSongData(final int position) {
        try {
            uRLBusiness = new URLBusiness(PlayerService.this);
            if (uRLBusiness.Exist(playerQueue.getSongByPosition(position).getSongItem())) {
                getSongDetail(uRLBusiness.SelectSingle(playerQueue.getSongByPosition(position).getSongItem())
                        .getUrlContent(), position);
                uRLBusiness.Close();
            } else {
                AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
                asyncHttpClient.post(PlayerService.this, playerQueue.getSongByPosition(position).getSongItem(),
                        null, new AsyncHttpResponseHandler() {
                            @Override
                            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                                try {
                                    URLDomain uRLDomain = new URLDomain();
                                    uRLDomain.setUrlAddress(playerQueue.getSongByPosition(position).getSongItem());
                                    uRLDomain.setUrlContent(new String(responseBody));
                                    uRLBusiness.Save(uRLDomain);
                                    uRLBusiness.Close();
                                    getSongDetail(new String(responseBody), position);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

                            @Override
                            public void onFailure(int statusCode, Header[] headers, byte[] responseBody,
                                    Throwable error) {
                                Toast.makeText(PlayerService.this, "Song added failed", Toast.LENGTH_SHORT).show();
                            }
                        });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void getSongDetail(String body, int position) {
        try {
            int startIndex = body.indexOf("profile-pic");
            startIndex = startIndex + 18;
            int endIndex = body.indexOf("alt", startIndex + 1);
            endIndex = endIndex - 2;
            String imageUrl = body.substring(startIndex, endIndex).trim();
            System.out.println(imageUrl);
            startIndex = body.indexOf("<source");
            startIndex = startIndex + 13;
            endIndex = body.indexOf("type", startIndex + 1);
            endIndex = endIndex - 2;
            String url = body.substring(startIndex, endIndex).trim();
            System.out.println(url);
            url = url.replace(" ", "%20");
            playerQueue.getSongByPosition(position).setSongSource(url);
            playerQueue.getSongByPosition(position).setSongImage(imageUrl);
            slavePlayer
                    .setDataSource(playerQueue.getSongByPosition(playerQueue.getCurrentPosition()).getSongSource());
            slavePlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void setupNotification(Song song, String notificationType) {
        Bitmap remote_picture = null;
        RemoteViews smallNotification;
        RemoteViews bigNotification;
        Notification notification;

        NotificationManager notificationManager = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);

        if (song != null) {
            if (song.getSongImage().contentEquals("http://sarigama.lk/img/songs/default.jpg")) {
                remote_picture = BitmapFactory.decodeResource(PlayerService.this.getResources(),
                        R.drawable.default_song_art);
            } else {
                try {
                    remote_picture = BitmapFactory
                            .decodeStream((InputStream) new URL(song.getSongImage()).getContent());
                } catch (Exception e) {
                    remote_picture = BitmapFactory.decodeResource(PlayerService.this.getResources(),
                            R.drawable.default_song_art);
                    e.printStackTrace();
                }
            }
        }

        switch (notificationType) {
        case HomeActivity.NOTIFICATION_TYPE_PLAY:
            try {
                smallNotification = new RemoteViews(getPackageName(), R.layout.notification_layout_small);
                smallNotification.setImageViewBitmap(R.id.ivSmallNotificationSongImage, remote_picture);
                smallNotification.setTextViewText(R.id.tvSmallNotificationSong, song.getSongTitle());
                smallNotification.setTextViewText(R.id.tvSmallNotificationArtist, song.getSongArtist());
                smallNotification.setImageViewResource(R.id.ibSmallPlay, R.drawable.ic_pause_white);
                smallNotification.setOnClickPendingIntent(R.id.flSmallPlay, playIntent);
                smallNotification.setOnClickPendingIntent(R.id.ivSmallNext, nextIntent);

                bigNotification = new RemoteViews(getPackageName(), R.layout.notification_layout_big);
                bigNotification.setImageViewBitmap(R.id.ivBigNotificationSongImage, remote_picture);
                bigNotification.setTextViewText(R.id.tvBigNotificationSong, song.getSongTitle());
                bigNotification.setTextViewText(R.id.tvBigNotificationArtist, song.getSongArtist());
                bigNotification.setImageViewResource(R.id.ibBigPlay, R.drawable.ic_pause_white);
                bigNotification.setOnClickPendingIntent(R.id.ibBigNext, nextIntent);
                bigNotification.setOnClickPendingIntent(R.id.ibBigPlay, playIntent);
                bigNotification.setOnClickPendingIntent(R.id.ibBigPrevious, previousIntent);

                notification = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_play_white)
                        .setAutoCancel(false).setOngoing(true).setContent(smallNotification)
                        .setContentIntent(startIntent).build();

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    notification.bigContentView = bigNotification;
                }
                notificationManager.notify(NOTIFICATION_ID, notification);
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
        case HomeActivity.NOTIFICATION_TYPE_PAUSE:
            try {
                smallNotification = new RemoteViews(getPackageName(), R.layout.notification_layout_small);
                smallNotification.setImageViewResource(R.id.ibSmallPlay, R.drawable.ic_play_white);

                bigNotification = new RemoteViews(getPackageName(), R.layout.notification_layout_big);
                bigNotification.setImageViewBitmap(R.id.ivBigNotificationSongImage, remote_picture);
                bigNotification.setTextViewText(R.id.tvBigNotificationSong, song.getSongTitle());
                bigNotification.setTextViewText(R.id.tvBigNotificationArtist, song.getSongArtist());
                bigNotification.setImageViewResource(R.id.ibBigPlay, R.drawable.ic_play_white);
                bigNotification.setOnClickPendingIntent(R.id.ibBigNext, nextIntent);
                bigNotification.setOnClickPendingIntent(R.id.ibBigPlay, playIntent);
                bigNotification.setOnClickPendingIntent(R.id.ibBigPrevious, previousIntent);

                notification = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_pause_white)
                        .setOngoing(false).setAutoCancel(false).setContent(smallNotification)
                        .setContentIntent(startIntent).build();

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    notification.bigContentView = bigNotification;
                }
                notificationManager.notify(NOTIFICATION_ID, notification);
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
        case HomeActivity.NOTIFICATION_TYPE_DISMISS:
            notificationManager.cancel(NOTIFICATION_ID);
            break;
        }
    }
    //endregion

    //region public sub class
    public class PlayerBinder extends Binder {
        public PlayerService getService() {
            return PlayerService.this;
        }
    }

    private class NotificationIntentReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
            case HomeActivity.ACTION_NEXT:
                next();
                break;
            case HomeActivity.ACTION_PREV:
                previous();
                break;
            case HomeActivity.ACTION_PLAY:
                setPlayPause();
                break;
            case HomeActivity.ACTION_BRING_FRONT:
                startIntent(getBaseContext(), HomeActivity.class);
                break;
            }
        }
    }
    //endregion
}