【问题标题】:Activity start from sleep mode immediately close?Activity 从睡眠模式启动立即关闭?
【发布时间】:2014-06-23 16:10:57
【问题描述】:

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

原理很简单: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)。

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

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

【问题讨论】:

  • 我认为你的方法一开始有点缺陷。如果您确实需要让Service 与Activity 一起运行,并且如果您希望Service 能够停止Activity,那么您应该考虑binding the Service。
  • 感谢您指点我...另一个问题 ;) 我的代码灵感来自 android 源代码中的闹钟,并且它是这样工作的。
  • 您确定您的接收者没有收到任何空意图吗?还是可能导致此行为的多个意图?

标签: android wakelock keyguard


【解决方案1】:

好的,即使我不完全了解正在发生的事情,我也会解决我的问题。

在从睡眠模式启动的activity中,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(以及为什么它不是闹钟原始源代码中的错误),但现在它可以工作了,我很高兴。

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

【讨论】:

    猜你喜欢
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 2014-07-17
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    相关资源
    最近更新 更多