I am trying to write an android app that streams from an icecast server when you click play. This is for a radio station that I help out in my area, and they need to get out in the community, and be able to advertise. I have written some android apps before, but my experience with this is limited.
There are no errors in the code according to android studio, and the app does everything the way it is supposed to except play the stream. I have tested the stream on my browser, and it is up and running.
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
Button b_play;
MediaPlayer mediaPlayer;
boolean prepared = false;
boolean started = false;
String stream = "<server address>";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_play = (Button) findViewById(R.id.b_play);
b_play.setEnabled(false);
b_play.setText("LOADING...");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
new PlayerTask().execute(stream);
b_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(started) {
started = false;
mediaPlayer.pause();
b_play.setText("PLAY");
}else{
started = true;
mediaPlayer.start();
b_play.setText("PAUSE");
}
}
});
}
class PlayerTask extends AsyncTask<String, Void, Boolean>{
#Override
protected Boolean doInBackground(String... strings) {
try {
mediaPlayer.setDataSource(strings[0]);
mediaPlayer.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aboolean) {
super.onPostExecute(aboolean);
mediaPlayer.start();
b_play.setEnabled(true);
b_play.setText("PLAY");
}
}
#Override
protected void onPause() {
super.onPause();
if(started) {
mediaPlayer.pause();
}
}
#Override
protected void onResume() {
super.onResume();
if(started) {
mediaPlayer.start();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(prepared){
mediaPlayer.release();
}
}
}
Icecast has delay picking up Android apps. If you have 32k streaming it can take up to 40 seconds for the stream to load. 64k can take awhile also.
Shoutcast servers pick up almost instantly.
https://androidaudio.info/android-audio-buffering-issues-with-32k-acc-icecast-server/
Related
I have an activity named Player Activity in which I am streaming music with the help of MediaPlayer API. Whenever my activity is created a notification is displayed which has some basic control of the music player.
So when I tap on my notification it jumps back to the Player Activity, but the state of the activity is lost.
Before tapping on notification :
After tapping on notification :
Here is the code of my notification's Pending Intent
Intent notifyIntent = new Intent(context, PlayerActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
notifyIntent.setAction("android.intent.action.MAIN");
notifyIntent.addCategory("android.intent.category.LAUNCHER");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Here is the code for PlayerActivity.java :
package com.example.user.musicplayer;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.concurrent.TimeUnit;
import de.hdodenhof.circleimageview.CircleImageView;
public class PlayerActivity extends AppCompatActivity implements MediaPlayer.OnBufferingUpdateListener,MediaPlayer.OnCompletionListener{
private static Button btn_play_pause;
private Button btnToggleRepeat;
private Button btnStop;
private SeekBar seekBar;
private TextView textView;
public static MediaPlayer mediaPlayer;
private int mediaFileLength;
private int realtimeLength;
private String musicUrl;
private String imageUrl;
final Handler handler = new Handler();
private boolean isRepeat;
private CircleImageView musicImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
Log.d("TAG", "onCreate");
NotificationGenerator.customBigNotification(getApplicationContext());
musicUrl = getIntent().getStringExtra("musicUrl");
imageUrl = getIntent().getStringExtra("imageUrl");
seekBar = (SeekBar)findViewById(R.id.seekbar);
seekBar.setMax(99); // 100% (0~99)
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(mediaPlayer.isPlaying())
{
SeekBar seekBar = (SeekBar)v;
int playPosition = (mediaFileLength/100)*seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
}
return false;
}
});
textView = (TextView)findViewById(R.id.txtTime);
btnToggleRepeat = findViewById(R.id.btnRepeat);
btnStop = findViewById(R.id.btnStop);
musicImage = findViewById(R.id.musicImgView);
Picasso.get().load(imageUrl).placeholder(R.drawable.music).error(R.drawable.music).into(musicImage);
btn_play_pause = (Button) findViewById(R.id.btnTogglePlay);
btn_play_pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog mDialog = new ProgressDialog(PlayerActivity.this);
AsyncTask<String,String,String> mp3Play = new AsyncTask<String, String, String>() {
#Override
protected void onPreExecute() {
mDialog.setMessage("Please wait");
mDialog.show();
}
#Override
protected String doInBackground(String... params) {
try{
mediaPlayer.setDataSource(params[0]);
mediaPlayer.prepare();
}
catch (Exception ex)
{
}
return "";
}
#Override
protected void onPostExecute(String s) {
mediaFileLength = mediaPlayer.getDuration();
realtimeLength = mediaFileLength;
if(!mediaPlayer.isPlaying())
{
playMusic();
}
else
{
pauseMusic();
}
updateSeekBar();
mDialog.dismiss();
}
};
mp3Play.execute(musicUrl); // direct link mp3 file
}
});
btnToggleRepeat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isRepeat){
isRepeat = false;
mediaPlayer.setLooping(false);
btnToggleRepeat.setText("Repeat");
}
else{
isRepeat = true;
mediaPlayer.setLooping(true);
btnToggleRepeat.setText("Single");
}
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mediaPlayer.pause();
mediaPlayer.stop();
}
catch (Exception e){
Toast.makeText(PlayerActivity.this, "Opps! sorry something bad happened", Toast.LENGTH_SHORT).show();
}
}
});
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
public void pauseMusic() {
mediaPlayer.pause();
btn_play_pause.setText("Play");
}
public void playMusic() {
mediaPlayer.start();
btn_play_pause.setText("Pause");
}
private void updateSeekBar() {
seekBar.setProgress((int)(((float)mediaPlayer.getCurrentPosition() / mediaFileLength)*100));
if(mediaPlayer.isPlaying())
{
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
realtimeLength-=1000; // declare 1 second
textView.setText(String.format("%d:%d",TimeUnit.MILLISECONDS.toMinutes(realtimeLength),
TimeUnit.MILLISECONDS.toSeconds(realtimeLength) -
TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(realtimeLength))));
}
};
handler.postDelayed(updater,1000); // 1 second
}
}
#Override
protected void onResume() {
super.onResume();
Log.d("TAG", "onResume");
}
#Override
protected void onStart() {
super.onStart();
Log.d("TAG", "onStart");
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
seekBar.setSecondaryProgress(percent);
}
#Override
public void onCompletion(MediaPlayer mp) {
if(!mediaPlayer.isLooping())
btn_play_pause.setText("Play");
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onPause() {
super.onPause();
}
public static class DownloadCancelReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("notificationPlayer","Received Cancelled Event");
}
}
}
Thanks in advance. Pardon me if the explanation is not clear, because if i might have right words to explain it, I would have googled it.
Add this to your PlayerActivity activity in manifest :
android:launchMode="singleTask"
And use these flags in the intent for pendingintent :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Here is the code for the button which should start and pause the audio.
I have checked the button-text == "start" or "pause" and change the text and use the appropriate methods accordingly
i.e mediaplayer.start() and mediaplayer.pause().
But still, the audio won't play.
package com.example.demo;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity
{
MediaPlayer mediaPlayer;//Mediaplayer
Button button;
public void start(View view)
{
String text = button.getText().toString();
if (text == "start")
{
mediaPlayer.start(); //starting the audio
button.setText("pause");
}
else
{
mediaPlayer.pause(); //pausing the audio
button.setText("start");
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.start);
mediaPlayer = MediaPlayer.create(this,R.raw.music);
}
}
There are a few steps you should try:
First, try this because I think It gives always a false condition:
if(text.trim().equals("start"))
If Still not work Try this one:
public class MainActivity extends AppCompatActivity
{
MediaPlayer mediaPlayer;//Mediaplayer
Button button;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.start);
mediaPlayer = MediaPlayer.create(this,R.raw.music);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String text = button.getText().toString().trim();
if (text.equals("start"))
{
mediaPlayer.start();
button.setText("pause");
}
else
{
mediaPlayer.pause();
button.setText("start");
}
}
}
} }
When I run my app on the emulator, the app runs fine but when I run the app on my actual phone it crashes when I click on the button to use the play method. I used another phone to see if the app will work but it crashes again.
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.media.MediaPlayer;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
MediaPlayer song;
boolean playing=false;
int length;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
song = MediaPlayer.create(MainActivity.this, R.raw.snakin);
}
public void play(View view){
if(playing==false) {
Button play = (Button) findViewById(R.id.play);
song.seekTo(length);
song.start();
playing=true;
}
}
public void pause(View view){
Button pause=(Button)findViewById(R.id.pause);
song.pause();
length = song.getCurrentPosition();
playing=false;
}
}
I've changed the mp3 file to another one. I really don't know why the first mp3 file only worked on the emulator, but my guess is that the file was corrupted.
You didn't mention listeners to play and pause.
Need to mention listeners for song play and pause operations.
Here, I modified your code, you can try below given code.
public class MainActivity extends AppCompatActivity {
MediaPlayer song;
boolean playing=false;
int length;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button play = (Button) findViewById(R.id.play);
Button pause = (Button) findViewById(R.id.pause);
song = MediaPlayer.create(MainActivity.this, R.raw.song);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(playing==false) {
song.seekTo(length);
song.start();
playing = true;
}
}
});
pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(playing==true) {
song.pause();
length = song.getCurrentPosition();
playing = false;
}
}
});
}
}
Im following tutorials on youtube and I'm stuck https://www.youtube.com/watch?v=pPpVZ8YZXHk&t=62s
in the tutorial after entering
package com.example.oneilbogle.radiov1;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button b_play;
MediaPlayer mediaPlayer;
boolean prepared = false;
boolean started = false;
String stream = "http://142.4.217.133:8647/stream";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_play = (Button) findViewById(R.id.b_play);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
new PlayerTask().execute(stream);
b_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
class PlayerTask extends AsyncTask<String, Void, Boolean>{
#Override
protected Boolean doInBackground(String... params) {
mediaPlayer.setDataSource(strings[0]);
return prepared;
}
}
}
mediaPlayer.setDataSource(strings[0]);
the author uses a try/catch option but i get a different option
what should i do ?
You are messing the parameters names around.
Try with either:
protected Boolean doInBackground(String... params) {
mediaPlayer.setDataSource(params[0]);
return prepared;
}
or
protected Boolean doInBackground(String... strings) {
mediaPlayer.setDataSource(strings[0]);
return prepared;
}
so what i did was i changed it to stream
mediaPlayer.setDataSource(stream);
I wanted to create a webview that comes on shakeactivity. In xml of current activity, I made webview visibility as invisibe. Now, I have this shakeevent listener. Everything is working fine, except I start this shakeactivity on its first launch it displays shaking in toast in text i included that, which i have in onShake() function. But, I dont want that. I want to neglect the first launch of this shakeactivity and after 2nd shake i want to refresh the shakeactivity to load a url and visibility of webview to visible.
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.Toast;
public class MainActivity extends Activity implements
ShakeEventManager.shakeListener {
private ShakeEventManager sd;
private static long back_pressed;
Boolean isInternetPresent = false;
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
createData();
sd = new ShakeEventManager();
sd.setListener(this);
sd.init(this);
}
private void createData() {
WebView web = (WebView) findViewById(R.id.webview);
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setPluginsEnabled(true);
web.loadUrl("http://www.google.com");
}
#Override
public void onShake() {
count++;
if (count >= 1) {
ConnectionDetector cd = new ConnectionDetector(
getApplicationContext());
isInternetPresent = cd.isConnectingToInternet();
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
if (isInternetPresent) {
createData();
} else {
Toast.makeText(getApplicationContext(),
"Enable Data Connection", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onResume() {
super.onResume();
sd.register();
}
#Override
protected void onPause() {
super.onPause();
sd.deregister();
}
#Override
public void onBackPressed() {
finish();
}
}
Your count++ variable increasing value first before checking condition first time so that you may have to increase in if as i have done or you can put this statement at the last after condition.
Change like following:
#Override
public void onShake() {
if (count++ >= 1) {
ConnectionDetector cd = new ConnectionDetector(
getApplicationContext());
isInternetPresent = cd.isConnectingToInternet();
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
if (isInternetPresent) {
createData();
} else {
Toast.makeText(getApplicationContext(),
"Enable Data Connection", Toast.LENGTH_LONG).show();
}
}
}
Note: I dont have tested but i just saw your code and found this
logical mistake so may be helpful to you :)