按照[本教程](http://www.tutorialsface.com/2015/08/android-custom-notification-tutorial),我最终得到了通知中显示的控件,但都没有响应(除了显示作者所包含的Toasts)。
控件似乎不会以任何方式绑定到音乐服务。我尝试创建广播,直接从通知中调用服务,创建服务的新实例。我已经尝试了很多我甚至不能记住它们的东西。我见过人们问过类似的问题,但我没有尝试过任何工作。现在,我已经尝试了很多这样的事情,以至于我对自己认为自己走在正确道路上的时间/地点感到困惑。关于如何使这些控件正常运行的任何想法?
通知服务:
public class NotificationService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constant.ACTION.STARTFOREGROUND_ACTION)) {
showNotification();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
} else if (intent.getAction().equals(Constant.ACTION.PREV_ACTION)) {
Toast.makeText(this, "Clicked Previous", Toast.LENGTH_SHORT).show();
Log.i("NS", "Clicked Previous");
} else if (intent.getAction().equals(Constant.ACTION.PLAY_ACTION)) {
Log.i("NS", "Clicked Play");
} else if (intent.getAction().equals(Constant.ACTION.NEXT_ACTION)) {
Toast.makeText(this, "Clicked Next", Toast.LENGTH_SHORT).show();
Log.i("NS", "Clicked Next");
} else if (intent.getAction().equals(
Constant.ACTION.STOPFOREGROUND_ACTION)) {
Log.i("NS", "Received Stop Foreground Intent");
Toast.makeText(this, "Service Stoped", Toast.LENGTH_SHORT).show();
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void showNotification() {
Notification status;
// Using RemoteViews to bind custom layouts into Notification
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.status_bar);
RemoteViews bigViews = new RemoteViews(getPackageName(),
R.layout.status_bar_expanded);
// showing default album image
views.setViewVisibility(R.id.status_bar_icon, View.VISIBLE);
views.setViewVisibility(R.id.status_bar_album_art, View.GONE);
bigViews.setImageViewBitmap(R.id.status_bar_album_art,
Constant.getDefaultAlbumArt(this));
Intent notificationIntent = new Intent(this, NotificationService.class);
notificationIntent.setAction(Constant.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Intent previousIntent = new Intent(this, NotificationService.class);
previousIntent.setAction(Constant.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
previousIntent, 0);
Intent playIntent = new Intent(this, NotificationService.class);
playIntent.setAction(Constant.ACTION.PLAY_ACTION);
PendingIntent pplayIntent = PendingIntent.getService(this, 0,
playIntent, 0);
Intent nextIntent = new Intent(this, NotificationService.class);
nextIntent.setAction(Constant.ACTION.NEXT_ACTION);
PendingIntent pnextIntent = PendingIntent.getService(this, 0,
nextIntent, 0);
Intent closeIntent = new Intent(this, NotificationService.class);
closeIntent.setAction(Constant.ACTION.STOPFOREGROUND_ACTION);
PendingIntent pcloseIntent = PendingIntent.getService(this, 0,
closeIntent, 0);
views.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
views.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
views.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
views.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
views.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
bigViews.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
views.setTextViewText(R.id.status_bar_track_name, "Song Title");
bigViews.setTextViewText(R.id.status_bar_track_name, "Song Title");
views.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
bigViews.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
bigViews.setTextViewText(R.id.status_bar_album_name, "Album Name");
status = new Notification.Builder(this).build();
status.contentView = views;
status.bigContentView = bigViews;
status.flags = Notification.FLAG_ONGOING_EVENT;
status.icon = R.drawable.ic_launcher;
status.contentIntent = pendingIntent;
startForeground(Constant.NOTIFICATION_ID.FOREGROUND_SERVICE, status);
}
}
MusicService:
public class MusicService extends Service implements
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener {
//media player
private MediaPlayer player;
//song list
private ArrayList<Song> songs;
//current position
private int songPosn;
private final IBinder musicBind = new MusicBinder();
private String songTitle="";
private static final int NOTIFY_ID=1;
private boolean shuffle=false;
private Random rand;
public void onCreate(){
//create the service
super.onCreate();
songPosn=0;
player = new MediaPlayer();
initMusicPlayer();
rand=new Random();
}
public void initMusicPlayer(){
//set player properties
player.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public void setList(ArrayList<Song> theSongs){
songs=theSongs;
}
public class MusicBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
public void setShuffle(){
if(shuffle) shuffle=false;
else shuffle=true;
}
public void playSong(){
player.reset();
//get song
Song playSong = songs.get(songPosn);
//get id
long currSong = playSong.getID();
//set uri
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
currSong);
try{
player.setDataSource(getApplicationContext(), trackUri);
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
songTitle=playSong.getTitle();
}
public void setSong(int songIndex){
songPosn=songIndex;
}
public int getPosn(){
return player.getCurrentPosition();
}
public int getDur(){
return player.getDuration();
}
public boolean isPng(){
return player.isPlaying();
}
public void pausePlayer(){
player.pause();
}
public void seek(int posn){
player.seekTo(posn);
}
public void go(){
player.start();
}
public void playPrev(){
songPosn--;
if(songPosn<0) songPosn=songs.size()-1;
playSong();
}
//skip to next
public void playNext(){
if(shuffle){
int newSong = songPosn;
while(newSong==songPosn){
newSong=rand.nextInt(songs.size());
}
songPosn=newSong;
}
else{
songPosn++;
if(songPosn>=songs.size()) songPosn=0;
}
playSong();
}
@Override
public void onDestroy() {
stopForeground(true);
}
@Override
public IBinder onBind(Intent intent) {
return musicBind;
}
@Override
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
@Override
public void onCompletion(MediaPlayer mp) {
if(player.getCurrentPosition()>0){
mp.reset();
playNext();
}
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onPrepared(MediaPlayer mp) {
//start playback
mp.start();
Intent onPreparedIntent = new Intent("MEDIA_PLAYER_PREPARED");
LocalBroadcastManager.getInstance(this).sendBroadcast(onPreparedIntent);
Intent notIntent = new Intent(this, MusicPlayer.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0,
notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.player_play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing")
.setContentText(songTitle);
Notification not = builder.build();
Intent serviceIntent = new Intent(MusicService.this, NotificationService.class);
serviceIntent.setAction(Constant.ACTION.STARTFOREGROUND_ACTION);
startService(serviceIntent);
}
}
音乐播放器:
public class MusicPlayer extends AppCompatActivity implements MediaPlayerControl {
private ArrayList<Song> songList;
private ListView songView;
public MusicService musicSrv;
private Intent playIntent;
private boolean musicBound=false;
private MusicController controller;
private boolean paused=false, playbackPaused=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player);
songView = (ListView)findViewById(R.id.song_list);
songList = new ArrayList<Song>();
getSongList();
Collections.sort(songList, new Comparator<Song>(){
public int compare(Song a, Song b){
return a.getArtist().compareTo(b.getArtist());
}
});
songAdapter songAdt = new songAdapter(this, songList);
songView.setAdapter(songAdt);
setController();
FloatingActionButton fabRandom = (FloatingActionButton)findViewById(R.id.fabRandom);
fabRandom.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
//play next
private void playNext(){
musicSrv.playNext();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
private void playPrev(){
musicSrv.playPrev();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
public void songPicked(View view){
musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
musicSrv.playSong();
if(playbackPaused){
setController();
playbackPaused=false;
}
setController();
controller.show(0);
}
@Override
protected void onPause(){
super.onPause();
paused=true;
}
@Override
protected void onResume(){
super.onResume();
// Set up receiver for media player onPrepared broadcast
LocalBroadcastManager.getInstance(this).registerReceiver(onPrepareReceiver,
new IntentFilter("MEDIA_PLAYER_PREPARED"));
if(paused){
setController();
paused=false;
}
}
@Override
protected void onStop() {
super.onStop();
}
private void setController(){
//set the controller up
if (controller == null) controller = new MusicController(this);
controller.invalidate();
controller.setPrevNextListeners(new View.OnClickListener() {
@Override
public void onClick(View v) {
playNext();
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
playPrev();
}
});
controller.setMediaPlayer(this);
controller.setAnchorView(findViewById(R.id.song_list));
}
@Override
public void onBackPressed() {
moveTaskToBack(true);
Intent intent = new Intent (getApplicationContext(), FitnessActivity.class);
startActivity(intent);
}
// Broadcast receiver to determine when music player has been prepared
private BroadcastReceiver onPrepareReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context c, Intent i) {
// When music player has been prepared, show controller
controller.show(0);
}
};
private BroadcastReceiver onNextClickedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
musicSrv.playNext();
}
};
//connect to the service
public ServiceConnection musicConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder)service;
//get service
musicSrv = binder.getService();
//pass list
musicSrv.setList(songList);
musicBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
@Override
protected void onStart() {
super.onStart();
if(playIntent==null){
playIntent = new Intent(this, MusicService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
setController();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_shuffle:
musicSrv.setShuffle();
break;
case R.id.action_end:
stopService(playIntent);
musicSrv=null;
System.exit(0);
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
stopService(playIntent);
musicSrv=null;
super.onDestroy();
}
public void getSongList() {
//retrieve song info
ContentResolver musicResolver = getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
if(musicCursor!=null && musicCursor.moveToFirst()){
//get columns
int titleColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.ARTIST);
int durationColumn = musicCursor.getColumnIndex
(MediaStore.Audio.Media.DURATION);
//add songs to list
do {
long thisId = musicCursor.getLong(idColumn);
String thisTitle = musicCursor.getString(titleColumn);
String thisArtist = musicCursor.getString(artistColumn);
long thisDuration = musicCursor.getLong(durationColumn);
if (thisDuration>10000){
songList.add(new Song(thisId, thisTitle, thisArtist, thisDuration));}
}
while (musicCursor.moveToNext());
}
}
@Override
public void start() {
musicSrv.go();
}
@Override
public void pause() {
playbackPaused=true;
musicSrv.pausePlayer();
}
@Override
public int getDuration() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getDur();
else return 0;
}
@Override
public int getCurrentPosition() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getPosn();
else return 0;
}
@Override
public void seekTo(int pos) {
musicSrv.seek(pos);
}
@Override
public boolean isPlaying() {
if(musicSrv!=null && musicBound)
return musicSrv.isPng();
return false;
}
@Override
public int getBufferPercentage() {
return 0;
}
@Override
public boolean canPause() {
return true;
}
@Override
public boolean canSeekBackward() {
return true;
}
@Override
public boolean canSeekForward() {
return true;
}
@Override
public int getAudioSessionId() {
return 0;
}
public void onNextNotification(){
}
}
清单:
<activity
android:name=".MusicPlayer"
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MusicService"
/>
<service android:name=".NotificationService" />
答案 0 :(得分:0)
通知服务收到您的通知操作,而不是音乐服务。编辑通知意图以定位音乐服务
Intent playIntent = new Intent(this, MusicService.class);
//... edit all of them
将onStartCommand()
方法移至音乐服务并分配操作
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constant.ACTION.PLAY_ACTION)) {
//call play method
}
//...etc
除了 STARTFOREGROUND_ACTION
和STOPFOREGROUND_ACTION
,请将其保留在Notification Service的onStartCommand()中。同时在两个服务中插入对Intent的空检查。