我这里有一个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也就失效了。因此,向死亡线程的Handler发送消息,就会抛出Logcat中的异常。这个异常是在android.os.MessageQueue.enqueueMessage()方法中抛出的,
样例代码如下
if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false;}
Dialog的创建需要在主线程操作。建议你启动一个普通的Service,而不是IntentService,在onStartCommand()方法中创建Dialog即可。