Manual start timer

  • Tutorial
Hi, Habr. This article is addressed to those who understand the art of Android development, just like me.

Recently, I needed to make a timer that starts a certain task, after a certain period of time.

But the differences from the standard solution were as follows:
  • Firstly, if the task could not be completed, you must immediately repeat it. And so, to the end. After that, we return to normal mode.
  • Secondly, it may be necessary to start the task manually, without waiting for the next timer.
  • And thirdly, the timer should start if the device is rebooted or the Internet connection has been restored.

The problem was solved as follows.

Let's write a test application. Create a project with empty activity.

The form:

activity_main.xml


Create a new IntentService named UniversalService.

In MainActivity, make changes to onCreate:

onCreate
    CheckBox checkBox, checkBox1;
    SharedPreferences sPref;
    SharedPreferences.Editor editor;
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkBox = (CheckBox)findViewById(R.id.checkBox);
        sPref = getSharedPreferences("AlertTest",MODE_PRIVATE);
        editor = sPref.edit();
        editor.putBoolean("chbAutomatic", checkBox.isChecked());
        editor.putBoolean("success", checkBox.isChecked());
        editor.commit();
     checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                editor.putBoolean("chbAutomatic", checkBox.isChecked());
                editor.commit();
                setServiceAlarm(MainActivity.this);
            }
        });
        checkBox1 = (CheckBox)findViewById(R.id.checkBox2);
        checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                editor.putBoolean("success", checkBox1.isChecked());
                editor.commit();
                setServiceAlarm(MainActivity.this);
            }
        });
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("AlertTest", "Загрузка в ручном режиме");
                Intent intent = new Intent(MainActivity.this, UniversalService.class);
                startService(intent);
            }
        });
    }


And add a method:

public void setServiceAlarm(Context context){
        SharedPreferences settings = getSharedPreferences("AlertTest", MODE_PRIVATE);
        Boolean automaticSynchronize = settings.getBoolean("chbAutomatic", false);
        Intent intent = new Intent(context, UniversalService.class);
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Integer period = 5;
        if(automaticSynchronize){
            alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), period*1000, pendingIntent);
            Log.d("AlertTest", "Загрузка в автоматическом режиме, период: "+period*1000);
        } else {
            Log.d("AlertTest", "Загрузка отменена");
            alarmManager.cancel(pendingIntent);
            pendingIntent.cancel();
        }
    }

In this code (in the onCreate method), we save in the General Settings, with the name "AlertTest", the state of the checkboxes, and (in the setServiceAlarm method) we start the timer with a frequency of 5 seconds to execute the UniversalService service.

Also, we want to receive a response from the service about the success of the operation.

To do this, add a class to MainActivity:

 public class MyBroadRec extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Boolean result = intent.getBooleanExtra(UniversalService.EXTRA_KEY_OUT, false);
            Intent intentRec = new Intent(MainActivity.this, UniversalService.class);
            if(!result){
                Log.d("AlertTest", "Новая попытка");
                startService(intentRec);
            }
        }
    }

And at the end of onCreate add:

     MyBroadRec myBroadRec = new MyBroadRec();
        IntentFilter intentFilter = new IntentFilter(UniversalService.ACTION_MYINTENTSERVICE);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        registerReceiver(myBroadRec, intentFilter);
        setServiceAlarm(MainActivity.this);

And in UniversalService, change the code to the following:

Universal service
package ru.alerttest;
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class UniversalService extends IntentService {
    public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
    public static final String ACTION_MYINTENTSERVICE = "ru.timgor.alerttest.RESPONSE";
    public UniversalService() {
        super("UniversalService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("AlertTest", "Начало загрузки");
        if(!verify()){
            Intent responseIntent = new Intent();
            responseIntent.setAction(ACTION_MYINTENTSERVICE);
            responseIntent.addCategory(Intent.CATEGORY_DEFAULT);
            responseIntent.putExtra(EXTRA_KEY_OUT, false);
            Log.d("AlertTest", "Загрузка не произошла");
            sendBroadcast(responseIntent);
        } else{
            Log.d("AlertTest", "Загрузка прошла успешно");
        }
    }
    public boolean verify(){
        SharedPreferences settings = getSharedPreferences("AlertTest", MODE_PRIVATE);
        Boolean success = settings.getBoolean("success", false);
        return success;
    }
}


As you can see, the verify method emulates our task. If it is unsuccessful, an Intent is created that launches MyBroadRec, which starts our service again. We can configure through the "Very Important Option" checkbox. If we put the “Auto start” checkbox into an inactive state, the timer will stop working. As soon as the task is completed - go to normal mode.

But we still have the task of autostarting our application. To do this, create the UniversalReceiver class inheriting from BroadcastReceiver:

package ru.alerttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class UniversalReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("AlertTest", "Произошла смена статуса");
        Intent intentNew = new Intent(context, MainActivity.class);
        intentNew.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intentNew);
    }
}

