I want to build an Music-App and my Musicplayer should only stop, if the User touchs on Stop in the notification.
The Music should not stop if the User closes the App (if possible, also if the User cleans the App-History)!
I'm playing music with a Service:
public class MusicService extends Service
implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener,
AudioManager.OnAudioFocusChangeListener {
//region Variables
private MediaPlayer mediaPlayer;
private Song[] sSongs;
private int iSongPosition;
private PlayMode playMode;
private static final int NOTIFY_ID = 1;
private final IBinder musicBinder = new MusicBinder();
private AudioManager audioManager;
private Handler handler;
public ServiceInterface serviceInterface;
private Notification notification;
//endregion
//region Service-Methods
#Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
iSongPosition = 0;
playMode = PlayMode.PASS;
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
int iAudioReqResult = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (iAudioReqResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
new AlertDialog.Builder(this)
.setTitle("Sorry.")
.setMessage("Musixs wasn't able to gain the AudioStream garanted!")
.setCancelable(false)
.show();
}
handler = new Handler();
serviceInterface = new ServiceInterface() {
#Override
public void MP_PlayPause() {
if (isPlaying()) {
pause();
}
else {
start();
}
}
#Override
public void MP_PlayPrev() {
playPrev();
}
#Override
public void MP_PlayNext() {
playNext();
}
#Override
public boolean MP_isPlaying() {
return isPlaying();
}
#Override
public int MP_getDuration() {
return getDuration();
}
#Override
public int MP_getCurrentPosition() {
return getCurrentPosition();
}
#Override
public Song MP_getActualSong() {
return getActualSong();
}
#Override
public void MP_seekTo(int pos) {
seekTo(pos);
}
};
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return musicBinder;
}
#Override
public boolean onUnbind(Intent intent) {
mediaPlayer.stop();
mediaPlayer.release();
return super.onUnbind(intent);
}
#Override
public void onCompletion(MediaPlayer mp) {
mp.reset();
if (playMode == PlayMode.REPEAT_SINGLE) {
playSong(iSongPosition);
return;
}
if (playMode == PlayMode.SHUFFLE) {
iSongPosition = new Random().nextInt(sSongs.length);
playSong(iSongPosition);
return;
}
iSongPosition++;
if (iSongPosition == sSongs.length) {
if (playMode == PlayMode.REPEAT_ALL) {
iSongPosition = 0;
playSong(iSongPosition);
}
else {
mp.stop();
mp.release();
}
}
else {
playSong(iSongPosition);
}
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
Intent notIntent = new Intent(getApplicationContext(), PlayActivity.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent notPendignIntent = PendingIntent.getActivity(getApplicationContext(), 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PlayActivity.setServiceInterface(serviceInterface);
Notification.Builder nBuilder = new Notification.Builder(this);
nBuilder.setContentIntent(notPendignIntent)
.setSmallIcon(android.R.drawable.ic_media_play)
.setTicker(getActualSong().getTitle())
.setOngoing(true)
.setContentTitle(getString(R.string.app_name))
.setContentText(getActualSong().getTitle());
notification = nBuilder.build();
startForeground(NOTIFY_ID, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public void onAudioFocusChange(int focusChange) {
audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}
//endregion
//region Methods
public void setSongs(Song[] songs) {
sSongs = songs;
}
public void setPlayMode(PlayMode mode) {
playMode = mode;
}
public void playSong(int index) {
mediaPlayer.reset();
iSongPosition = index;
Song playSong = sSongs[iSongPosition];
long playSongID = playSong.getID();
Uri trackUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, playSongID);
try {
mediaPlayer.setDataSource(getApplicationContext(), trackUri);
}
catch (IOException ioe) {
ioe.printStackTrace();
}
mediaPlayer.prepareAsync();
}
public void playNext() {
iSongPosition++;
if (iSongPosition == sSongs.length) {
iSongPosition = 0;
}
playSong(iSongPosition);
}
public void playPrev() {
iSongPosition--;
if (iSongPosition < 0) {
iSongPosition = sSongs.length - 1;
}
playSong(iSongPosition);
}
public Song getActualSong() {
return sSongs[iSongPosition];
}
public int getActualSongPosition() {
return iSongPosition;
}
public PlayMode getPlayMode() {
return playMode;
}
//region MediaController-Methods
public void start() {
mediaPlayer.start();
startForeground(NOTIFY_ID, notification);
}
public void pause() {
mediaPlayer.pause();
stopForeground(true);
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return (mediaPlayer.getCurrentPosition() * 100) / mediaPlayer.getDuration();
}
public boolean canPause() {
return mediaPlayer.isPlaying();
}
public boolean canSeekBackward() {
return mediaPlayer.getCurrentPosition() != 0;
}
public boolean canSeekForward() {
return mediaPlayer.getCurrentPosition() == mediaPlayer.getDuration();
}
//endregion
//endregion
public class MusicBinder extends Binder {
public MusicService getService() {
return MusicService.this;
}
}
And my Service is started in MainActivity:
#Override
protected void onStart() {
super.onStart();
if (playIntent == null) {
playIntent = new Intent(this, MusicService.class);
bindService(playIntent, musicServiceConn, BIND_AUTO_CREATE);
startService(playIntent);
}
}
My ServiceConnection:
musicServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder musicBinder = (MusicService.MusicBinder) service;
musicService = musicBinder.getService();
bMusicServiceConnected = true;
musicService.setSongs(sSongs);
}
#Override
public void onServiceDisconnected(ComponentName name) {
bMusicServiceConnected = false;
}
};
Actually, my MediaPlayer stops, if I close the app (clear App-History) or press the Back-Button.
The full code:
https://github.com/guger/Musixs
I hope you can help me!
Thanks!
You need to override onStartCommand in the service and return START_STICKY.
Related
I have almost a week figuring out how should I have one instance of exoplayer in background.
I want to use this instance in a playerview and in notification as well. Problem I am facing now, the player plays well, after a time it pauses (to release resource I guess), but when i click play it plays again, when i click other oudio, I get two audio playing at same time.
Here are my codes.
------------------------ BACKGROUND SERVICE --------------------------------------
public class BackgroundPlayingService extends Service {
public static PlayerNotificationManager playerNotificationManager;
public static ExoPlayer exoPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (this.exoPlayer == null){
createPlayer();
}
/////////////////THIS WAS ADDED LATER
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
exoPlayer.pause();
exoPlayer = null;
playerNotificationManager.setPlayer(null);
}
private void createPlayer(){
exoPlayer = new ExoPlayer.Builder(this).build();
MediaItem mediaItem;
try {
mediaItem = MediaItem.fromUri(Uri.parse(DataUtility.playingUrl));
}catch (Exception e){
mediaItem = MediaItem.fromUri(Uri.parse("https://server13.mp3quran.net/husr/062.mp3"));
}
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
exoPlayer.addListener(new Player.Listener() {
#Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
if (playbackState==Player.STATE_READY){
try {
ThePlayingActivity.downloadBtn.setVisibility(View.VISIBLE);
showNotification();
}catch (Exception ignore){
}
}
if (playbackState == Player.STATE_BUFFERING) {
try {
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
}catch (Exception e){
}
} else {
try {
ThePlayingActivity.myProgress.setVisibility(View.GONE);
}catch (Exception e){
}
}
}
#Override
public void onIsLoadingChanged(boolean isLoading) {
Player.Listener.super.onIsLoadingChanged(isLoading);
}
#Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();
}
playerNotificationManager.setPlayer(null);
}catch (Exception ignore){
}
}
});
exoPlayer.play();
try {
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
}catch (Exception e){
Log.d("background", "createPlayer: set player to view"+e.getLocalizedMessage());
}
}
public static void setNewPlayeData(){
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(DataUtility.playingUrl));
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
try {
ThePlayingActivity.myPlayerView.setPlayer(exoPlayer);
}catch (Exception e){
Log.d("background", "createPlayer: set player to view"+e.getLocalizedMessage());
}
}
public void showNotification() {
playerNotificationManager = new PlayerNotificationManager.Builder(this, 151,
this.getResources().getString(R.string.app_name))
.setChannelNameResourceId(R.string.app_name)
.setChannelImportance(IMPORTANCE_HIGH)
.setMediaDescriptionAdapter(new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public CharSequence getCurrentContentTitle(Player player) {
return player.getCurrentMediaItem().mediaMetadata.displayTitle;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
return null;
}
#Nullable
#Override
public CharSequence getCurrentContentText(Player player) {
return Objects.requireNonNull(player.getCurrentMediaItem()).mediaMetadata.artist;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
}).setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
}
#Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
PlayerNotificationManager.NotificationListener.super.onNotificationPosted(notificationId, notification, ongoing);
}
})
.build();
playerNotificationManager.setUseStopAction(false);
try {
playerNotificationManager.setPlayer(exoPlayer);
}catch (Exception e){
}
}
}
-----------------------HERE IS THE ACTIVITY WITH PLAYER ----------------------------------
public class ThePlayingActivity extends AppCompatActivity {
private static final int PERMISION_STORAGE_CODE = 100;
private ProgressBar downloadingProgress;
public static ProgressBar myProgress;
public static Dialog dialog;
private ConstraintLayout layoutForSnack;
long downloadId;
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
String myurl;
public static PlayerControlView myPlayerView;
private TextView currentPlaying, downloadingTv;
public static Button downloadBtn;
private String thePlayingSura;
private final BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID,-1);
if (downloadId == id){
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
downloadBtn.setText("DOWNLOADED");
downloadBtn.setBackgroundColor(Color.TRANSPARENT);
downloadBtn.setTextColor(Color.BLACK);
downloadBtn.setClickable(false);
Toast.makeText(context, "DOWNLOAD COMPLETED", Toast.LENGTH_SHORT).show();
}
}
};
#SuppressLint("SetTextI18n")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_the_playing);
myPlayerView = findViewById(R.id.playerView);
Intent dataIntent = getIntent();
myurl = dataIntent.getStringExtra("theUrl");
if (BackgroundPlayingService.exoPlayer == null){
startService();}else{
BackgroundPlayingService.setNewPlayeData();
myPlayerView.setPlayer(BackgroundPlayingService.exoPlayer);
}
keepActivityAlive();
registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadingProgress = findViewById(R.id.downloadProgress);
downloadingTv = findViewById(R.id.downloadingWaitTv);
currentPlaying = findViewById(R.id.currentPlaying);
downloadBtn = findViewById(R.id.downloadbtn);
downloadBtn.setVisibility(View.GONE);
myProgress = findViewById(R.id.progressBar2);
myProgress.setVisibility(View.GONE);
layoutForSnack = findViewById(R.id.constraintLayout);
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
thePlayingSura = dataIntent.getStringExtra("sendSuraName");
currentPlaying.setText(thePlayingSura+" - " + DataUtility.theKariName);
/////////////end of ids
showLoadingDialog();
/////////////////download
downloadBtn.setOnClickListener(view -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){
//todo ask permission
String permissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions,PERMISION_STORAGE_CODE);
}else{
downloadStaffs();
}
}else {
//TODO DOWNLOAD
downloadStaffs();
}
});
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
}
#Override
public void onBackPressed() {
super.onBackPressed();
//todo fire service (may be)
}
private void showLoadingDialog() {
dialog = new Dialog(ThePlayingActivity.this);
dialog.setContentView(R.layout.dialog_loading_quran);
dialog.setCancelable(false);
dialog.show();
}
private void showSnackBar() {
Snackbar snackbar = Snackbar.make(layoutForSnack, "THERE WAS ON ERROR, CHECK YOUR INTERNET CONNECTION", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("RETRY", view -> {
});
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case PERMISION_STORAGE_CODE:{
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
// we have permission
//todo Download
downloadStaffs();
}else{
Toast.makeText(ThePlayingActivity.this , "PERMISSION DENIED... CAN NOT DOWNLOAD", Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
try {
if (wakeLock.isHeld()){
wakeLock.release();}
}catch (Exception ignore){
}
}
private void downloadStaffs(){
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DataUtility.playingUrl));
request.setDescription("Download File");
request.setTitle(thePlayingSura);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, thePlayingSura+" - "+ DataUtility.theKariName+".mp3");
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
this.downloadId = downloadId;
final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.downloadProgress);
downloadingTv.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
#SuppressLint("Range")
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
#SuppressLint("Range") int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
#SuppressLint("Range") int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
final double dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setProgress((int) dl_progress);
}
});
Log.d("MESSAGES", statusMessage(cursor));
cursor.close();
}
}
}).start();
}
#SuppressLint("Range")
private String statusMessage(Cursor c) {
String msg = "???";
switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
msg = "Download failed!";
break;
case DownloadManager.STATUS_PAUSED:
msg = "Download paused!";
break;
case DownloadManager.STATUS_PENDING:
msg = "Download pending!";
break;
case DownloadManager.STATUS_RUNNING:
msg = "Download in progress!";
break;
case DownloadManager.STATUS_SUCCESSFUL:
msg = "Download complete!";
break;
default:
msg = "Download is nowhere in sight";
break;
}
return (msg);
}
}
private void keepActivityAlive(){
powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"QuranAudio:WakeLock");
}
private void startService(){
Intent i = new Intent(this, BackgroundPlayingService.class);
startService(i);
}
}
I figured it out.
I had to keep most of my business inside in onStartCommand
public class BackgroundPlayingService extends Service {
public static final String TAG = "bck_service";
public static ExoPlayer player;
public static PlayerNotificationManager playerNotificationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String url = DataUtility.playingUrl;
if (url==null){
url = "https://server8.mp3quran.net/afs/Rewayat-AlDorai-A-n-Al-Kisa-ai/025.mp3";
}
if (player == null){
player = createPlayerIfNull();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(url));
player.setMediaItem(mediaItem);
player.prepare();
player.addListener(new Player.Listener() {
#Override
public void onEvents(Player player, Player.Events events) {
}
#Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
if (playbackState==Player.STATE_READY){
try {
ThePlayingActivity.downloadBtn.setVisibility(View.VISIBLE);
showNotification();
}catch (Exception ignore){
}
}
if (playbackState == Player.STATE_BUFFERING) {
try {
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
}catch (Exception e){
}
} else {
try {
ThePlayingActivity.myProgress.setVisibility(View.GONE);
}catch (Exception e){
}
}
}
#Override
public void onIsLoadingChanged(boolean isLoading) {
Player.Listener.super.onIsLoadingChanged(isLoading);
}
#Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
try {
if (ThePlayingActivity.dialog.isShowing()){
ThePlayingActivity.dialog.dismiss();}
}catch (Exception ignore){
}
}
});
player.play();
try {
ThePlayingActivity.myPlayerView.setPlayer(player);
}catch (Exception ignore){}
}
//notification
createNotificationChannel();
Intent i = new Intent(this,BackgroundPlayingService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,0);
Notification notification = new NotificationCompat.Builder(this,"myChannelId")
.setContentTitle("QURAN IS PLAYING")
.setContentText("This means that Qur-an app is open. You can close it from app exit menu")
.setSmallIcon(androidx.core.R.drawable.notification_icon_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1,notification);
return START_STICKY;
}
public ExoPlayer createPlayerIfNull() {
if (player == null) {
player = new ExoPlayer.Builder(BackgroundPlayingService.this).build();
ThePlayingActivity.myProgress.setVisibility(View.VISIBLE);
try {
ThePlayingActivity.dialog.show();
}catch (Exception e){
Log.d(TAG, "createPlayerIfNull: ");
}
}
return player;
}
private void createNotificationChannel(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel("myChannelId","qur-anAudiChannel", NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
player.stop();
player = null;
stopForeground(true);
}
public void showNotification() {
playerNotificationManager = new PlayerNotificationManager.Builder(this, 151,
this.getResources().getString(R.string.app_name))
.setChannelNameResourceId(R.string.app_name)
.setChannelImportance(IMPORTANCE_HIGH)
.setMediaDescriptionAdapter(new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public CharSequence getCurrentContentTitle(Player player) {
return player.getCurrentMediaItem().mediaMetadata.displayTitle;
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
return null;
}
#Nullable
#Override
public CharSequence getCurrentContentText(Player player) {
return Objects.requireNonNull(player.getCurrentMediaItem()).mediaMetadata.artist;
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
}).setNotificationListener(new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
}
#Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
PlayerNotificationManager.NotificationListener.super.onNotificationPosted(notificationId, notification, ongoing);
}
})
.build();
playerNotificationManager.setUseStopAction(false);
try {
playerNotificationManager.setPlayer(player);
}catch (Exception e){
}}
}
-------------------- player view activity ------------------------------------
public class ThePlayingActivity extends AppCompatActivity {
private static final int PERMISION_STORAGE_CODE = 100;
private ProgressBar downloadingProgress;
public static ProgressBar myProgress;
public static Dialog dialog;
private ConstraintLayout layoutForSnack;
long downloadId;
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
String myurl;
public static PlayerControlView myPlayerView;
private TextView currentPlaying, downloadingTv;
public static Button downloadBtn;
private String thePlayingSura;
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadId == id) {
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
downloadBtn.setText("DOWNLOADED");
downloadBtn.setBackgroundColor(Color.TRANSPARENT);
downloadBtn.setTextColor(Color.BLACK);
downloadBtn.setClickable(false);
Toast.makeText(context, "DOWNLOAD COMPLETED", Toast.LENGTH_SHORT).show();
}
}
};
#SuppressLint("StaticFieldLeak")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_the_playing);
myPlayerView = findViewById(R.id.playerView);
Intent dataIntent = getIntent();
myurl = dataIntent.getStringExtra("theUrl");
Intent backgroundPlayIntent = new Intent(ThePlayingActivity.this,BackgroundPlayingService.class);
try {
stopService(backgroundPlayIntent);
}catch (Exception e){}
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
startForegroundService(backgroundPlayIntent);
}else{
startService(backgroundPlayIntent);
}
keepActivityAlive();
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadingProgress = findViewById(R.id.downloadProgress);
downloadingTv = findViewById(R.id.downloadingWaitTv);
currentPlaying = findViewById(R.id.currentPlaying);
downloadBtn = findViewById(R.id.downloadbtn);
downloadBtn.setVisibility(View.GONE);
myProgress = findViewById(R.id.progressBar2);
myProgress.setVisibility(View.VISIBLE);
layoutForSnack = findViewById(R.id.constraintLayout);
downloadingProgress.setVisibility(View.GONE);
downloadingTv.setVisibility(View.GONE);
thePlayingSura = dataIntent.getStringExtra("sendSuraName");
currentPlaying.setText(thePlayingSura + " - " + DataUtility.theKariName);
/////////////end of ids
showLoadingDialog();
/////////////////download
downloadBtn.setOnClickListener(view -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
String permissions[] = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, PERMISION_STORAGE_CODE);
} else {
downloadStaffs();
}
} else {
downloadStaffs();
}
});
}
private void showLoadingDialog() {
dialog = new Dialog(ThePlayingActivity.this);
dialog.setContentView(R.layout.dialog_loading_quran);
dialog.setCancelable(false);
dialog.show();
}
public void showSnackBar() {
Snackbar snackbar = Snackbar.make(layoutForSnack, "THERE WAS ON ERROR, CHECK YOUR INTERNET CONNECTION", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("RETRY", view -> {
//todo retry player
});
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISION_STORAGE_CODE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// we have permission
downloadStaffs();
} else {
Toast.makeText(ThePlayingActivity.this, "PERMISSION DENIED... CAN NOT DOWNLOAD", Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
try {
if (wakeLock.isHeld()) {
wakeLock.release();
}
} catch (Exception ignore) {
}
}
private void downloadStaffs() {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DataUtility.playingUrl));
request.setDescription("Download File");
request.setTitle(thePlayingSura);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, thePlayingSura + " - " + DataUtility.theKariName + ".mp3");
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
this.downloadId = downloadId;
final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.downloadProgress);
downloadingTv.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
#SuppressLint("Range")
#Override
public void run() {
boolean downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
#SuppressLint("Range") int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
#SuppressLint("Range") int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
final double dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressBar.setProgress((int) dl_progress);
}
});
Log.d("MESSAGES", statusMessage(cursor));
cursor.close();
}
}
}).start();
}
#SuppressLint("Range")
private String statusMessage(Cursor c) {
String msg = "???";
switch (c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
case DownloadManager.STATUS_FAILED:
msg = "Download failed!";
break;
case DownloadManager.STATUS_PAUSED:
msg = "Download paused!";
break;
case DownloadManager.STATUS_PENDING:
msg = "Download pending!";
break;
case DownloadManager.STATUS_RUNNING:
msg = "Download in progress!";
break;
case DownloadManager.STATUS_SUCCESSFUL:
msg = "Download complete!";
break;
default:
msg = "Download is nowhere in sight";
break;
}
return (msg);
}
private void keepActivityAlive() {
powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "QuranAudio:WakeLock");
}
private void startService() {
Intent i = new Intent(this, BackgroundPlayingService.class);
startService(i);
}}
--------------------- extra --------------------------------------
I also had to create other service to remove notification when the
user kill app by clearing app from recent apps.
here is it
MyAppService extends Service {
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Intent i = new Intent(MyAppService.this,BackgroundPlayingService.class);
try {
BackgroundPlayingService.playerNotificationManager.setPlayer(null);
stopService(i);
}catch (Exception ignore){}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}}
-------------------- WARNING ----------------------------------
I don't take this as a best approach, but it gave me a quick solution while waiting for a better approach.
I will pot the app link here when it's available in playstore.
Im creating an app in android studio where I want 10 clips to be played at the same time side by side. Im having some problems with some lags already at three clips and I wounder if Im better off using threads? In that case how?
Any hint would be very much apreciated
Here is my code so far. I know it is not very efficient and I am better off using an array of a player object for example but Im just testing so far:
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {
private MediaPlayer mp1, mp2, mp3;
private TextureView tv1, tv2, tv3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.textureView1);
tv2 = findViewById(R.id.textureView2);
tv3 = findViewById(R.id.textureView3);
tv1.setSurfaceTextureListener(this);
tv2.setSurfaceTextureListener(this);
tv3.setSurfaceTextureListener(this);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Surface surface = new Surface(surfaceTexture);
mp1 = MediaPlayer.create(this, R.raw.a7);
mp1.setSurface(surface);
// mp1.prepareAsync(); //
mp1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp1) {
mp1.start();
}
});
Surface surface2 = new Surface(surfaceTexture);
mp2 = MediaPlayer.create(this, R.raw.a9);
mp2.setSurface(surface2);
// mp1.prepareAsync(); //
mp2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp2) {
mp2.start();
}
});
Surface surface3 = new Surface(surfaceTexture);
mp3 = MediaPlayer.create(this, R.raw.a10);
mp3.setSurface(surface3);
// mp1.prepareAsync(); //
mp3.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp3) {
mp3.start();
}
});
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
#Override
protected void onPause() {
if (mp1 != null && mp1.isPlaying()) {
mp1.pause();
}
super.onPause();
}
#Override
protected void onResume() {
if (mp1 != null) {
mp1.start();
}
super.onResume();
}
#Override
protected void onDestroy() {
if (mp1 != null) {
mp1.stop();
mp1.release();
mp1 = null;
}
super.onDestroy();
}
}
You should play media in a different non-ui thread. like this:-
public class MediaService extends Service {
private MediaPlayer mp1, mp2, mp3;
private static final String ACTION_START = TAG + ".ACTION_START";
private IBinder mBinder = new MyBinder();
private MediaPlayer.OnPreparedListener mMediaPrepared = new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "MediaPlayer.onPrepared");
onCommandPlay(mp);
}
};
#Override
public IBinder onBind(Intent intent) {
Log.v(TAG, "onBind");
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
m1 = MediaPlayer.create(this, R.raw.a1);
m2 = MediaPlayer.create(this, R.raw.a2);
m3 = MediaPlayer.create(this, R.raw.a9);
}
#Override
public void onDestroy() {
super.onDestroy();
if (m1 != null) m1 .release();
if (m2 != null) m2 .release();
if (m3 != null) m3 .release();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
Log.d(TAG, "onStartCommand: " + intent.getAction());
if (ACTION_START.equals(action)) {
onCommandStart();
return START_STICKY;
}
stopSelf();
return Service.START_STICKY_COMPATIBILITY;
}
/**
* Performs actions related to media player when Service onStartCommand method is called
*
*/
private void onCommandStart() {
// Create Notifications with remote views
mNotification = new NotificationCompat.Builder(this).setTicker("Media Service started...")
.setSmallIcon(R.mipmap.ic_launcher)
.setContent(collapsed)
.setAutoCancel(false)
.setOngoing(true)
.build();
startForeground(NOTIFICATION_ID, mNotification);
startPlaying();
}
private void onCommandPlay(MediaPlayer mp) {
try {
mp.start();
} catch (IllegalStateException e) {
Log.e(TAG, "onCommandPlay", e);
}
}
/**
* Start playing the provided media item
*
*/
private void startPlaying() {
mCurrent = item;
try {
mp1.reset();
mp1.setOnPreparedListener(mMediaPrepared);
mp2.reset();
mp2.setOnPreparedListener(mMediaPrepared);
mp3.reset();
mp3.setOnPreparedListener(mMediaPrepared);
AssetFileDescriptor afd1 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a9););
AssetFileDescriptor afd2 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a10););
AssetFileDescriptor afd3 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a8););
mp1.setDataSource(afd1 .getFileDescriptor(), afd1 .getStartOffset(), afd1.getLength());
mp2.setDataSource(afd2 .getFileDescriptor(), afd2 .getStartOffset(), afd2 .getLength());
mp3.setDataSource(afd3 .getFileDescriptor(), afd3 .getStartOffset(), afd3 .getLength());
mp1.prepareAsync();
mp2.prepareAsync();
mp3.prepareAsync();
} catch (IOException e) {
Log.e(TAG, "startPlaying", e);
}
}
public class MyBinder extends Binder {
public MediaService getService() {
return MediaService.this;
}
}
}
then start the service from Activity like this:
Intent intent = new Intent(context, MediaService.class);
intent.setAction(ACTION_START);
startServie(intent);
You should also handle different media playing use-cases. You can refer this link for more.
i'm trying to play music in my app using code below ,and it's work fine when i tested on (Android 8.0 ,7.0,5.0) but when i tested on Android 9.0 ,it doesn't worked,it seems like RadioService doesn't work it show me Somethig went wrong!! Toast so onPlayerError called
public void onPlayerError(ExoPlaybackException error) {
EventBus.getDefault().post(PlaybackStatus.ERROR);
}
MainActivity.java
#Subscribe
public void onEvent(String status) {
switch (status) {
case PlaybackStatus.LOADING:
progressloading.setVisibility(View.VISIBLE);
trigger.setVisibility(View.GONE);
break;
case PlaybackStatus.ERROR:
Toast.makeText(this, "Something went wrong!!", Toast.LENGTH_SHORT).show();
break;
}
if (status.equals(PlaybackStatus.PLAYING)) {
trigger.setVisibility(View.VISIBLE);
progressloading.setVisibility(View.GONE);
}
trigger.setImageResource(status.equals(PlaybackStatus.PLAYING)
? R.drawable.ic_pause_black
: R.drawable.ic_play_arrow_black);
}
, can anyone help me to get solution of this issue.
RadioService.java
#Override
public void onCreate() {
super.onCreate();
String strAppName = getResources().getString(R.string.app_name);
String strLiveBroadcast = getResources().getString(R.string.live_broadcast);
onGoingCall = false;
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
notificationManager = new MediaNotificationManager(this);
wifiLock = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mcScPAmpLock");
mediaSession = new MediaSessionCompat(this, getClass().getSimpleName());
transportControls = mediaSession.getController().getTransportControls();
mediaSession.setActive(true);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "...")
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, strAppName)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, strLiveBroadcast)
.build());
mediaSession.setCallback(mediasSessionCallback);
handler = new Handler();
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
AdaptiveTrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(trackSelectionFactory);
exoPlayer = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector, new CustomLoadControl());
exoPlayer.addListener(this);
registerReceiver(becomingNoisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
status = PlaybackStatus.IDLE;
}//END ON CREATE
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
if (TextUtils.isEmpty(action)) return START_NOT_STICKY;
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
stop();
return START_NOT_STICKY;
}
if (action != null) {
if (action.equalsIgnoreCase(ACTION_PLAY)) {
transportControls.play();
} else if (action.equalsIgnoreCase(ACTION_PAUSE)) {
transportControls.pause();
} else if (action.equalsIgnoreCase(ACTION_STOP)) {
transportControls.stop();
}
}
return START_NOT_STICKY;
}
#Override
public boolean onUnbind(Intent intent) {
serviceInUse = false;
if (status.equals(PlaybackStatus.IDLE))
stopSelf();
return super.onUnbind(intent);
}
#Override
public void onRebind(final Intent intent) {
serviceInUse = true;
}
#Override
public void onDestroy() {
pause();
exoPlayer.release();
exoPlayer.removeListener(this);
notificationManager.cancelNotify();
mediaSession.release();
unregisterReceiver(becomingNoisyReceiver);
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
serviceInUse = true;
return iBinder;
}
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
exoPlayer.setPlayWhenReady(true);
exoPlayer.setVolume(1.0f);
break;
case AudioManager.AUDIOFOCUS_GAIN:
exoPlayer.setVolume(0.8f);
resume();
break;
case AudioManager.AUDIOFOCUS_LOSS:
stop();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (isPlaying()) pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (isPlaying())
exoPlayer.setVolume(0.1f);
break;
}
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
status = PlaybackStatus.LOADING;
break;
case Player.STATE_ENDED:
status = PlaybackStatus.STOPPED;
break;
case Player.STATE_IDLE:
status = PlaybackStatus.IDLE;
break;
case Player.STATE_READY:
status = playWhenReady ? PlaybackStatus.PLAYING : PlaybackStatus.PAUSED;
break;
default:
status = PlaybackStatus.IDLE;
break;
}
if (!status.equals(PlaybackStatus.IDLE)) {
final Uri uri = Uri.parse("http://radio.plaza.one/mp3");
OnNewMetadataListener listener = new OnNewMetadataListener() {
#Override
public void onNewHeaders(String stringUri, List<String> name, List<String> desc, List<String> br, List<String> genre, List<String> info) {
}
#Override
public void onNewStreamTitle(String stringUri, final String streamTitle) {
MainActivity.songinfo.setText(streamTitle);
if (Build.VERSION.SDK_INT >= 21)
notificationManager.startNotify(getApplicationContext(), status, streamTitle);
}
};
AudiostreamMetadataManager.getInstance()
.setUri(uri)
.setOnNewMetadataListener(listener)
.setUserAgent(UserAgent.WINDOWS_MEDIA_PLAYER)
.start();
}
EventBus.getDefault().post(status);
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
EventBus.getDefault().post(PlaybackStatus.ERROR);
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
public void play(String streamUrl) {
this.streamUrl = streamUrl;
if (wifiLock != null && !wifiLock.isHeld()) {
wifiLock.acquire();
}
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, getClass().getSimpleName()), bandwidthMeter);
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
ExtractorMediaSource mediaSource = new ExtractorMediaSource(Uri.parse(streamUrl), dataSourceFactory, extractorsFactory, handler, null);
exoPlayer.prepare(mediaSource);
exoPlayer.setPlayWhenReady(true);
}
public void resume() {
if (streamUrl != null)
play(streamUrl);
}
public void pause() {
exoPlayer.setPlayWhenReady(false);
audioManager.abandonAudioFocus(this);
wifiLockRelease();
}
public void stop() {
exoPlayer.stop();
audioManager.abandonAudioFocus(this);
wifiLockRelease();
}
public void playOrPause(String url) {
if (streamUrl != null && streamUrl.equals(url)) {
if (!isPlaying()) {
play(streamUrl);
} else {
pause();
}
} else {
if (isPlaying()) {
pause();
}
play(url);
}
}
public String getStatus() {
return status;
}
public MediaSessionCompat getMediaSession() {
return mediaSession;
}
public boolean isPlaying() {
return this.status.equals(PlaybackStatus.PLAYING);
}
private void wifiLockRelease() {
if (wifiLock != null && wifiLock.isHeld()) {
wifiLock.release();
}
}
public int getCurrentPosition() {
return (int) exoPlayer.getCurrentPosition();
}
}
MediaNotificationManager.java
public class MediaNotificationManager {
private static final int NOTIFICATION_ID = 555;
private RadioService service;
private NotificationManagerCompat notificationManager;
private Resources resources;
MediaNotificationManager(RadioService service) {
this.service = service;
this.resources = service.getResources();
notificationManager = NotificationManagerCompat.from(service);
}
void startNotify(Context context, String playbackStatus, String title) {
String titlesonge;
String artist;
try {
titlesonge = StringUtils.substringBefore(title, " - ");
artist = StringUtils.substringAfter(title, " - ");
} catch (Exception e) {
titlesonge = title.substring(0, title.indexOf(" - "));
artist = title.substring(title.lastIndexOf(" - ") - 1);
}
int icon = R.drawable.ic_pause_white;
Intent playbackAction = new Intent(service, RadioService.class);
playbackAction.setAction(RadioService.ACTION_PAUSE);
PendingIntent action = PendingIntent.getService(service, 1, playbackAction, 0);
if (playbackStatus.equals(PlaybackStatus.PAUSED)) {
icon = R.drawable.ic_play_white;
playbackAction.setAction(RadioService.ACTION_PLAY);
action = PendingIntent.getService(service, 2, playbackAction, 0);
}
Intent stopIntent = new Intent(service, RadioService.class);
stopIntent.setAction(RadioService.ACTION_STOP);
PendingIntent stopAction = PendingIntent.getService(service, 3, stopIntent, 0);
Intent intent = new Intent(service, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, intent, 0);
notificationManager.cancel(NOTIFICATION_ID);
String PRIMARY_CHANNEL = "PRIMARY_CHANNEL_ID";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
String PRIMARY_CHANNEL_NAME = "PRIMARY";
NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL, PRIMARY_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(service, PRIMARY_CHANNEL)
.setAutoCancel(false)
.setContentTitle(titlesonge)
.setContentText(artist)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.largeicon))
.setContentIntent(pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.smallwidth)
.setColor(ContextCompat.getColor(context, R.color.colorneeded))
.addAction(icon, "pause", action)
.addAction(R.drawable.ic_stop_white, "stop", stopAction)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
.setMediaSession(service.getMediaSession().getSessionToken())
.setShowActionsInCompactView(0, 1)
.setShowCancelButton(true)
.setCancelButtonIntent(stopAction));
service.startForeground(NOTIFICATION_ID, builder.build());
}
void cancelNotify() {
service.stopForeground(true);
notificationManager.cancel(NOTIFICATION_ID);
}
}
RadioManager.java
public class RadioManager {
#SuppressLint("StaticFieldLeak")
private static RadioManager instance = null;
private static RadioService service;
private Context context;
private boolean serviceBound;
public RadioManager(Context context) {
this.context = context;
serviceBound = false;
}
public static RadioManager with(Context context) {
if (instance == null)
instance = new RadioManager(context);
return instance;
}
public static RadioService getService() {
return service;
}
public void playOrPause(String streamUrl) {
service.playOrPause(streamUrl);
}
public boolean isPlaying() {
if (service != null) {
return service.isPlaying();
}
return false;
}
public int getCurrentPosition() {
if (service != null) {
return service.getCurrentPosition();
}
return 0;
}
public void bind() {
Intent intent = new Intent(context, RadioService.class);
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
if (service != null)
EventBus.getDefault().post(service.getStatus());
}
public void unbind() {
context.unbindService(serviceConnection);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
RadioService.LocalBinder rl = (RadioService.LocalBinder) binder;
service = rl.getService();
}
public void onServiceDisconnected(ComponentName arg0) {
serviceBound = false;
}
};
}
Manifest.xml
<service
android:name=".RadioTools.RadioService"
android:exported="true"
android:stopWithTask="true" />
Since Android 9 ,the link with Http no longer supported,i just added S to my link so instead of
http://mylink.com/mp3
i added s :
https://mylink.com/mp3
And everything worked fine
I am making a game app but the music still keeps playing even when I closed the game. how to stop? and how to change background music once I go to another activity after I clicked a button
public class BackgroundSoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.rysk);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
this is my main activity (PlayActivity.class)
Intent svc=new Intent(this, BackgroundSoundService.class);
startService(svc);
I want to change the music when I clicked a button and went to CatActivity
You should have to work with registerReceiver,unregisterReceiver.
May this helps you.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button btn_startservice;
private Button btn_stopservice;
private TextView tv_servicecounter;
ServiceDemo myService;
boolean isBound;
BroadcastReceiver broadcastRec = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int datapassed = intent.getIntExtra("value", 0);
tv_servicecounter.setText(String.valueOf(datapassed));
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_servicecounter = (TextView) findViewById(R.id.tv_activity_main_count);
btn_startservice = (Button) findViewById(R.id.btn_activity_main_startservices);
btn_stopservice = (Button) findViewById(R.id.btn_activity_main_stopservices);
btn_startservice.setOnClickListener(
new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onClick(View v) {
Intent objIntent = new Intent(MainActivity.this, ServiceDemo.class);
if (!isBound) {
bindService(objIntent, myConnection, Context.BIND_AUTO_CREATE);
isBound = true;
startService(objIntent);
} else {
isBound = false;
unbindService(myConnection);
}
}
}
);
btn_stopservice.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent objIntent = new Intent(MainActivity.this, ServiceDemo.class);
if (isBound) {
isBound = false;
unbindService(myConnection);
stopService(objIntent);
} else {
stopService(objIntent);
}
}
}
);
}
#Override
protected void onResume() {
registerReceiver(broadcastRec, new IntentFilter("USER_ACTION"));
super.onResume();
}
#Override
protected void onStop() {
this.unregisterReceiver(broadcastRec);
super.onStop();
}
private ServiceConnection myConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
myService = ((ServiceDemo.MyLocalBinder) service).getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
#Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(myConnection);
isBound = false;
}
}
}
And ServiceDemo.java
public class ServiceDemo extends Service {
int i;
private MyThread mythread;
public boolean isRunning = false;
Notification notification;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
mythread = new MyThread();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
if (!isRunning) {
mythread.start();
isRunning = true;
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mythread.interrupt();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
}
public void sendBrodcastMsg(int value) {
Intent intent = new Intent();
intent.setAction("USER_ACTION");
intent.putExtra("value", value);
sendBroadcast(intent);
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
class MyThread extends Thread {
static final long DELAY = 100;
#Override
public void run() {
while (isRunning) {
try {
i++;
Thread.sleep(DELAY);
sendBrodcastMsg(i);
shownotification();
} catch (InterruptedException e) {
isRunning = false;
e.printStackTrace();
}
}
stopSelf();
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void shownotification() {
Intent in = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), in, 0);
notification = new NotificationCompat.Builder(this)
.setContentTitle(String.valueOf(i))
.setContentText(String.valueOf(i))
.setSmallIcon(R.drawable.musicplayer)
.setContentIntent(pIntent)
.setAutoCancel(true).build();
;
startForeground(101, notification);
}
public class MyLocalBinder extends Binder {
ServiceDemo getService() {
return ServiceDemo.this;
}
}
private final IBinder myBinder = new MyLocalBinder();
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return myBinder;
}
}
put this two lines in manifest.
<service android:name=".ServiceDemo"
android:enabled="true"/>
You need to stop the player in onPause(). Following code can be used:
#Override
protected void onPause() {
super.onPause();
if (this.isFinishing()){
player.stop();
}
}
Check Android Stop Background Music for more details
for that you should stop the service in the onCreate method of the Activity. Below is the code for it :
stopService(new Intent(MyService.MY_SERVICE));
Best of Luck!
In Your MainActivity , You Should Call stopService() Inside MainActivity
#Override
public void OnPause() {
stopService(svc);
}
I'm trying play an audio file with the mediacontroler in my android application. When playing audio the seekbar does not move.I looked mediacontroler function. But I could not find a function for updating seekbar.
please advice.
public class Show_subject_Activity extends Activity
implements MediaController.MediaPlayerControl, MediaPlayer.OnBufferingUpdateListener {
private RatingBar box_litner;
private MediaController mController;
private MediaPlayer mPlayer;
private Cursor cur;
int bufferPercent = 0;
DB_Nabege_helper db_nabege = new DB_Nabege_helper(this);
private String voicefileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_subject);
box_litner = (RatingBar) findViewById(R.id.ratingBar1);
mController = (MediaController) findViewById(R.id.mediaController_voice);
mController.setAnchorView(null);
db_nabege.open();
cur = db_nabege.getSubject(Intent_values.id_subject);
voicefileName = getVoiceFileName();
db_nabege.close();
}
#Override
public void onResume() {
super.onResume();
mPlayer = new MediaPlayer();
// Set the audio data source
try {
mPlayer.setDataSource(this, getUriVoice());
mPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}
// Set an image for the album cover
// coverImage.setImageResource(R.drawable.icon);
mController.setMediaPlayer(this);
mController.setEnabled(true);
}
private Uri getUriVoice() {
File voiceFile = null;
try {
voiceFile = new File(Environment.getExternalStorageDirectory().getPath() + "/nabege" + File.separator
+ "audio" + File.separator + voicefileName);
} catch (Exception e) {
Log.d("log", e.toString());
}
Uri voiceUri = Uri.fromFile(voiceFile);
return voiceUri;
}
#Override
public void onPause() {
super.onPause();
mPlayer.release();
mPlayer = null;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mController.show();
return super.onTouchEvent(event);
}
// MediaPlayerControl Methods
#Override
public int getBufferPercentage() {
return bufferPercent;
}
#Override
public int getCurrentPosition() {
return mPlayer.getCurrentPosition();
}
#Override
public int getDuration() {
return mPlayer.getDuration();
}
#Override
public boolean isPlaying() {
return mPlayer.isPlaying();
}
#Override
public void pause() {
mPlayer.pause();
}
#Override
public void seekTo(int pos) {
mPlayer.seekTo(pos);
}
#Override
public void start() {
mPlayer.start();
}
// BufferUpdateListener Methods
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
bufferPercent = percent;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
}
You can update the seekbar yourself, e.g.:
final Handler mHandler = new Handler();
final Runnable mUpdateSeekbar = new Runnable() {
public void run() {
mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
mSeekBar.setMax(mMediaPlayer.getDuration());
mHandler.postDelayed(this, 1000);
}
};
Post the runnable in onResume and mHandler.removeCallbacks(mUpdateSeekbar) in onPause.