Я занимаюсь разработкой сервиса проигрывателя фоновой музыки с уведомлением в Android.
При выполнении кода отображается ошибка метода CallBack из класса обслуживания.
Может кто-нибудь, пожалуйста, помогите мне решить эту ошибку?
Заранее спасибо.
Вот мой код MainActivity:
public class MainActivity extends AppCompatActivity implements NotificationService.Callbacks {
MediaPlayer mediaPlayer;
Intent serviceIntent;
NotificationService notificationService;
LinearLayout customMediaController;
Button playPauseButton, forwardButton, rewindButton;
SeekBar seekBar;
TextView timer;
ProgressBar loader;
ProgressBar progressBar;
Handler handler = new Handler();
RemoteViews notificationLayout;
PendingIntent pendingIntent;
NotificationManagerCompat notificationManager;
final Integer CALL = 0x2;
TelephonyManager telephonyManager;
PhoneStateListener phoneStateListener;
AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBindService();//start background service to control music while app is running in background
initialiseAllView();//iniatialise all UI part
handler.postDelayed(runnable, 1000);//update progress of song
setNotification();// show controllers in notification bar
callHandler();//to handle phone calls in between
audioHandler();// to handle another app playing song in between
}
Runnable runnable = new Runnable() {
@Override
public void run() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
playPauseButton.setBackgroundResource(R.drawable.ic_pause_circle_outline_black_24dp);
} else {
playPauseButton.setBackgroundResource(R.drawable.ic_play_circle_outline_black_24dp);
}
updateTimer();
}
handler.postDelayed(runnable, 1000);
}
};
//callback of controllers from notification bar
@Override
public void updateClient(final MediaPlayer mediaPlayer) {
this.mediaPlayer = mediaPlayer;
if (this.mediaPlayer != null) {
seekBar.setMax(this.mediaPlayer.getDuration());
this.mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
progressBar.setSecondaryProgress(percent);
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekMediaPlayer(seekBar);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.seekTo(0);
mp.start();
}
});
}
}
public void onForwardButtonClick(View view) {
if (mediaPlayer != null) {
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() + 2000);
seekBar.setProgress(mediaPlayer.getCurrentPosition() + 2000);
}
}
public void onRewindButtonClick(View view) {
if (mediaPlayer != null) {
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() - 2000);
seekBar.setProgress(mediaPlayer.getCurrentPosition() - 2000);
}
}
public void onPlayPauseClick(View view) {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
pauseMusic();
} else {
playMusic();
}
}
}
public void playMusic() {
if (mediaPlayer != null) {
mediaPlayer.start();
playPauseButton.setBackgroundResource(R.drawable.ic_pause_circle_outline_black_24dp);
notificationLayout.setImageViewResource(R.id.playnotify, R.drawable.ic_pause_black_24dp);
updateNotification();
}
}
public void pauseMusic() {
if (mediaPlayer != null) {
mediaPlayer.pause();
playPauseButton.setBackgroundResource(R.drawable.ic_play_circle_outline_black_24dp);
notificationLayout.setImageViewResource(R.id.playnotify, R.drawable.ic_play_arrow_black_24dp);
updateNotification();
}
}
private void seekMediaPlayer(SeekBar seekBar) {
mediaPlayer.seekTo(seekBar.getProgress());
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
NotificationService.LocalBinder binder = (NotificationService.LocalBinder) service;
notificationService = binder.getServiceInstance();
notificationService.registerClient(MainActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
public void startBindService() {
serviceIntent = new Intent(MainActivity.this, NotificationService.class);
serviceIntent.putExtra("Hello","Hello");
serviceIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(serviceIntent);
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
}
public void initialiseAllView() {
customMediaController = findViewById(R.id.customMediaController);
progressBar = findViewById(R.id.progressBar);
loader=findViewById(R.id.progress);
playPauseButton = findViewById(R.id.bttn);
forwardButton = findViewById(R.id.forward);
rewindButton = findViewById(R.id.rewind);
timer = findViewById(R.id.timer);
seekBar = findViewById(R.id.seekBar);
}
public void updateNotification() {
Notification customNotification = new NotificationCompat.Builder(this, "notify")
.setSmallIcon(R.drawable.ic_music_note_black_24dp)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(1, customNotification);
}
public void setNotification() {
notificationLayout = new RemoteViews(getPackageName(), R.layout.notification);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Intent playIntent = new Intent(this, NotificationService.class);
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pendingPlayIntent = PendingIntent.getService(this, 0,
playIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.playnotify, pendingPlayIntent);
Intent rewindIntent = new Intent(this, NotificationService.class);
rewindIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent pendingRewindIntent = PendingIntent.getService(this, 0,
rewindIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.rewindnotify, pendingRewindIntent);
Intent forwardIntent = new Intent(this, NotificationService.class);
forwardIntent.setAction(Constants.ACTION.NEXT_ACTION);
PendingIntent pendingForwardIntent = PendingIntent.getService(this, 0,
forwardIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.forwardnotify, pendingForwardIntent);
}
public void callHandler() {
int permissionGranted = askForPermission(Manifest.permission.READ_PHONE_STATE, CALL);
if (permissionGranted == 1) {
phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
//Incoming call: Pause music
pauseMusic();
} else if (state == TelephonyManager.CALL_STATE_IDLE) {
//Not in call: Play music
if (mediaPlayer != null && !mediaPlayer.isPlaying())
playMusic();
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
//A call is dialing, active or on hold
pauseMusic();
}
super.onCallStateChanged(state, incomingNumber);
}
};
telephonyManager = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
}
public void audioHandler() {
onAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
pauseMusic();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
pauseMusic();
break;
}
}
};
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
// Request audio focus for play back
if (audioManager != null) {
audioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}
}
public void updateTimer() {
int currentPosition = mediaPlayer.getCurrentPosition();
if(currentPosition!=0)
{
loader.setVisibility(View.GONE);
}
seekBar.setProgress(currentPosition);
int t = currentPosition / 1000;
int min = t / 60;
int sec = t % 60;
if (min < 10) {
if (sec < 10) {
String string = "0" + min + ":0" + sec;
timer.setText(string);
} else {
String string = "0" + min + ":" + sec;
timer.setText(string);
}
}
if (min >= 10) {
if (sec < 10) {
String string = min + ":0" + sec;
timer.setText(string);
} else {
String string = min + ":" + sec;
timer.setText(string);
}
}
}
private int askForPermission(String permission, Integer requestCode) {
if (ContextCompat.checkSelfPermission(MainActivity.this, permission) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
//This is called if user has denied the permission before
//In this case I am just asking the permission again
ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
}
} else {
return 1;
}
return 0;
}
@Override
protected void onDestroy() {
super.onDestroy();
stopService(serviceIntent);
if (telephonyManager != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
}
}
Вот мой код класса обслуживания:
public class NotificationService extends Service {
Callbacks activity;
MediaPlayer mediaPlayer;
RemoteViews notificationLayout;
NotificationManagerCompat notificationManager;
private final IBinder mBinder = new LocalBinder();
PendingIntent pendingIntent;
String url = "https://www.betezda.com/songs/English/audio/God%20is%20here.mp3"; // your URL here
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
//returns the instance of the service
public class LocalBinder extends Binder {
public NotificationService getServiceInstance() {
return NotificationService.this;
}
}
//Here Activity register to the service as Callbacks client
public void registerClient(Activity activity) {
this.activity = (Callbacks) activity;
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
String hello = intent.getExtras().getString("Hello");
Toast.makeText(getApplicationContext(), hello, Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(this, R.raw.cheshta);
mediaPlayer.start();
activity.updateClient(mediaPlayer);
/* mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
activity.updateClient(mediaPlayer);
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});*/
handleNotification(intent);
} else {
handleNotification(intent);
}
return Service.START_STICKY;
}
private void handleNotification(Intent intent) {
if (intent.getAction() != null) {
switch (intent.getAction()) {
case Constants.ACTION.STARTFOREGROUND_ACTION:
showNotification();
break;
case Constants.ACTION.PLAY_ACTION:
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
notificationLayout.setImageViewResource(R.id.playnotify, R.drawable.ic_play_arrow_black_24dp);
updateNotification();
} else {
mediaPlayer.start();
notificationLayout.setImageViewResource(R.id.playnotify, R.drawable.ic_pause_black_24dp);
updateNotification();
}
break;
case Constants.ACTION.PREV_ACTION: {
int pos = mediaPlayer.getCurrentPosition();
mediaPlayer.seekTo(pos - 2000);
break;
}
case Constants.ACTION.NEXT_ACTION: {
int pos = mediaPlayer.getCurrentPosition();
mediaPlayer.seekTo(pos + 2000);
break;
}
}
}
}
private void showNotification() {
notificationLayout = new RemoteViews(getPackageName(), R.layout.notification);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Intent playIntent = new Intent(this, NotificationService.class);
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pendingPlayIntent = PendingIntent.getService(this, 0,
playIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.playnotify, pendingPlayIntent);
Intent rewindIntent = new Intent(this, NotificationService.class);
rewindIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent pendingRewindIntent = PendingIntent.getService(this, 0,
rewindIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.rewindnotify, pendingRewindIntent);
Intent forwardIntent = new Intent(this, NotificationService.class);
forwardIntent.setAction(Constants.ACTION.NEXT_ACTION);
PendingIntent pendingForwardIntent = PendingIntent.getService(this, 0,
forwardIntent, 0);
notificationLayout.setOnClickPendingIntent(R.id.forwardnotify, pendingForwardIntent);
updateNotification();
}
@Override
public void onDestroy() {
super.onDestroy();
notificationManager.cancel(1);
}
public void updateNotification() {
Notification customNotification = new NotificationCompat.Builder(this, "notify")
.setSmallIcon(R.drawable.ic_music_note_black_24dp)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(1, customNotification);
}
public interface Callbacks {
void updateClient(MediaPlayer mediaPlayer);
}
}
И это показывает ошибку
java.lang.RuntimeException: Unable to start service NotificationService@870853f with Intent { act=startforeground cmp=newmediaplayer/.NotificationService (has extras) }: java.lang.NullPointerException: Attempt to invoke interface method 'void NotificationService$Callbacks.updateClient(android.media.MediaPlayer)' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3335)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1578)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void NotificationService$Callbacks.updateClient(android.media.MediaPlayer)' on a null object reference
at NotificationService.onStartCommand(NotificationService.java:53)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3318)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1578)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Показывает ошибку Activity.updateClient (mediaPlayer); в классе обслуживания.
Метод обратного вызова не получает активность.