我这里有一个service是这样,开启后,每一分钟做一次弹窗提醒(闹钟app的铺垫,每天一次弹窗提醒)。
然而,我的这个dialog有一个PositiveButton,但是这要点击这个 button 就会报错.
错误如下:
Handler (com.android.internal.app.AlertController$ButtonHandler) {385957f} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (com.android.internal.app.AlertController$ButtonHandler) {385957f} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:555)
at android.os.Handler.enqueueMessage(Handler.java:707)
at android.os.Handler.sendMessageAtTime(Handler.java:609)
at android.os.Handler.sendMessageDelayed(Handler.java:579)
at android.os.Handler.sendMessage(Handler.java:516)
at android.os.Message.sendToTarget(Message.java:429)
at com.android.internal.app.AlertController$1.onClick(AlertController.java:146)
at android.view.View.performClick(View.java:5265)
at android.view.View$PerformClick.run(View.java:21534)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
我的代码是这样的:
public class ClockService extends IntentService {
private static final String TAG = "ClockService";
private Vibrator vibrator;
private MediaPlayer mMediaPlayer = null;
private Context mContext ;
AlertDialog dialog;;
private static final int TIME = 1000*20;
public static Intent newIntent(Context context){
return new Intent(context,ClockService.class);
}
public ClockService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
LogUtil.d(TAG,"service intent ");
System.out.println("我是闹钟,我要叫醒你...");
dismissHandler= new Handler(getMainLooper());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("闹钟");
builder.setMessage("测试");
builder.setPositiveButton("知道了", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//我这里啥都没有,但是只要点击 知道了 就会报错
}
});
dialog = builder.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mHandler =new Handler(Looper.getMainLooper());
new Thread(){
@Override
public void run() {
super.run();
mHandler.post(new Runnable() {
@Override
public void run() {
dialog.show();
}
});
}
}.start();
// dialog.show();
}
Handler mHandler,dismissHandler ;
public static void setServiceAlarm(Context context,boolean isON){
Intent i = ClockService.newIntent(context);
PendingIntent pi = PendingIntent.getService(context,0,i,0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (isON){
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),TIME,pi);
}else{
alarmManager.cancel(pi);
pi.cancel();
}
}
}
onHandleIntent()는 하위 스레드에서 실행됩니다. 메서드가 실행된 후 IntentService는 즉시 stopSelf()를 호출하여 자체를 중지하고 하위 스레드의 Looper가 삭제됩니다.
으아악onHandleIntent()에서 생성된 Dialog의 내부 ButtonHandler는 하위 스레드의 메시지 대기열에 바인딩됩니다. 버튼 클릭 이벤트가 발생하면 하위 스레드가 삭제되고 메시지 루프가 종료되며 ButtonHandler도 변경됩니다. 유효하지 않은. 따라서 죽은 스레드의 핸들러에 메시지를 보내면 Logcat에서 예외가 발생합니다. 이 예외는 android.os.MessageQueue.enqueueMessage() 메서드에서 발생합니다.
샘플 코드는 다음과 같습니다
Dialog 생성은 메인 스레드에서 이루어져야 합니다. IntentService 대신 일반 서비스를 시작하고 onStartCommand() 메서드에서 Dialog를 생성하는 것이 좋습니다.