服务上下文为空!我已经尝试 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
我有两个 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