And in the manifest, add the following lines:


Everything, the problem is solved. Then let me take my leave. I hope someone will find this useful. If someone has comments and tips, I will listen to them with great pleasure.

PS: Classes fully:

Mainactivity
package ru.alerttest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
public class MainActivity extends AppCompatActivity {
    CheckBox checkBox, checkBox1;
    SharedPreferences sPref;
    SharedPreferences.Editor editor;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkBox = (CheckBox)findViewById(R.id.checkBox);
        sPref = getSharedPreferences("AlertTest",MODE_PRIVATE);
        editor = sPref.edit();
        editor.putBoolean("chbAutomatic", checkBox.isChecked());
        editor.putBoolean("success", checkBox.isChecked());
        editor.commit();
     checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                editor.putBoolean("chbAutomatic", checkBox.isChecked());
                editor.commit();
                setServiceAlarm(MainActivity.this);
            }
        });
        checkBox1 = (CheckBox)findViewById(R.id.checkBox2);
        checkBox1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                editor.putBoolean("success", checkBox1.isChecked());
                editor.commit();
                setServiceAlarm(MainActivity.this);
            }
        });
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("AlertTest", "Загрузка в ручном режиме");
                Intent intent = new Intent(MainActivity.this, UniversalService.class);
                startService(intent);
            }
        });
        MyBroadRec myBroadRec = new MyBroadRec();
        IntentFilter intentFilter = new IntentFilter(UniversalService.ACTION_MYINTENTSERVICE);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        registerReceiver(myBroadRec, intentFilter);
        setServiceAlarm(MainActivity.this);
    }
    public class MyBroadRec extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Boolean result = intent.getBooleanExtra(UniversalService.EXTRA_KEY_OUT, false);
            Intent intentRec = new Intent(MainActivity.this, UniversalService.class);
            if(!result){
                Log.d("AlertTest", "Новая попытка");
                startService(intentRec);
            }
        }
    }
    public void setServiceAlarm(Context context){
        SharedPreferences settings = getSharedPreferences("AlertTest", MODE_PRIVATE);
        Boolean automaticSynchronize = settings.getBoolean("chbAutomatic", false);
        Intent intent = new Intent(context, UniversalService.class);
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Integer period = 5;
        if(automaticSynchronize){
            alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), period*1000, pendingIntent);
            Log.d("AlertTest", "Загрузка в автоматическом режиме, период: "+period*1000);
        } else {
            Log.d("AlertTest", "Загрузка отменена");
            alarmManager.cancel(pendingIntent);
            pendingIntent.cancel();
        }
    }
}


Universal service
package ru.alerttest;
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class UniversalService extends IntentService {
    public static final String EXTRA_KEY_OUT = "EXTRA_OUT";
    public static final String ACTION_MYINTENTSERVICE = "ru.timgor.alerttest.RESPONSE";
    public UniversalService() {
        super("UniversalService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("AlertTest", "Начало загрузки");
        if(!verify()){
            Intent responseIntent = new Intent();
            responseIntent.setAction(ACTION_MYINTENTSERVICE);
            responseIntent.addCategory(Intent.CATEGORY_DEFAULT);
            responseIntent.putExtra(EXTRA_KEY_OUT, false);
            Log.d("AlertTest", "Загрузка не произошла");
            sendBroadcast(responseIntent);
        } else{
            Log.d("AlertTest", "Загрузка прошла успешно");
        }
    }
    public boolean verify(){
        SharedPreferences settings = getSharedPreferences("AlertTest", MODE_PRIVATE);
        Boolean success = settings.getBoolean("success", false);
        return success;
    }
}


Universalreceiver
package ru.alerttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class UniversalReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("AlertTest", "Произошла смена статуса");
        Intent intentNew = new Intent(context, MainActivity.class);
        intentNew.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intentNew);
    }
}



PPS: Made changes to BroadcastReceiver to the errors Handy and BlackStream pointed out to me .
Now I'm dealing with SyncAdapter.

Also popular now: