0

Im creating a receiver that captures power button preses, and for now its working but its not behaving like I want to. In it its defined to do certain action if the user presses 5 times in less than 5 seconds, but for now its not that responsive and sometimes it takes more than 5 presses so the receiver do the specified action.

Can someone tell me how can I improve my code Thanks

Here is my Receiver.class:

public class Receiver extends BroadcastReceiver {
    public boolean successfull = false;
    public boolean test = false;
    int presses;
    long time;
    SharedPreferences prefs;
    private Context context;

    @Override
    public void onReceive(Context context, Intent intent) {

        AudioManager manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (manager.getMode() != AudioManager.MODE_IN_CALL) {
            this.context = context;
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF) || intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                calculationLogic();
            }
        }
    }

    public void calculationLogic() {
        prefs = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
        presses = prefs.getInt("repeats", 0);
        Log.d("--", "Power pressed, #presses: " + presses);

        Log.d("--", "time " + System.currentTimeMillis());
//            screenOff = true;
        time = System.currentTimeMillis();
        //saving initial power btn press
        if (prefs.getLong("time", 0) == 0) {
            Log.d("receiver", "40");
            prefs.edit().putLong("time", time).apply();
            presses += 1;
        } else {
            Log.d("receiver", "44");
            //calculate the difference between the first power press and current power press
            Log.d("--", "time diff = " + time + " - " + prefs.getLong("time", 0) + " = " + (time - prefs.getLong("time", 0)));
            if (time - prefs.getLong("time", 0) > 5000) {
                reset();
                if (test) {
                    vibrate();
                    ((IntroActivity) context).onBackPressed();
                    ((IntroActivity) context).showTestSuccess(successfull);
                    context.unregisterReceiver(this);
                }
                Log.d("receiver", "fail");
            } else {
                if (presses == 5) {
                    Log.d("receiver", "success");
                    reset();
                    successfull = true;
                    Log.d("--", "staring activity");
                    vibrate();
                    //TODO

                    if (!test) {
                        doAction(context);
                    } else {
                        ((IntroActivity) context).onBackPressed();
                        ((IntroActivity) context).showTestSuccess(successfull);
                        context.unregisterReceiver(this);
                    }
                    time = 0;
                } else {
                    presses += 1;
                    Log.d("receiver", "presses so far " + presses);
                }
            }
        }
        prefs.edit().putInt("repeats", presses).apply();

    }

    private void reset() {
        presses = 0;
        prefs.edit().remove("time").apply();
    }

    private void vibrate() {
        Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        v.vibrate(200);
    }

    private void doAction(Context context) {
        Log.d("receiver", "STARTING main");
        Intent i = new Intent();
        i.setClass(context, SplashActivity.class);
//        i.setClassName("com.emergencyapp", ".SplashActivity");
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    }


}
Darko Petkovski
  • 3,892
  • 13
  • 53
  • 117

1 Answers1

0

Triggers from the power button to toggle the screen state are queued upon receipt and handled by PowerManagerService. In this way, the switch events are effectively debounced such that there will not necessarily be a 1:1 mapping between button presses and system broadcasts to toggle the screen state (or even actual screen on/off events).

Moreover, the delays between this internal queueing and actual broadcast delivery (which is variable) makes it difficult to accurately time the button presses from the events you are receiving.

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • So is there a way to detect the button presses via the PowerManagerService, or can you suggest any method that can be reliable? – Darko Petkovski Mar 17 '15 at 19:06
  • Not really. Those events are intentionally not delivered to applications. For example, you can only receive a long-press key event on power, not a tap, so that applications cannot attempt interfere with the screen toggling behavior. Volume keys are similar, there are only special conditions under which they are delivered to a foreground application. – devunwired Mar 17 '15 at 19:54
  • The broadcasts you are tracking are the best indication the framework gives you of these events, so perhaps the count or timing logic needs some relaxing. As a user, I wouldn't be terribly happy with someone asking me to mash by power button 5 times fast... – devunwired Mar 17 '15 at 19:55