如何在android中更新前台服务的通知?

时间:2015-03-16 13:50:12

标签: android android-service android-mediaplayer android-notifications

我制作了一个音乐播放器。音乐在前台服务中播放。如何在音乐更改或开始新音乐时更新通知?

这是我的服务类:

public class EngineBackground extends Service implements MediaPlayer.OnCompletionListener{

    private static MainActivity m = new MainActivity();
    private static Uri uri;
    public int songId;
    public static SharedPreferences sp;
    private static SharedPreferences.Editor editor;
    TaskStackBuilder stackBuilder;
    PendingIntent pendingIntent;

    static MediaPlayer mp = null;
    public static Notification notification;
    NotificationManager notificationManager;

    @Override
    public void onCreate() {

        super.onCreate();

        stackBuilder = TaskStackBuilder.create(this);
        sp = getSharedPreferences("setPrefernces", Context.MODE_PRIVATE);
        editor = sp.edit();

        notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        if(mp == null){
            Uri uri = Uri.parse("" + m.songsPath.get(0));
            mp = MediaPlayer.create(this, uri);
        }
        startInForground();
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    void startInForground(){
        RemoteViews remoteViews = new RemoteViews(getPackageName(),
                R.layout.notification_layout_big);

        Intent myIntent = new Intent(this, Player.class);
        myIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        pendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);


        Log.e("Api version:", "" + Build.VERSION.SDK_INT);

        if (Build.VERSION.SDK_INT >= 16){
            notification = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .setPriority(128)
                    .build();
            notification.bigContentView = remoteViews;
        } else{

            notification = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                    .setPriority(128)
                    .setContentTitle(getTitle())
                    .setContentText(getArtist())
                    .setTicker(getTitle())
                    .build();
        }
        startForeground(1, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (uri != null) {
            mp.stop();
            mp.release();
            mp = MediaPlayer.create(this, uri);
            mp.start();
        }
        mp.setOnCompletionListener(this);
        return START_STICKY;
    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }



    @Override
    public void onCompletion(MediaPlayer mp) {

        mp.pause();
        songId = sp.getInt("songId", 0) + 1;
        editor.putInt("songId", songId);
        editor.commit();
        startInForground();
        switch (sp.getInt("repeat", 0)) {
            case 0:
                break;
            case 1:
                break;
            case 2:
                break;
        }

        if (songId < m.songsPath.size()) {
            uri = Uri.parse("" + m.songsPath.get(songId));
            mp = MediaPlayer.create(this, uri);
            this.mp = mp;
            this.mp.setOnCompletionListener(this);
            this.mp.start();
        }
    }


    public void nextSong(){
        songId = sp.getInt("songId", 0) + 1;
        editor.putInt("songId", songId);
        editor.commit();

        if(mp.isPlaying()){
            mp.stop();
            mp.release();
            mp = null;
            this.uri = Uri.parse("" + m.songsPath.get(songId));
            mp = MediaPlayer.create(this, this.uri);
            mp.setOnCompletionListener(this);
            mp.start();
            Log.e("From next ", "" + songId);
        }else{
            mp.stop();
            mp.release();
            mp = null;
            this.uri = Uri.parse("" + m.songsPath.get(songId));
            mp = MediaPlayer.create(this, this.uri);
            mp.setOnCompletionListener(this);
            mp.start();
            Log.e("From next ", "" + songId);
        }
        startInForground();
    }
    public void previousSong(){
        songId = sp.getInt("songId", 0) - 1;
        editor.putInt("songId", songId);
        editor.commit();
        if(mp.isPlaying()){
            mp.stop();
            mp.release();
            this.uri = Uri.parse("" + m.songsPath.get(songId));
            mp = MediaPlayer.create(this, this.uri);
            mp.setOnCompletionListener(this);
            mp.start();
            Log.e("From pre ", "" + songId);
        }else{
            mp.stop();
            mp.release();
            this.uri = Uri.parse("" + m.songsPath.get(songId));
            mp = MediaPlayer.create(this, this.uri);
            mp.setOnCompletionListener(this);
            mp.start();
            Log.e("From pre ", "" + songId);
        }
        startInForground();
    }
    public void setUri(String uri, int songId){
        this.uri = Uri.parse(uri);
        //this.songId = songId;
        Log.e("From setUri ", "" + this.songId);
    }


    @Override
    public void onDestroy() {
        editor.putInt("songId", songId);
        editor.commit();
        super.onDestroy();
    }

    public CharSequence getTitle() {

        return "" + m.title.get(songId = sp.getInt("songId", 0));
        //startInForground();
    }

    public CharSequence getArtist() {
        return "" + m.artist.get(songId = sp.getInt("songId", 0));
    }
}

我在播放器活动中创建了此服务的实例。如果按下相应的按钮,则调用nextSong()previousSong()方法。 所以通常当一首歌完成并启动另一首歌时,它会调用startInForeground()方法并更新通知而没有任何问题。但是,如果我在nextSong()previousSong()中调用相同的方法,则会抛出错误。

这是按下按钮的方法:

private static EngineBackground f = new EngineBackground();

next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(f.mp.isPlaying()){
                    f.nextSong();
                }else{
                    f.nextSong();
                }
            }
        });

任何人都可以帮助我吗?这段代码有什么问题?为什么我无法从startInForeGround()调用nextSong()方法?

java.lang.NullPointerException
            at android.content.ContextWrapper.getPackageName(ContextWrapper.java:120)
            at prime.myapplication.EngineBackground.startInForground(EngineBackground.java:74)
            at prime.myapplication.EngineBackground.nextSong(EngineBackground.java:178)
            at prime.myapplication.Player$4.onClick(Player.java:178)
            at android.view.View.performClick(View.java:2485)
            at android.view.View$PerformClick.run(View.java:9080)
            at android.os.Handler.handleCallback(Handler.java:587)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:123)
            at android.app.ActivityThread.main(ActivityThread.java:3683)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:507)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
            at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

您的媒体播放器可能为空 试试这个

private static EngineBackground f = new EngineBackground();

next.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(f.mp == null)){
            // Media play is null and needs initialized  <---- see if this helps
            }else if(f.mp.isPlaying()){
                f.nextSong();
            }else{
                f.nextSong();
            }
        }
    });

答案 1 :(得分:0)

这背后的原因是您从活动中创建EngineBackground的实例,然后在其上调用next方法。该服务尚未启动,因此服务中的上下文仍为空,因此您的NullPointerException

您访问服务的方式完全错误,不推荐使用。看看这个 : http://developer.android.com/guide/components/services.html