0

I have an app wich is a kind of alarmclock. I have a weird issue.

The principle is simple : The alarmmanager send a broadcast that will start a service and an activity.

The service vibrates the phone for 10s and then kill the activity and itself. The activity shows a dismiss button. If you click on it, it stops the service and itself.

If the broadcast is received when the phone is on, then it works fine (activity starts and the phone vibrates).

If the broadcast is received when the phone is in sleeping mode, then the activity starts and immediatly stops (you actually can't see it on screen unless you put a Thread.sleep somewhere). The service works fine.

I don't understand why the activity stops just after being created ?

In the logcat, i have these two last lines i didn't have when it's working :

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)

Thanks.


Here's the code in the receiver :

        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);

The activity :

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);  
}

And the service :

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);
}

EDIT :

After a few other tests, it appears that even without starting the service, the app doesn't want my activity to stay on ui.

The broadcast triggers the activity and the device wakes up and run the activity, but then it shuts down (it goes from onresume to onpause immediatly).

With or whithout keyguard, the result is the same, my activity starts and stops.

It should be simple ? I just try to run an activity from sleep mode by trigering a broadcast.

user1391967
  • 497
  • 1
  • 6
  • 13
  • I think your approach is a little flawed to start with. If you really need to have the `Service` run together with the `Activity` and if you want the `Service` to be able to stop the `Activity` then you should consider [**binding the `Service`**](http://developer.android.com/guide/components/bound-services.html). – Xaver Kapeller Jun 23 '14 at 16:29
  • Thanks for pointing to me ... an other issue ;) My code is inspired by the alarm clock from the android source code, and it's working this way. – user1391967 Jun 23 '14 at 16:51
  • are you sure your receiver is not getting any null intents? Or multiple intents that could cause this behavior? – Jim Jun 23 '14 at 16:54

1 Answers1

2

Ok, i solve my issue even if i don't fully understand what's happening.

In the activity started from sleep mode, the onStop method is :

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

This is the same method as in the android alarmclock source code. If i change it to :

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

It's working....

What happens is that i was looking why the onStop was beeing called. It appears that android when running this activity from sleep mode, creates it then set it onstop. Then, the finish() will destroy it.

I still don't undersant why Android wants the activity to go onStop (and why it's not a bug in the orignal source code of alarmclock), but now it's working and i'm happy.

Thanks to those who try to help me.

user1391967
  • 497
  • 1
  • 6
  • 13