I am new to Android. I'm trying to create a music player which will play specific MP3 based on the count (controlled by Rc variable) and based on the button sequence (controlled by BitCount variable) should change. And I have one stop button by clicking which I should be able to stop the music.
My problem is everything is working fine when UI is on foreground but when screen goes to background then also music start running (it's OK let music be running on background) but when once again I bring my UI from background to foreground than by clicking stop button I am unable to stop the music, it runs continuously. This same problem is happening when I am rotating my mobile.
Code:
package com.example.tallite;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;
public class MainActivity extends Activity implements OnSeekBarChangeListener {
MediaPlayer OurSong;
public Handler handler1 = new Handler();
Button Start;
Button Stop;
Button Button21;
Button Button22;
Button StopButton;
public int GProgreess=0;
int Rc=0;
int BitCount=6;
int SeekPos=0;
int Period=500;
int BreakVar=0;
Thread myThread ;
public TextView text1,text2,text3,text4;
private SeekBar bar;
private TextView textProgress,textAction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "onCreate()", Toast.LENGTH_LONG).show();
text1 = (TextView)findViewById(R.id.textbit1);
text2 = (TextView)findViewById(R.id.textbit2);
text3 = (TextView)findViewById(R.id.textbit3);
text4 = (TextView)findViewById(R.id.textbit4);
Button21=(Button)findViewById(R.id.button21);
Button22=(Button)findViewById(R.id.button22);
StopButton=(Button)findViewById(R.id.buttonstop);
bar = (SeekBar)findViewById(R.id.seekBar1);
textProgress = (TextView)findViewById(R.id.textViewProgress);
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
try {
OurSong.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bar.setOnSeekBarChangeListener(this); // set seekbar listener.
/*handler1.post(runnable1);
stopPlaying();*/
StopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
BitCount=5;
handler1.removeCallbacks(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
Button21.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
Rc=0;
BitCount=13;
handler1.removeCallbacks(runnable1);
handler1.post(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
Button22.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
stopPlaying();
Rc=0;
BitCount=15;
handler1.removeCallbacks(runnable1);
handler1.post(runnable1);
}/****End of on clk******/
});/*****End of set on clk listener*****/
}
#Override
protected void onStart() {
//the activity is become visible.
super.onStart();
/*handler1.removeCallbacks(runnable1);*/
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onStop() {
//the activity is no longer visible.
super.onStop();
Toast.makeText(this, "onStop()", Toast.LENGTH_LONG).show();
}
#Override
protected void onDestroy() {
//The activity about to be destroyed.
super.onDestroy();
Toast.makeText(this, "onDestroy()", Toast.LENGTH_LONG).show();
}
private void stopPlaying()
{
if (OurSong != null)
{
OurSong.stop();
OurSong.release();
OurSong = null;
}
}
/* private void stopPlaying()
{
OurSong.stop();
OurSong.release();
}*/
public Runnable runnable1= new Runnable() {
#Override
public void run() {
if(BitCount==13)
{
text1.setText("1");
text2.setText(""+Rc);
text3.setText(""+BitCount);
if(Rc==0||Rc==6||Rc==10)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
OurSong.start();
}
if(Rc==2||Rc==4||Rc==8||Rc==12)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.b);
OurSong.start();
}
if(Rc==13)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.c);
OurSong.start();
}
Rc++;
if(Rc>BitCount)
{
text4.setText(""+Rc);
Rc=0;
}
}/****End of bitcount=13****/
if(BitCount==15)
{
text1.setText("2");
text2.setText(""+Rc);
text3.setText(""+BitCount);
if(Rc==0||Rc==8||Rc==12)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.a);
OurSong.start();
}
if(Rc==2||Rc==4||Rc==6||Rc==10||Rc==14)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.b);
OurSong.start();
/* Toast.makeText(getApplicationContext(), "-",
Toast.LENGTH_LONG).show();*/
}
if(Rc==15)
{
stopPlaying();
OurSong=MediaPlayer.create(MainActivity.this,R.raw.c);
OurSong.start();
/*Toast.makeText(getApplicationContext(), "|",
Toast.LENGTH_LONG).show();*/
}
Rc++;
if(Rc>BitCount)
{
text4.setText(""+Rc);
Rc=0;
}
}/***End of bitcount=15***/
if(BitCount==5)
{
text1.setText("Rc"+Rc);
stopPlaying();
}
if(BitCount==6)
{
text1.setText("x"+Rc);
stopPlaying();
}
handler1.postDelayed(runnable1, Period);
}
};
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
GProgreess=progress+20;
textProgress.setText("Bit/Minute: "+(progress+20));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekBar.setSecondaryProgress(seekBar.getProgress());
SeekPos=GProgreess;
Period=(int)(30000/SeekPos);
/*textProgress.setText("Period: "+Period);*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
When you close your app, ur activity is destroyed and hence reference to ur media player variable is lost. When you recreate ur activity you get a new set of reference and hence ur unable to stop it.
You will have to create a Service name it as MediaPlayerService which will deal with all media related actions like play, pause etc..
You can read about service over here:
http://developer.android.com/guide/components/services.html
If you want an example for media player, you can check RandomMusicPlayer, an excellent media player example provided by android in android sample projects.
Here is my implementation of MediaPlayerService
MediaPlayerService Class:
package com.cyberinsane.musicplayerlibrary;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class MediaPlayerService extends Service implements OnCompletionListener, OnPreparedListener, OnErrorListener {
private static final int NOTIFICATION_ID = 1;
public static final String INTENT_URL = "url";
public enum MediaState {
Playing, Paused, Stopped
}
private MediaState mState = MediaState.Stopped;
private MediaPlayer mPlayer;
private NotificationManager mNotificationManager;
public String mCurrentUrl = "";
public static final String ACTION_TOGGLE_PLAYBACK = "com.cyberinsane.musicplayerlibrary.action.TOGGLE_PLAYBACK";
public static final String ACTION_PLAY = "com.cyberinsane.musicplayerlibrary.action.PLAY";
public static final String ACTION_PAUSE = "com.cyberinsane.musicplayerlibrary.action.PAUSE";
public static final String ACTION_STOP = "com.cyberinsane.musicplayerlibrary.action.STOP";
#Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
String url = intent.getExtras().getString(INTENT_URL);
if (url != null) {
if (!url.equals(mCurrentUrl)) {
mCurrentUrl = url;
mState = MediaState.Stopped;
relaxResources(true);
processPlayRequest();
} else {
if (action.equals(ACTION_TOGGLE_PLAYBACK)) {
processTogglePlaybackRequest();
} else if (action.equals(ACTION_PLAY)) {
processPlayRequest();
} else if (action.equals(ACTION_PAUSE)) {
processPauseRequest();
} else if (action.equals(ACTION_STOP)) {
processStopRequest(false);
}
}
}
}
return START_STICKY;
}
private void processTogglePlaybackRequest() {
if (mState == MediaState.Paused || mState == MediaState.Stopped) {
processPlayRequest();
} else {
processPauseRequest();
}
}
private void processPlayRequest() {
try {
if (mState == MediaState.Stopped) {
createMediaPlayerIfNeeded();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(getApplicationContext(), Uri.parse(mCurrentUrl));
mPlayer.prepare();
} else if (mState == MediaState.Paused) {
mState = MediaState.Playing;
setUpAsForeground("Playing...");
if (!mPlayer.isPlaying()) {
mPlayer.start();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPlay();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void processPauseRequest() {
if (mState == MediaState.Playing) {
mState = MediaState.Paused;
mPlayer.pause();
relaxResources(false);
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPause();
}
}
}
private void processStopRequest(boolean force) {
if (mState == MediaState.Playing || mState == MediaState.Paused || force) {
mState = MediaState.Stopped;
relaxResources(true);
stopSelf();
}
}
private void createMediaPlayerIfNeeded() {
if (mPlayer == null) {
mPlayer = new MediaPlayer();
mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
} else
mPlayer.reset();
}
private void relaxResources(boolean releaseMediaPlayer) {
stopForeground(true);
if (releaseMediaPlayer && mPlayer != null) {
mPlayer.reset();
mPlayer.release();
mPlayer = null;
}
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(getApplicationContext(), "Media player error! Resetting.", Toast.LENGTH_SHORT).show();
Log.e("MusicPlayer", "Error: what=" + String.valueOf(what) + ", extra=" + String.valueOf(extra));
mState = MediaState.Stopped;
relaxResources(true);
if (mIMediaPlayer != null) {
mIMediaPlayer.onError();
}
return true; // true indicates we handled the error
}
#Override
public void onPrepared(MediaPlayer mp) {
mState = MediaState.Playing;
updateNotification("Playing...");
if (!mPlayer.isPlaying()) {
mPlayer.start();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioPlay();
}
}
}
#Override
public void onCompletion(MediaPlayer mp) {
mState = MediaState.Stopped;
relaxResources(true);
stopSelf();
if (mIMediaPlayer != null) {
mIMediaPlayer.onAudioStop();
}
}
/**
* Updates the notification.
*/
private void updateNotification(String text) {
mNotificationManager.notify(NOTIFICATION_ID, buildNotification(text).build());
}
private void setUpAsForeground(String text) {
startForeground(NOTIFICATION_ID, buildNotification(text).build());
}
private NotificationCompat.Builder buildNotification(String text) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this.getApplicationContext());
builder.setSmallIcon(R.drawable.ic_launcher)
.setOngoing(true)
.setContentTitle("Cyberinsane MusicPlayer")
.setContentText(text)
.setContentIntent(
PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(),
MediaPlayerActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
.setContentInfo("Awesome");
return builder;
}
#Override
public void onDestroy() {
mState = MediaState.Stopped;
relaxResources(true);
}
public class LocalBinder extends Binder {
MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
private IMediaPlayer mIMediaPlayer;
public MediaPlayer getMediaPlayer() {
return mPlayer;
}
public void setIMediaPlayer(IMediaPlayer mediaPlayer) {
mIMediaPlayer = mediaPlayer;
}
public MediaState getMediaState() {
return mState;
}
public boolean isPlaying() {
return (mState == MediaState.Playing);
}
public String getCurrentUrl() {
return mCurrentUrl;
}
public long duration() {
if (mPlayer != null) {
return mPlayer.getDuration();
}
return 0;
}
public long position() {
if (mPlayer != null) {
return mPlayer.getCurrentPosition();
}
return 0;
}
public void seekTo(long position) {
if (mPlayer != null) {
mPlayer.seekTo((int) position);
}
}
}
MediaPlayerActivity Class:
package com.cyberinsane.musicplayerlibrary;
import java.io.File;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MediaPlayerActivity extends Activity implements IMediaPlayer {
private ImageButton mButtonPlay;
private EditText mEditTextUrl;
private SeekBar mSeekBarProgress;
private boolean mIsBound;
private String mExtStorePath;
private MediaPlayerService mMediaService;
private Handler mSeekHandler = new Handler();
private Runnable mSeekRunnable = new Runnable() {
#Override
public void run() {
seekStartUpdation();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.media_player_activity);
mButtonPlay = (ImageButton) findViewById(R.id.buttonPlay);
mEditTextUrl = (EditText) findViewById(R.id.editTextURL);
mSeekBarProgress = (SeekBar) findViewById(R.id.seekBarMediaProgress);
mExtStorePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
doBindService();
initListeners();
}
private void initListeners() {
mButtonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String urlExt = mEditTextUrl.getText().toString();
if (urlExt != null && !urlExt.equals("")) {
String url = mExtStorePath + urlExt;
startService(new Intent(MediaPlayerService.ACTION_TOGGLE_PLAYBACK).putExtra(
MediaPlayerService.INTENT_URL, url));
}
}
});
mSeekBarProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mMediaService.seekTo(seekBar.getProgress());
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// empty
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// empty
}
});
}
#Override
protected void onResume() {
super.onResume();
doBindService();
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
#Override
protected void onPause() {
super.onPause();
doUnbindService();
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
mMediaService = ((MediaPlayerService.LocalBinder) service).getService();
mMediaService.setIMediaPlayer(MediaPlayerActivity.this);
setControlState();
}
#Override
public void onServiceDisconnected(ComponentName className) {
mMediaService = null;
}
};
private void doBindService() {
bindService(new Intent(MediaPlayerActivity.this, MediaPlayerService.class), mConnection,
Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
#Override
public void onAudioPlay() {
setPlayerState(true);
}
#Override
public void onAudioPause() {
setPlayerState(false);
}
#Override
public void onAudioStop() {
setPlayerState(false);
mSeekBarProgress.setProgress(0);
}
#Override
public void onError() {
// handle errors here
}
private void setControlState() {
if (mMediaService.isPlaying()) {
mEditTextUrl.setText(mMediaService.getCurrentUrl().replace(mExtStorePath, ""));
setPlayerState(true);
} else {
setPlayerState(false);
}
}
public void setPlayerState(boolean isPlaying) {
if (isPlaying) {
mButtonPlay.setImageResource(R.drawable.ic_pause);
mSeekBarProgress.setMax((int) mMediaService.duration());
seekStartUpdation();
} else {
mButtonPlay.setImageResource(R.drawable.ic_play);
seekStopUpdate();
}
}
public void seekStartUpdation() {
mSeekBarProgress.setProgress((int) mMediaService.position());
mSeekHandler.postDelayed(mSeekRunnable, 1000);
}
public void seekStopUpdate() {
mSeekHandler.removeCallbacks(mSeekRunnable);
}
}
Media Player Event Listener
package com.cyberinsane.musicplayerlibrary;
public interface IMediaPlayer {
public void onAudioPlay();
public void onAudioPause();
public void onAudioStop();
public void onError();
}
And finally my Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyberinsane.musicplayerlibrary"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.cyberinsane.musicplayerlibrary.MediaPlayerActivity"
android:label="#string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.cyberinsane.musicplayerlibrary.MediaPlayerService"
android:exported="false" >
<intent-filter>
<action android:name="com.cyberinsane.musicplayerlibrary.action.TOGGLE_PLAYBACK" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.PLAY" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.PAUSE" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.SKIP" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.REWIND" />
<action android:name="com.cyberinsane.musicplayerlibrary.action.STOP" />
</intent-filter>
</service>
</application>
</manifest>
Related
I am trying to run my Android radio app in the background. So when I click the back button after a little time it has been forced to stop. Automatically calls the onDestroy() method. How do I fix this problem?
This is the main activity class onBackPressed() button code.
#Override
public void onBackPressed(){
System.out.println("onBackPressed");
serviceIntent.addCategory(Intent.CATEGORY_HOME);
serviceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(serviceIntent);
moveTaskToBack(true);
//activity.moveTaskToBack(true);
}
This is the console log
> I/System.out: onPrepared I/System.out: onBackPressed I/System.out:
> onDestroy I/System.out: onDestroy1 I/System.out: onDestroy2
> V/MediaPlayer: resetDrmState: mDrmInfo=null
> mDrmProvisioningThread=null mPrepareDrmInProgress=false
> mActiveDrmScheme=false V/MediaPlayer: cleanDrmObj: mDrmObj=null
> mDrmSessionId=null W/MediaPlayer: mediaplayer went away with unhandled
> events
MainActivity
package com.jiat.yesradio;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements MusicStoppedListener {
private ImageView imagePlayPause;
String stream = "https://radio.lankayes.lk/8002/stream";
boolean musicPlaying = false;
Intent serviceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
System.out.println("onCreate MainA");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imagePlayPause = (ImageView) findViewById(R.id.imagePlayPause);
imagePlayPause.setImageResource(R.drawable.play_icon);
serviceIntent = new Intent(this, MyPlayService.class);
// serviceIntent = new Intent(this, SimpleMyPlayService.class);
ApplicationClass.context = (Context) MainActivity.this;
imagePlayPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("onClick");
if (!musicPlaying) {
System.out.println("onClick_inside_music_player");
startService(serviceIntent);
playAudio();
imagePlayPause.setImageResource(R.drawable.pause_icon);
musicPlaying = true;
}
else {
stopPlayService();
stopService(serviceIntent);
imagePlayPause.setImageResource(R.drawable.play_icon);
musicPlaying = false;
}
}
});
}
#Override
public void onBackPressed(){
System.out.println("onBackPressed");
/* serviceIntent.addCategory(Intent.CATEGORY_HOME);
serviceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(serviceIntent);*/
moveTaskToBack(true); //activity.moveTaskToBack(true);
}
private void stopPlayService() {
System.out.println("stopPlayService");
try {
stopService(serviceIntent);
} catch (SecurityException e) {
Toast.makeText(this, "Error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void playAudio() {
System.out.println("playAudio");
serviceIntent.putExtra("AudioLink", stream);
// serviceIntent.putExtra("SimpleAudioLink", stream);
try {
startService(serviceIntent);
} catch (SecurityException e) {
Toast.makeText(this, "Error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onMusicStopped() {
System.out.println("onMusicStopped");
imagePlayPause.setImageResource(R.drawable.play_icon);
musicPlaying = false;
}
}
MyPlayService class.
package com.jiat.yesradio;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.widget.Toast;
public class MyPlayService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener,
MediaPlayer.OnBufferingUpdateListener {
private MediaPlayer mediaPlayer;
String link;
private MusicStoppedListener musicStoppedListener;
Context context;
public MyPlayService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
System.out.println("onBind");
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
System.out.println("onCreate");
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setLooping(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
link = intent.getStringExtra("AudioLink");
mediaPlayer.reset();
musicStoppedListener = (MusicStoppedListener) ApplicationClass.context;
if (!mediaPlayer.isPlaying()) {
try {
mediaPlayer.setDataSource(link);
mediaPlayer.prepareAsync();
} catch (Exception e) {
Toast.makeText(this, "Error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("onDestroy");
if (mediaPlayer != null) {
System.out.println("onDestroy1");
if (mediaPlayer.isPlaying()) {
System.out.println("onDestroy2");
mediaPlayer.stop();
}
mediaPlayer.release();
}
}
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
System.out.println("onBufferingUpdate");
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
/* if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
musicStoppedListener.onMusicStopped();
stopSelf();*/
System.out.println("onCompletion");
}
#Override
public boolean onError(MediaPlayer mediaPlayer, int what, int i1) {
System.out.println("onError");
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Toast.makeText(this, "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK", Toast.LENGTH_SHORT).show();
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Toast.makeText(this, "MEDIA_ERROR_SERVER_DIED", Toast.LENGTH_SHORT).show();
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Toast.makeText(this, "MEDIA_ERROR_UNKNOWN", Toast.LENGTH_SHORT).show();
break;
}
return false;
}
#Override
public boolean onInfo(MediaPlayer mediaPlayer, int i, int i1) {
System.out.println("onInfo");
return false;
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
System.out.println("onPrepared");
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
#Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
System.out.println("onSeekComplete");
}
}
I created a virtual assistant app in Android Studio and it working fine until I exit the app window and the process stops. I want to make the app run in the background always so when it get's the wake word anytime it will respond. I tried using a Service but I couldn't make it work.
Can you help me please?
This is my code:
package com.eylon.jarvis;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import java.util.ArrayList;
import java.util.Locale;
import ai.picovoice.porcupine.Porcupine;
import ai.picovoice.porcupine.PorcupineActivationException;
import ai.picovoice.porcupine.PorcupineActivationLimitException;
import ai.picovoice.porcupine.PorcupineActivationRefusedException;
import ai.picovoice.porcupine.PorcupineActivationThrottledException;
import ai.picovoice.porcupine.PorcupineException;
import ai.picovoice.porcupine.PorcupineInvalidArgumentException;
import ai.picovoice.porcupine.PorcupineManager;
import ai.picovoice.porcupine.PorcupineManagerCallback;
enum AppState {
STOPPED,
WAKEWORD,
STT
}
public class MainActivity extends AppCompatActivity {
private static final String ACCESS_KEY = "Oc8ZOSkVtJHWKhVW3iGMedHDSCSXn6P4vQtrQBl8hNLXwLmxLhs2AA==";
private PorcupineManager porcupineManager = null;
TextView textView;
ToggleButton button;
private SpeechRecognizer speechRecognizer;
private Intent speechRecognizerIntent;
private AppState currentState;
private void displayError(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private final PorcupineManagerCallback porcupineManagerCallback = new PorcupineManagerCallback() {
#Override
public void invoke(int keywordIndex) {
runOnUiThread(() -> {
textView.setText("");
try {
// need to stop porcupine manager before speechRecognizer can start listening.
porcupineManager.stop();
} catch (PorcupineException e) {
displayError("Failed to stop Porcupine.");
return;
}
speechRecognizer.startListening(speechRecognizerIntent);
currentState = AppState.STT;
});
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text1);
button = findViewById(R.id.button1);
if (!SpeechRecognizer.isRecognitionAvailable(this)) {
displayError("Speech Recognition not available.");
}
// Creating the Intent of the Google speech to text and adding extra variables.
speechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE, "en-US");
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Start speaking");
try {
porcupineManager = new PorcupineManager.Builder()
.setAccessKey(ACCESS_KEY)
.setKeyword(Porcupine.BuiltInKeyword.JARVIS)
.setSensitivity(0.7f)
.build(getApplicationContext(), porcupineManagerCallback);
} catch (PorcupineInvalidArgumentException e) {
onPorcupineInitError(
String.format("%s\nEnsure your accessKey '%s' is a valid access key.", e.getMessage(), ACCESS_KEY)
);
} catch (PorcupineActivationException e) {
onPorcupineInitError("AccessKey activation error");
} catch (PorcupineActivationLimitException e) {
onPorcupineInitError("AccessKey reached its device limit");
} catch (PorcupineActivationRefusedException e) {
onPorcupineInitError("AccessKey refused");
} catch (PorcupineActivationThrottledException e) {
onPorcupineInitError("AccessKey has been throttled");
} catch (PorcupineException e) {
onPorcupineInitError("Failed to initialize Porcupine " + e.getMessage());
}
currentState = AppState.STOPPED;
}
private void onPorcupineInitError(final String errorMessage) {
runOnUiThread(() -> {
TextView errorText = findViewById(R.id.text1);
errorText.setText(errorMessage);
ToggleButton recordButton = findViewById(R.id.button1);
recordButton.setChecked(false);
recordButton.setEnabled(false);
});
}
#Override
protected void onStop() {
if (button.isChecked()) {
stopService();
button.toggle();
speechRecognizer.destroy();
}
super.onStop();
}
private boolean hasRecordPermission() {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED;
}
private void requestRecordPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},
0);
}
#SuppressLint("SetTextI18n")
private void playback(int milliSeconds) {
speechRecognizer.stopListening();
currentState = AppState.WAKEWORD;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (currentState == AppState.WAKEWORD) {
porcupineManager.start();
textView.setText("Listening for " + Porcupine.BuiltInKeyword.JARVIS + " ...");
}
}, milliSeconds);
}
private void stopService() {
if (porcupineManager != null) {
try {
porcupineManager.stop();
} catch (PorcupineException e) {
displayError("Failed to stop porcupine.");
}
}
textView.setText("");
speechRecognizer.stopListening();
speechRecognizer.destroy();
currentState = AppState.STOPPED;
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length == 0 || grantResults[0] == PackageManager.PERMISSION_DENIED) {
displayError("Microphone permission is required for this app!");
requestRecordPermission();
} else {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(new SpeechListener());
playback(0);
}
}
public void process(View view) {
if (button.isChecked()) {
if (hasRecordPermission()) {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(new SpeechListener());
playback(0);
} else {
requestRecordPermission();
}
} else {
stopService();
}
}
private class SpeechListener implements RecognitionListener {
#Override
public void onReadyForSpeech(Bundle params) {
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onRmsChanged(float rmsdB) {
}
#Override
public void onBufferReceived(byte[] buffer) {
}
#Override
public void onEndOfSpeech() {
}
#SuppressLint("SwitchIntDef")
#Override
public void onError(int error) {
switch (error) {
case SpeechRecognizer.ERROR_AUDIO:
displayError("Error recording audio.");
break;
case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
displayError("Insufficient permissions.");
break;
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
case SpeechRecognizer.ERROR_NETWORK:
displayError("Network Error.");
break;
case SpeechRecognizer.ERROR_NO_MATCH:
if (button.isChecked()) {
displayError("No recognition result matched.");
playback(1000);
}
case SpeechRecognizer.ERROR_CLIENT:
return;
case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
displayError("Recognition service is busy.");
break;
case SpeechRecognizer.ERROR_SERVER:
displayError("Server Error.");
break;
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
displayError("No speech input.");
break;
default:
displayError("Something wrong occurred.");
}
stopService();
button.toggle();
}
#Override
public void onResults(Bundle results) {
ArrayList<String> data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
audioResponseSelecting(data.get(0).toLowerCase(Locale.ROOT));
textView.setText(data.get(0));
playback(3000);
}
#Override
public void onPartialResults(Bundle partialResults) {
ArrayList<String> data = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
audioResponseSelecting(data.get(0).toLowerCase(Locale.ROOT));
textView.setText(data.get(0));
}
#Override
public void onEvent(int eventType, Bundle params) {
}
}
// The response selecting function.
public void audioResponseSelecting(String transcript)
{
if (transcript.equals(("Good morning").toLowerCase(Locale.ROOT)))
{
executeResponse(R.raw.good_morning);
}
else if (transcript.equals(("Who is your creator").toLowerCase(Locale.ROOT)))
{
executeResponse(R.raw.creator);
}
}
// The audio file response execution function.
public void executeResponse(final int audio)
{
MediaPlayer response = MediaPlayer.create(MainActivity.this, audio);
response.start();
}
}
By design, all SpeechRecognizer's methods "must be invoked only from the main application thread."
Main application thread is also referred to as "UI thread".
This means that SpeechRecognizer cannot run in a service.
I am trying to transmit the Android camera image via rtsp to Wowza, however without success. It does not return any error, but also in the local Wowza does not show any traffic. I have the local Wowza for testing in http://localhost:8088/
I am using the Libstreaming library to send the rtsp stream.
MainActivity.java
package com.security.testeslibstreaming;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowManager;
import net.majorkernelpanic.streaming.Session;
import net.majorkernelpanic.streaming.SessionBuilder;
import net.majorkernelpanic.streaming.audio.AudioQuality;
import net.majorkernelpanic.streaming.gl.SurfaceView;
import net.majorkernelpanic.streaming.rtsp.RtspClient;
public class MainActivity extends AppCompatActivity implements RtspClient.Callback, Session.Callback, SurfaceHolder.Callback {
// log tag
public final static String TAG = MainActivity.class.getSimpleName();
// surfaceview
private static SurfaceView mSurfaceView;
// Rtsp session
private Session mSession;
private static RtspClient mClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mSurfaceView.getHolder().addCallback(this);
// Initialize RTSP client
initRtspClient();
}
#Override
protected void onResume() {
super.onResume();
toggleStreaming();
}
#Override
protected void onPause(){
super.onPause();
toggleStreaming();
}
private void initRtspClient() {
// Configures the SessionBuilder
mSession = SessionBuilder.getInstance()
.setContext(getApplicationContext())
.setAudioEncoder(SessionBuilder.AUDIO_NONE)
.setAudioQuality(new AudioQuality(8000, 16000))
.setVideoEncoder(SessionBuilder.VIDEO_H264)
.setSurfaceView(mSurfaceView).setPreviewOrientation(0)
.setCallback(this).build();
// Configures the RTSP client
mClient = new RtspClient();
mClient.setSession(mSession);
mClient.setCallback(this);
mSurfaceView.setAspectRatioMode(SurfaceView.ASPECT_RATIO_PREVIEW);
String ip, port, path;
// We parse the URI written in the Editext
Pattern uri = Pattern.compile("rtsp://(.+):(\\d+)/(.+)");
Matcher m = uri.matcher(AppConfig.STREAM_URL);
m.find();
ip = m.group(1);
port = m.group(2);
path = m.group(3);
mClient.setCredentials(AppConfig.PUBLISHER_USERNAME,
AppConfig.PUBLISHER_PASSWORD);
mClient.setServerAddress(ip, Integer.parseInt(port));
mClient.setStreamPath("/" + path);
}
private void toggleStreaming() {
if (!mClient.isStreaming()) {
// Start camera preview
mSession.startPreview();
// Start video stream
mClient.startStream();
} else {
// already streaming, stop streaming
// stop camera preview
mSession.stopPreview();
// stop streaming
mClient.stopStream();
}
}
#Override
public void onDestroy() {
super.onDestroy();
mClient.release();
mSession.release();
mSurfaceView.getHolder().removeCallback(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onSessionError(int reason, int streamType, Exception e) {
switch (reason) {
case Session.ERROR_CAMERA_ALREADY_IN_USE:
break;
case Session.ERROR_CAMERA_HAS_NO_FLASH:
break;
case Session.ERROR_INVALID_SURFACE:
break;
case Session.ERROR_STORAGE_NOT_READY:
break;
case Session.ERROR_CONFIGURATION_NOT_SUPPORTED:
break;
case Session.ERROR_OTHER:
break;
}
if (e != null) {
alertError(e.getMessage());
e.printStackTrace();
}
}
private void alertError(final String msg) {
final String error = (msg == null) ? "Unknown error: " : msg;
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage(error).setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
#Override
public void onRtspUpdate(int message, Exception exception) {
switch (message) {
case RtspClient.ERROR_CONNECTION_FAILED:
case RtspClient.ERROR_WRONG_CREDENTIALS:
alertError(exception.getMessage());
exception.printStackTrace();
break;
}
}
#Override
public void onPreviewStarted() {
}
#Override
public void onSessionConfigured() {
}
#Override
public void onSessionStarted() {
}
#Override
public void onSessionStopped() {
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void onBitrateUpdate(long bitrate) {
}
}
AppConfig.java
package com.security.testeslibstreaming;
public class AppConfig {
public static final String STREAM_URL = "rtsp://192.XXX.XX.XX:1935/live/myStream";
public static final String PUBLISHER_USERNAME = "barrXXXXXXX";
public static final String PUBLISHER_PASSWORD = "XXXXXXXXXX";
}
I am a newbie in Android Developer
I am building a game app on Android Studio. But, I have had a problem about Background music while playing game. I have used Bound Service to handle through the class: MusicService extends Service implements MediaPlayer.OnErrorListener. But, my App was stopped when I run.
I have tried to fixed and explored solutions, but, I can't run app...
This is source code:
MusicService.java
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MusicService extends Service implements MediaPlayer.OnErrorListener {
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public MediaPlayer Player;
public MusicService() {
}
public class ServiceBinder extends Binder {
public MusicService getService() {
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
Player = MediaPlayer.create(this, R.raw.one);
mPlayer.setOnErrorListener(this);
if (mPlayer != null) {
mPlayer.setLooping(true);
mPlayer.setVolume(100, 100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int
extra) {
onError(mPlayer, what, extra);
return true;
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPlayer.start();
return START_STICKY;
}
public void pauseMusic() {
if (mPlayer.isPlaying()) {
mPlayer.pause();
length = mPlayer.getCurrentPosition();
}
}
public void resumeMusic() {
if (mPlayer.isPlaying() == false) {
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic() {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
return false;
}
}
and, MainActivity.java
public class MainActivity extends AppCompatActivity {
private boolean mIsBound = false;
private MusicService mServ;
private ServiceConnection Scon =new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.ServiceBinder binder = (MusicService.ServiceBinder)service;
mServ =binder.getService();
}
public void onServiceDisconnected(ComponentName name) {
mServ = null;
}
};
// Activity create UI its
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Activity start.
#Override
protected void onStart() {
super.onStart();
// create Intent for MusicService.
Intent intent = new Intent(MainActivity.this,MusicService.class);
// call method bindService(..) to bind activity
this.bindService(intent, Scon, Context.BIND_AUTO_CREATE);
}
//Activity stop
#Override
protected void onStop() {
super.onStop();
if (mIsBound) {
this.unbindService(Scon);
mIsBound = false;
}
}
Then, I didn't also forget add the code following in AndroidManifest
<service
android:name=".MusicService"
android:enabled="true"
android:exported="true"></service>
That's all problems mine. This makes me so confuse
Help you, please
Thank you very much
Can you add more log debug in logcat? Not sure but I guess problem is you call:
mPlayer.start();
in onStartComand(). Your service should implement MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,MediaPlayer.OnCompletionListener and above function should be call in
void onPrepared(MediaPlayer mp)
This question already has answers here:
Why does ArrayIndexOutOfBoundsException occur and how to avoid it in Android? [closed]
(4 answers)
Closed 6 years ago.
I'm developing a music application but i keep geting this error, i don't understand it and dont know how to solve. I'm stuck for 2 day trying to re-write the code but still the error pops-up.My logcat comes up as java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0. And please elaborate the main problem.
This MainActivity.java
package com.developer.bunamay.player;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SeekBar;
import android.widget.TextView;
import java.util.List;
public class MainActivity extends AppCompatActivity implements MusicService.MediaFileListener {
public static final PlayerUtils PlayerController = PlayerUtils.getInstance();
public static final int PICK_FOLDER_REQUEST = 8;
private MediaFileAdapter mediaFileAdapter = null;
private TextView playingSong;
private Button btnPause, btnPlay, btnNext, btnPrevious;
private Button btnStop;
private LinearLayout linearLayoutPlayingSong;
private ListView mediaListView;
private SeekBar seekbar;
private TextView textBufferDuration, textDuration;
private ImageView imageViewAlbumArt;
private Context context;
MusicService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = MainActivity.this;
init();
if (!PlayerUtils.isServiceRunning(MusicService.class.getName(), getApplicationContext())) {
Intent i = new Intent(getApplicationContext(), MusicService.class);
startService(i);
}
}
private void init() {
initViews();
setListeners();
playingSong.setSelected(true);
seekbar.getProgressDrawable().setColorFilter(ContextCompat.getColor(context, R.color.colorText), PorterDuff.Mode.SRC_IN);
if (PlayerController.SONGS_LIST.size() <= 0) {
PlayerController.SONGS_LIST = PlayerController.listOfSongs(getApplicationContext());
}
initAdapter();
}
private void initAdapter() {
mediaFileAdapter = new MediaFileAdapter(this, R.layout.custom_list, PlayerController.SONGS_LIST);
mediaListView.setAdapter(mediaFileAdapter);
mediaListView.setTextFilterEnabled(true);
mediaListView.setFastScrollEnabled(true);
}
private void initViews() {
playingSong = (TextView) findViewById(R.id.textNowPlaying);
mediaListView = (ListView) findViewById(R.id.listViewMusic);
btnPause = (Button) findViewById(R.id.btnPause);
btnPlay = (Button) findViewById(R.id.btnPlay);
linearLayoutPlayingSong = (LinearLayout) findViewById(R.id.linearLayoutPlayingSong);
seekbar = (SeekBar) findViewById(R.id.seekBar);
btnStop = (Button) findViewById(R.id.btnStop);
textBufferDuration = (TextView) findViewById(R.id.textBufferDuration);
textDuration = (TextView) findViewById(R.id.textDuration);
imageViewAlbumArt = (ImageView) findViewById(R.id.imageViewAlbumArt);
btnNext = (Button) findViewById(R.id.btnNext);
btnPrevious = (Button) findViewById(R.id.btnPrevious);
}
private Animation setButtonAnimation() {
return AnimationUtils.loadAnimation(this, R.anim.button_anim);
}
// defines callbacks for service binding, passed to bindService()
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
MusicService.LocalBinder binder = (MusicService.LocalBinder) service;
mService = binder.getService();
mService.setListener(MainActivity.this);
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
mService = null;
}
};
private void setListeners() {
mediaListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View item, int position, long id) {
PlayerController.SONG_PAUSED = false;
PlayerController.SONG_NUMBER = position;
boolean isServiceRunning = PlayerUtils.isServiceRunning(MusicService.class.getName(), getApplicationContext());
if (!isServiceRunning) {
Intent i = new Intent(getApplicationContext(), MusicService.class);
startService(i);
} else {
PlayerController.SONG_CHANGE_HANDLER.sendMessage(
PlayerController.SONG_CHANGE_HANDLER.obtainMessage());
}
updateUI();
changeButton();
}
});
btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PlayerController.playControl(getApplicationContext());
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PlayerController.pauseControl(getApplicationContext());
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(setButtonAnimation());
PlayerController.nextControl(getApplicationContext());
}
});
btnPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(setButtonAnimation());
PlayerController.previousControl(getApplicationContext());
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (PlayerUtils.isServiceRunning(MusicService.class.getName(), getApplicationContext())) {
PlayerController.pauseControl(getApplicationContext());
}
linearLayoutPlayingSong.setVisibility(View.GONE);
}
});
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
// clicked position on the seekBar
int currentSeekBarPosition = seekBar.getProgress();
// 1% of song duration = song duration / 100%
int onePercentOfSongDuration = (mService.getDuration() / 100);
// associate song duration with clicked position on the seekBar
int changedPosition = currentSeekBarPosition * onePercentOfSongDuration;
// seek to selected position
PlayerController.seekToAnyControl(getApplicationContext(), changedPosition);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
protected void onPause() {
if (mBound) {
unbindService(mConnection);
}
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
Intent i = new Intent(getApplicationContext(), MusicService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
handleAudioFromOpenWithPopup();
boolean isServiceRunning = PlayerUtils.isServiceRunning(MusicService.class.getName(), getApplicationContext());
if (isServiceRunning) {
updateUI();
} else {
linearLayoutPlayingSong.setVisibility(View.GONE);
}
changeButton();
PlayerController.SEEKBAR_HANDLER = new Handler() {
#Override
public void handleMessage(Message msg) {
Integer i[] = (Integer[]) msg.obj;
textBufferDuration.setText(PlayerUtils.getDuration(i[0]));
textDuration.setText(PlayerUtils.getDuration(i[1]));
seekbar.setProgress(i[2]);
}
};
}
public void updateUI() {
MediaFile mediaFile = PlayerController.SONGS_LIST.get(PlayerController.SONG_NUMBER);
String nowPlayingTitleText = mediaFile.getTitle() + " " + mediaFile.getArtist() + "-" + mediaFile.getAlbum();
playingSong.setText(nowPlayingTitleText);
Bitmap albumArt = PlayerController.getAlbumart(context, mediaFile.getAlbumId());
if (albumArt != null) {
imageViewAlbumArt.setBackgroundDrawable(new BitmapDrawable(Resources.getSystem(), albumArt));
} else {
Bitmap defaultAlbumArt = PlayerController.getDefaultAlbumArt(context);
imageViewAlbumArt.setBackgroundDrawable(new BitmapDrawable(Resources.getSystem(), defaultAlbumArt));
}
linearLayoutPlayingSong.setVisibility(View.VISIBLE);
}
public void changeButton() {
if (PlayerController.SONG_PAUSED) {
btnPause.setVisibility(View.GONE);
btnPlay.setVisibility(View.VISIBLE);
} else {
btnPause.setVisibility(View.VISIBLE);
btnPlay.setVisibility(View.GONE);
}
}
public void changeUI() {
updateUI();
changeButton();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// init menu items for search
MenuItem itemSearchTitle = menu.findItem(R.id.action_search_title);
MenuItem itemSearchAlbum = menu.findItem(R.id.action_search_album);
MenuItem itemSearchArtist = menu.findItem(R.id.action_search_artist);
SearchView searchViewTitle = (SearchView) itemSearchTitle.getActionView();
SearchView searchViewAlbum = (SearchView) itemSearchAlbum.getActionView();
SearchView searchViewArtist = (SearchView) itemSearchArtist.getActionView();
searchViewTitle.setFocusable(true);
searchViewAlbum.setFocusable(true);
searchViewArtist.setFocusable(true);
// init searchable info for each menu item
searchViewTitle.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchViewTitle.setQueryHint("title...");
searchViewTitle.setIconified(true);
searchViewAlbum.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchViewAlbum.setQueryHint("album...");
searchViewAlbum.setIconified(true);
searchViewArtist.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchViewArtist.setQueryHint("artist...");
searchViewArtist.setIconified(true);
// set textChangeListeners for each type of search
final SearchView.OnQueryTextListener textChangeListenerTitle = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
if (!TextUtils.isEmpty(newText)) {
mediaFileAdapter.getFilter().filter(newText);
}
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
};
SearchView.OnQueryTextListener textChangeListenerAlbum = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
if (!TextUtils.isEmpty(newText)) {
mediaFileAdapter.getFilter().filter(newText);
}
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
};
SearchView.OnQueryTextListener textChangeListenerArtist = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
if (!TextUtils.isEmpty(newText)) {
mediaFileAdapter.getFilter().filter(newText);
}
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
};
// apply listeners to searchViews
searchViewTitle.setOnQueryTextListener(textChangeListenerTitle);
searchViewAlbum.setOnQueryTextListener(textChangeListenerAlbum);
searchViewArtist.setOnQueryTextListener(textChangeListenerArtist);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
// get music from specific folder
if (id == R.id.folder_music) {
Intent intent = new Intent(this, FolderPickerActivity.class);
startActivityForResult(intent, PICK_FOLDER_REQUEST);
return true;
}
// fetch all music from device
if (id == R.id.all_music) {
PlayerController.SONGS_LIST = PlayerController.listOfSongs(getApplicationContext());
initAdapter();
return true;
}
// search songs by title
if (id == R.id.action_search_title) {
PlayerController.SEARCH_TYPE = "TITLE";
return true;
}
// search songs by artist
if (id == R.id.action_search_artist) {
PlayerController.SEARCH_TYPE = "ARTIST";
return true;
}
// search songs by album
if (id == R.id.action_search_album) {
PlayerController.SEARCH_TYPE = "ALBUM";
return true;
}
if (id == R.id.action_sort_title) {
MediaFileComparator.sortByTitle(PlayerController.SONGS_LIST);
MediaFileAdapter mediaAdapter = (MediaFileAdapter) mediaListView.getAdapter();
mediaAdapter.notifyDataSetChanged();
return true;
}
if (id == R.id.action_sort_album) {
MediaFileComparator.sortByAlbum(PlayerController.SONGS_LIST);
MediaFileAdapter mediaAdapter = (MediaFileAdapter) mediaListView.getAdapter();
mediaAdapter.notifyDataSetChanged();
return true;
}
if (id == R.id.action_sort_artist) {
MediaFileComparator.sortByArtist(PlayerController.SONGS_LIST);
MediaFileAdapter mediaAdapter = (MediaFileAdapter) mediaListView.getAdapter();
mediaAdapter.notifyDataSetChanged();
return true;
}
if (id == R.id.action_sort_duration) {
MediaFileComparator.sortByDuration(PlayerController.SONGS_LIST);
MediaFileAdapter mediaAdapter = (MediaFileAdapter) mediaListView.getAdapter();
mediaAdapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == PICK_FOLDER_REQUEST) {
String pickedFolder = data.getStringExtra("pickedFolder");
Log.i("PICKER_FOLDER_TAG", pickedFolder);
// get last subfolder from path as WHERE arg
pickedFolder = getSelectionArg(pickedFolder);
Log.i("PICKER_FOLDER_WHERE_TAG", pickedFolder);
// reinit music list and adapter with data from specific folder
List<MediaFile> songsFromSpecificFolder = PlayerController.getSongsFromSpecificFolder(
getApplicationContext(), new String[]{pickedFolder}
);
if (songsFromSpecificFolder.size() != 0) {
PlayerController.SONGS_LIST = songsFromSpecificFolder;
PlayerController.SONG_NUMBER = 0;
initAdapter();
}
}
}
}
// receive audio action from 'Complete action with' pop-up
private void handleAudioFromOpenWithPopup() {
// receive Intent
Intent intent = getIntent();
// check action
String action = intent.getAction();
// if it's audio action view
if (action != null && action.equals("android.intent.action.VIEW")) {
// play song
PlayerController.playMusicFromActionPicker(this, intent.getData());
}
}
// get last subfolder from path as WHERE arg
private String getSelectionArg(String path) {
String sTag = "%";
// substring last directory in path
String lastSubfolder = path.substring(path.lastIndexOf("/") + 1);
return sTag + lastSubfolder + sTag;
}
#Override
public void onMediaFileChanged() {
changeUI();
}
#Override
public void onPlayPauseActionChanged() {
changeButton();
}
}
I've tried searching online varios times but i still dont understand.
Thanks
The root cause of the problem is that somewhere, either your code or some code that your code uses is doing something that is equivalent to this:
Object[] array = new Object[0];
...
System.out.println(array[0]);
Something created an array (of some type) with size ZERO, and it (or maybe something else) is trying to access the first element (index zero) of that array. That is beyond the end of the array ... and that results in an exception.
I can't see where you are creating a zero-length array in your code.
Could you have a look at the method protected void onResume()?
I think, you may have a problem in following lines:
Integer i[] = (Integer[]) msg.obj;
textBufferDuration.setText(PlayerUtils.getDuration(i[0]));
textDuration.setText(PlayerUtils.getDuration(i[1]));
seekbar.setProgress(i[2]);
First try running the program by commenting out those lines. It may happen that, on some occasions, your msg.obj is actually an array whose length is 0. Then you will get java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0. Hope it helps you.