服务上下文为空!我已经尝试 getContextAplication()

Service context is null ! I Already try getContextAplication()

我有两个 classes,一个是名为 OficioActivity 的 Activity,另一个是名为 Player 的服务,OficioActivity 启动服务播放器并然后它调用使用 MediaPlayer class 的方法 playPause()、adiantaAudio() 和 retrocedeAudio(),如果它在前台运行(当屏幕关闭时),问题就在于 Player 有一个 onCompletionListener()播放下一首歌曲,但如果我单击 OficioActivity 上的按钮转到下一首歌曲,它会崩溃并出现 nullpointException。

OficioActivity

public class OficioActivity extends ActionBarActivity implements View.OnClickListener {

private ImageButton btAdianta,btRetrocede,btPlayPause;
private TextView tvOficio;
private Player player;
private Notificacao notification;
private int NOTIFICACAO_ID =1;
private Intent intentService;


@Override
protected void onCreate(Bundle savedInstanceState) {
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_oficio);

    btAdianta = (ImageButton) findViewById(R.id.ibtn_adiantar);
    btRetrocede = (ImageButton) findViewById(R.id.ibtn_retroceder);
    btPlayPause = (ImageButton) findViewById(R.id.ibtn_play);
    tvOficio = (TextView) findViewById(R.id.tv_oficio);

    btAdianta.setOnClickListener(this);
    btPlayPause.setOnClickListener(this);
    btRetrocede.setOnClickListener(this);

    intentService = new Intent(OficioActivity.this,Player.class);
    startService(intentService);


}

@Override
protected void onResume() {
    if(player==null)
    player = new Player();
    notification = new Notificacao(OficioActivity.this);
    super.onResume();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_oficio, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

/**Serve para alterar um TextView em tempo de execução
 *
 * @param  tv TextView
 * @param texto String
 */
public void runOnThread(final TextView tv, final String texto){
    OficioActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            tv.setText(texto);
        }
    });
}

@Override
public void onClick(View v) {
    switch (v.getId()){

        case R.id.ibtn_adiantar:
            runOnThread(tvOficio,player.adianta());
        break;
        case R.id.ibtn_retroceder:
            runOnThread(tvOficio,player.retrocede());
        break;
        case R.id.ibtn_play:
            notification.geraNotificacao(NOTIFICACAO_ID,OficioActivity.this);
            runOnThread(tvOficio, player.playPause());
        break;

    }
}

@Override
protected void onDestroy() {
   // player.paraAudio();
    super.onDestroy();
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if(event.getKeyCode()==KeyEvent.KEYCODE_BACK){
        player.paraAudio();
        stopService(intentService);
        finish();
        notification.cancelaNotificacao(NOTIFICACAO_ID);
    }

    return super.onKeyDown(keyCode, event);
}

}

