Create temporary lock on the app

Asked

Viewed 617 times

7

In the app I’m developing there is a usage policy, and if this policy is scammed I want to suspend the use of the app for 30 mins, how can I do this?

  • All Activity passes the onCreate method. One solution I can imagine is just to do a simple validation by checking if the user did something wrong. If you have done so, you can call an Intent that sends to another Action that informs you that it has been blocked and how much time is left

3 answers

10

You need to implement something that allows the application to know if it is blocked or not.

This information can, as the regmoraes said, be stored in Shared Preferences.

The question now is how to know that 30 minutes have passed in order to unlock it.

One solution would be to keep, not a flag(true/false), but the value in milliseconds of the date(timestamp) where the application has been blocked.
To verify that 30 minutes have passed, just subtract between the current date and the saved date.

Method to block:

private void block(){
    SharedPreferences sharedPref = getPreferences("Pref", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putLong("BlockTime", new Date().getTime());
    editor.commit();
}

Method to check if it is locked:

private boolean isBlocked(){
    SharedPreferences sharedPref = getPreferences("Pref", Context.MODE_PRIVATE);
    long blockTime = sharedPref.getLong("BlockTime", 0);
    return new Date().getTime() - blockTime < 1800000; //30*60*1000
}

EDIT:

You can prevent the system from being duped by the user if the user changes the date/time of the system as follows:

In addition to guarding the timestamp also keep a flag indicating whether it is blocked or not:

private void block(){
    SharedPreferences sharedPref = getPreferences("Pref", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putLong("BlockTime", new Date().getTime());
    editor.putBoolean("IsBlocked", true);
    editor.commit();
}

Declare a Broadcastreceiver that responds to the action android.intent.action.TIME_SET. It will be called when there is a system date/time change:

Timechangereceiver.java

public class TimeChangeReceiver extends BroadcastReceiver{

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

        //Houve uma alteração na data/hora do sistema
        SharedPreferences sharedPref = getPreferences("Pref", Context.MODE_PRIVATE);
        boolean isBlocked = sharedPref.getBoolean("IsBlocked", false);
        if(isBlocked){
            //Grava novo timestamp
            SharedPreferences.Editor editor = sharedPref.edit();
            editor.putLong("BlockTime", new Date().getTime());
            editor.commit();
        }
    }    
}

Register the receiver in the Androidmanifest.xml:

<receiver android:name=".TimeChangeReceiver">
    <intent-filter>
        <action android:name="android.intent.action.TIME_SET"/>
    </intent-filter>
</receiver>

Change the method isBlocked() to deal with the flag:

private boolean isBlocked(){
    SharedPreferences sharedPref = getPreferences("Pref", Context.MODE_PRIVATE);
    long blockTime = sharedPref.getLong("BlockTime", 0);
    boolean isBlocked = new Date().getTime() - blockTime < 1800000; //30*60*1000
    if(!isBlocked){
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean("IsBlocked", false);
        editor.commit();
    }
    return isBlocked
}

Call the method isBlocked() in the onResesume()

My only question is whether minor time changes due to automatic synchronizations (if connected) will or will not launch the Receiver

  • 2

    Even so, malicious user will change the device date to be unlocked! If the application has internet connection would be interesting to Data if obtained from the internet, or even if the lock is done on the server! Malicious user ("the clever ones") is not lacking!

  • Well-placed Fernando

  • @Fernado You are right, there will always be a way to overcome whatever the protection, some more difficult than others.

  • I think it valid to do the test in case of automatic schedules change, maybe it generates some problem, but in general, it is a great solution.

  • @Paulogustavo In case it is unlocked no problem, in case it is blocked will renew the lock for another 30 minutes.

  • If I want to create a quota, like per day you can circumvent the rule up to twice, it would be another data saved in Shared prefferences?

  • Yes, this should be done in the method block()

Show 2 more comments

5

The solution that @Paulogustavo gave us in the comments is a good one, but I would make a small change:

You’d better validate the method onResume() of Activity, since that method is always called when an Activity opens, even if it has only been pause. Already the onCreate() is only called once ( when Activity is created ), therefore a "rogue" user could "circumvent" the check as follows:

  1. User hurts the usage policy
  2. The app hangs
  3. The user leaves the app putting it in the background ( by pressing the home key, for example)
  4. User opens list of recent apps and chooses your app
  5. User gets back in your app normally!

This is because on this round trip, your Activity was not destroyed, it was just stopped, it means that when you open it again, the method onCreate() will not be called

Another tip I give is:

So, when the user hurts the usage policy, you do this on your Activity:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(getString(R.string.bloqueado), true);
editor.commit(); 

If you want to "unlock" the app, just write the same code above by swapping true for false.

To treat the condition of "blocked app" or not, put the following code in the method onResume() of its Activity:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
boolean bloqueado = sharedPref.getBoolean(getString(R.string.bloqueado), /* valor default*/ );

if(bloqueado){

    //Notifica o usuário ou fecha a Activity

}else{

   //Continue a execução da Activity normalmente
}
  • Very good. I add here a link that shows the life cycle of the activity for a better understanding: http://www.devmedia.com.br/imagens/articles/263421/Activity.png

  • 1

    Just need to explain how to make the app stay unlocked after they have passed 30 minutes.

  • @ramaral edited the answer adding an explanation for this

  • The problem isn’t writing true in Shared Preferences but do so after 30 minutes. I am sorry for my comments but I think the answer will only completely answer the question if this is explained.

  • Thanks my old man, basically I had thought about it even using sharedpreferences, but my biggest problem is with time, how to program to unlock the app automatically?

  • Exact @ramaral the biggest problem on my part, is the 30 min scheduling part.

  • You can create a service, which will run in the background for a while and without depending on the application being open. Having said that, you can create a service to make such unlocking and/or when the person opens the application you see how much time is left. http://developer.android.com/intl/pt-br/guide/components/services.html

Show 2 more comments

1

How to do the lock has already been answered, the doubt is now on how to unlock. I think do a service background would be the good solution.

As @ramaral suggested and @Fernando commented, blocking through time would be something tricky and requiring the APP to have an internet connection is also very risky seeing that it can never have after the lock and if it does, it will never have an unlock.

I believe that by creating a service we can get the result of blocking without the user being able to circumvent.

Create a service as something like this:

    public class MyService extends Service {

    private Timer timer;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        timer = new Timer();
        timer.schedule(timerTask, 2000, 5000); //2000 representa o tempo da primeira chamada e 5000 das demais (milissegundos)
        return super.onStartCommand(intent, flags, startId);
    }

private TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {

            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    //do something

                    // stopSelf()
                }
            });

        }
    };


    }

The problem with this approach is that if the device is switched off, the service will be lost. If this happens, you will probably have to implement so that the service starts again at the device boot.

  • 1

    Initially I had thought of a solution that used a Timer to launch a Broadcastreceiver that would unlock the app. The problem was the same as its solution: if the appliance was turned off, during this period, the application would always be blocked. This could be solved by a new Broadcastreceiver to be launched on boot. I thought the solution would be complicated. As both can be "tricked".

Browser other questions tagged

You are not signed in. Login or sign up in order to post.