0

我有一个应用程序,它是一种闹钟。我有一个奇怪的问题。

原理很简单:alarmmanager 发送一个广播启动一个服务和一个活动。

该服务将手机振动 10 秒,然后终止活动及其本身。该活动显示一个关闭按钮。如果您单击它,它将停止服务及其本身。

如果在手机开机时接收到广播,那么它工作正常(活动开始并且手机振动)。

如果在手机处于睡眠模式时收到广播,则活动开始并立即停止(除非您在某处放置 Thread.sleep,否则您实际上无法在屏幕上看到它)。该服务工作正常。

我不明白为什么活动在创建后就停止了?

在 logcat 中,我有最后两行在它工作时我没有:

06-23 18:07:58.349: I/ActivityManager(305): Displayed com.example.testproject/.AlarmeScreenOffActivity: +100ms
06-23 18:07:58.349: I/power(305): *** set_screen_state 1
06-23 18:07:58.359: D/kernel(145): [557082.194793] request_suspend_state: wakeup (3->0) at 557080649502843 (2014-06-23 16:07:58.358764661 UTC)

谢谢。


这是接收器中的代码:

        WakeLockManager.acquireWakeLock(context);

        Intent closeDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        context.sendBroadcast(closeDialogs);

        Intent alarmeActivity = new Intent(context,
                AlarmeScreenOffActivity.class);
        alarmeActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(alarmeActivity);

        Intent playAlarm = new Intent(context, AlarmeSonVibration.class);
        context.startService(playAlarm);

活动 :

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (MyBroadcastReceiver.ALARM_TIMEOUT.equals(intent.getAction())) {
            dismiss();
        }
    }
};

@Override
protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);     
    updateLayout();     
    registerReceiver(mReceiver, new IntentFilter(MyBroadcastReceiver.ALARM_TIMEOUT));
}

private void updateLayout() {   

    requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); 
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | 
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | 
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 
            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
            WindowManager.LayoutParams.FLAG_FULLSCREEN | 
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | 
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 
            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

    setContentView(R.layout.alarm_alert);

    Button dismissbouton = (Button) findViewById(R.id.dismiss);
    dismissbouton.setText("Dismiss");

    dismissbouton.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {                   
            dismiss();
        }
    });

}

private void dismiss() {
    Intent playAlarm = new Intent(this, AlarmeSonVibration.class);
    stopService(playAlarm);
    finish();
}

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mReceiver);  
}

和服务:

private static int ALARM_TIMEOUT_SECONDS = 10;
private static final long[] sVibratePattern = new long[] { 500, 300 };
private boolean mPlaying = false;
private Vibrator mVibrator;

private static final int TIMEOUT = 1001;    
private Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case TIMEOUT:
            sendTimeOutBroadcast();
            stopSelf();
            break;
        }
    }
};

@Override
public void onCreate() {
    WakeLockManager.acquireWakeLock(this);      
    mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);      
}

@Override
public void onDestroy() {
    super.onDestroy();
    stop();
    WakeLockManager.releaseWakeLock();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent == null) {
        stopSelf();
        return START_NOT_STICKY;
    }
    play();
    return START_STICKY;
}

private void sendTimeOutBroadcast() {
    Intent alarmtimeout = new Intent(MyBroadcastReceiver.ALARM_TIMEOUT);
    sendBroadcast(alarmtimeout);
}

private void play() {
    stop();
    mVibrator.vibrate(sVibratePattern, 0);
    enableTimeOut();
    mPlaying = true;
}

public void stop() {
    if (mPlaying) {
        mPlaying = false;
        mVibrator.cancel();
    }
    disableTimeOut();
}

private void enableTimeOut() {
    mHandler.sendMessageDelayed(mHandler.obtainMessage(TIMEOUT, true),
            1000 * ALARM_TIMEOUT_SECONDS);
}

private void disableTimeOut() {
    mHandler.removeMessages(TIMEOUT);
}

编辑 :

经过其他一些测试后,似乎即使没有启动服务,该应用程序也不希望我的活动停留在 ui 上。

广播触发活动,设备唤醒并运行活动,但随后关闭(它立即从 onresume 变为 onpause)。

有或没有键盘保护,结果是一样的,我的活动开始和停止。

应该很简单吧?我只是尝试通过触发广播从睡眠模式运行活动。

4

1 回答 1

2

好的,即使我不完全理解发生了什么,我也解决了我的问题。

在从睡眠模式启动的活动中,onStop 方法是:

@Override
protected void onStop() {
    super.onStop();
    if (!isFinishing()) {
        // Don't hang around.
        finish();
    }
}

这与android闹钟源代码中的方法相同。如果我将其更改为:

@Override
protected void onStop() {
    super.onStop();
    if (!isFinishing()) {
        // Don't hang around.
        //finish();
    }
}

它正在工作......

发生的事情是我正在寻找为什么 onStop 被调用。看来android从睡眠模式运行此活动时,会创建它然后将其设置为onstop。然后,finish() 将销毁它。

我仍然不明白为什么 Android 想要活动继续 onStop(以及为什么它不是闹钟原始源代码中的错误),但现在它正在工作,我很高兴。

感谢那些试图帮助我的人。

于 2014-06-25T17:20:44.103 回答