public class Player extends Service implements MediaPlayer.OnCompletionListener {

private final int SALVE_MESA = R.raw.salve_mesa;
private final int AGORA_LABIOS = R.raw.agora_labios_meus;
private final int HUMILDES_OFERECEMOS = R.raw.humildes_oferecemos;
private final int INTRO = R.raw.intro;
private final int ORACAO = R.raw.oracao;
private final int SALVE_RELOGIO = R.raw.salve_relogio;
private final int SALVE_VIRGEM_IMACULADA = R.raw.salve_virgem_imaculada;
private final int SALVE_VIRGEM_TRINDADE = R.raw.salve_virgem_trindade;
private final int SEDE_EM_MEU_FAVOR = R.raw.sede_em_meu_favor;
private final int SALVE_TRONO = R.raw.salve_trono;
private final int SALVE_CIDADE = R.raw.salve_cidade;
private final int ROGAI_A_DEUS = R.raw.rogai_a_deus_vos;

private final int INICIAR_PAUSAR = 0;
private final int ADIANTAR = 1;
private final int RETROCEDER = 2;


private static MediaPlayer media;
private int audioAtual = 1;
private HashMap<Integer, Integer> hashMapAudio, hashMapRetrocede;
private String texto;

private HashMap<Integer, Integer> musicas = new HashMap<>();

public Player() {
    hashMapAudio = new HashMap<>();
    hashMapAudio.put(1, INTRO);
    hashMapAudio.put(2, AGORA_LABIOS);
    hashMapAudio.put(3, ORACAO);
    hashMapAudio.put(4, SEDE_EM_MEU_FAVOR);
    hashMapAudio.put(5, SALVE_MESA);
    hashMapAudio.put(6, ORACAO);
    hashMapAudio.put(7, SEDE_EM_MEU_FAVOR);
    hashMapAudio.put(8, SALVE_TRONO);
    hashMapAudio.put(9, ORACAO);
    hashMapAudio.put(10, SEDE_EM_MEU_FAVOR);
    hashMapAudio.put(11, SALVE_VIRGEM_TRINDADE);
    hashMapAudio.put(12, ORACAO);
    hashMapAudio.put(13, SEDE_EM_MEU_FAVOR);
    hashMapAudio.put(14, SALVE_CIDADE);
    hashMapAudio.put(15, ORACAO);
    hashMapAudio.put(16, SEDE_EM_MEU_FAVOR);
    hashMapAudio.put(17, SALVE_RELOGIO);
    hashMapAudio.put(18, ORACAO);
    hashMapAudio.put(19, ROGAI_A_DEUS);
    hashMapAudio.put(20, SALVE_VIRGEM_IMACULADA);
    hashMapAudio.put(21, ORACAO);
    hashMapAudio.put(22, HUMILDES_OFERECEMOS);

}


/**
 * Retorna o texto equivalente ao audio tocado
 *
 * @return String
 */
private String recuperaTexto() {


    switch (audioAtual) {
        case 1:
            texto = OficioEnum.INTRO.texto;
            break;
        case 2:
            texto = OficioEnum.AGORA_LABIOS_MEUS.texto;
            break;
        case 3:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 4:
            texto = OficioEnum.SEDE_EM_MEU_FAVOR.texto;
            break;
        case 5:
            texto = OficioEnum.MESA.texto;
            break;
        case 6:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 7:
            texto = OficioEnum.SEDE_EM_MEU_FAVOR.texto;
            break;
        case 8:
            texto = OficioEnum.TRONO.texto;
            break;
        case 9:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 10:
            texto = OficioEnum.SEDE_EM_MEU_FAVOR.texto;
            break;
        case 11:
            texto = OficioEnum.VIRGEM_DA_TRINDADE.texto;
            break;
        case 12:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 13:
            texto = OficioEnum.SEDE_EM_MEU_FAVOR.texto;
            break;
        case 14:
            texto = OficioEnum.CIDADE.texto;
            break;
        case 15:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 16:
            texto = OficioEnum.SEDE_EM_MEU_FAVOR.texto;
            break;
        case 17:
            texto = OficioEnum.RELOGIO.texto;
            break;
        case 18:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 19:
            texto = OficioEnum.ROGAI_A_DEUS.texto;
            break;
        case 20:
            texto = OficioEnum.VIRGEM_IMACULADA.texto;
            break;
        case 21:
            texto = OficioEnum.ORACAO.texto;
            break;
        case 22:
            texto = OficioEnum.HUMILDES_OFERECEMOS.texto;
            break;

    }


    return texto;
}


/**
 * Retorna o audio dependendo da acao se a acao for adiantar retorna proximo audio representado por um Integer
 *
 * @param acao
 * @return int
 */
private int verificaMusica(int acao) {

    /*
    * Sequencia do oficio
    * 1 - intro
    * 2 - agora labios meus
    * 3 - oracao
    * 4 - sede em meu favor
    * 5 - salve mesa
    * 6 - oracao
    * 7 - sede em meu favor
    * 8 - salve trono
    * 9 - oracao
    * 10 -sede em meu favor
    * 11 -salve virgem da trindade
    * 12 -oracao
    * 13 -sede em meu favor
    * 14 -salve cidade
    * 15 -oracao
    * 16 -sede em meu favor
    * 17 -salve relogio
    * 18 -oracao
    * 19 -rogai a Deus vos
    * 20 -salve virgem imaculada
    * 21 -oracao
    * 22 -humildes oferecemos
    * */

    if (acao == ADIANTAR) {
        incrementaAudioAtual();
        return hashMapAudio.get(audioAtual);
    } else {
        decrementaAudioAtual();
        return hashMapAudio.get(audioAtual);
    }

}


/**
 * Incrementa o audio com + 1 até 22
 */
private void incrementaAudioAtual() {
    if (audioAtual < 22) {
        audioAtual++;
    }

}

/**
 * DEcrementa o audio com -1 até 1
 */
private void decrementaAudioAtual() {
    if (audioAtual > 1) {
        audioAtual--;
    }

}

public MediaPlayer getMedia() {
    return media;
}

/**
 * Retorna se o audio está tocando
 *
 * @return true ou false
 */
public boolean isPlaying() {
    return media.isPlaying();
}

@Override
public IBinder onBind(Intent intent) {

    return null;
}

@Override
public void onCreate() {

    media = MediaPlayer.create(getApplicationContext(), INTRO);
    media.setOnCompletionListener(this);
    super.onCreate();
}


/**
 * Adianta o audio
 */
public String adianta() {

    if (media != null) {
        media.stop();
        media.release();
        media = MediaPlayer.create(getApplicationContext(), verificaMusica(ADIANTAR));
        media.setOnCompletionListener(this);
        media.start();
    }
    return recuperaTexto();
}

/**
 * Retrocede o audio
 *
 * @return String texto
 */
public String retrocede() {

    if (media != null) {
        media.stop();
        media.release();
        media = MediaPlayer.create(getApplicationContext(), verificaMusica(RETROCEDER));
        media.start();

    }
    return recuperaTexto();
}

/**
 * Para o audio e define a media como null para liberar memoria
 */
public void paraAudio() {
    if (media != null) {
        if (media.isPlaying()) {
            media.stop();
            media.release();
            media = null;

        } else {
            media.release();
            media = null;

        }
    }
}

/**
 * Se o audio não estiver tocando toca, caso contrario pausa a musica
 *
 * @return
 */

public String playPause() {
    if (media == null) {
        media = MediaPlayer.create(getApplicationContext(), verificaMusica(INTRO));
        media.start();
    } else {
        if (media.isPlaying()) {
            media.pause();
        } else {
            media.start();
        }
    }
    return recuperaTexto();
}

@Override
public void onCompletion(MediaPlayer mp) {
    adianta();
}

}

03-17 10:50:12.840: E/AndroidRuntime(1898): FATAL EXCEPTION: main
03-17 10:50:12.840: E/AndroidRuntime(1898): Process: com.renanwillamy.devocionario, PID: 1898
03-17 10:50:12.840: E/AndroidRuntime(1898): java.lang.NullPointerException
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at entidades.Player.adianta(Player.java:260)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at com.renanwillamy.devocionario.OficioActivity.onClick(OficioActivity.java:103)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.view.View.performClick(View.java:4438)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.view.View$PerformClick.run(View.java:18422)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.os.Handler.handleCallback(Handler.java:733)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.os.Handler.dispatchMessage(Handler.java:95)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.os.Looper.loop(Looper.java:136)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at android.app.ActivityThread.main(ActivityThread.java:5017)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at java.lang.reflect.Method.invokeNative(Native Method)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at java.lang.reflect.Method.invoke(Method.java:515)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-17 10:50:12.840: E/AndroidRuntime(1898):     at dalvik.system.NativeStart.main(Native Method)

谢谢大家,我像@Squonk 说的那样使用了 ServiceConnection 和 Binder! – Renan Willamy