Ванька Жуков, начинающий Android-пограммист, n-цати годов от роду, отданный в ученье неизвестно когда, не ложился спать. Дождавшись, когда коллеги и начальство уйдут к обедне, достал пузырек с тёмны… чаем, клавиатуру с заржавевшим выводом, запустил Android Studio и стал писать. Прежде чем вывести первую букву, он несколько раз пугливо оглянулся на окна Скайпа, и прерывисто вздохнул.

«Здравствуй, милый дедушка Хабр Хабрович! — писал он. — Пишу тебе письмо. Поздравляю вас со светлой Пятницей, и желаю тебе всего на выходных».
Ванька покосился на Скайп и живо вообразил себе Хабра Хабровича. Образ получился впечатляющий, но слишком объёмный. Ванька вздохнул и продолжил писать.
«А вчерась мне была выволочка. Надумал я написать свой таймер, с автоматическим запуском и ручным управлением. Написал, и любовался им долго. Но дядьки, сурово отчитали меня. Ругали, но за чуб не таскали. Дали книжек умных, и советов пользительных.
Дядька Dimezis, ругался сильно за неакуратные имена переменных, да за ключи переменных захардкоженные. Кодстайл ругал тож. Сказал переписать и не позориться.
Дядьки ivazhnov и Alex837 ругали за неаккуратное использование батареи. В морду, мордой ейной не сували, но хмурились сильно. Сказали переписать и не позориться.
Дядька MetAmfetamin, утешил, но поддержал других. Сказал переписать и не позориться».
Ванька почесал за ухом, и продолжил стучать по клавишам.
«Сказали, что нельзя для отлова изменения состояния сети использовать BroadcastReceiver, для которого в манифесте прописано:
Нельзя так писать, ибо батарейку выносит не по-детски:
Сказали смотреть в сторону JobScheduler или GcmNetworkManager или SyncAdapter.
Долго я думал и решил остановиться на GcmNetworkManager, потому как он для старых версий Android подходит и универсальней мне кажется».
Ванька покосился на гору документации, прочитанной вчера, и зевнул.
«Удалил я для начала все упоминания о UniversalReceiver. Ликвидировал, так сказать, как класс. И из манифеста потёр. Далее создал класс служебный, в который вынес все теги.
Далее в зависимости gradle добавил строчку:
В MainActivity добавил изменения. Объявил:
В onCreate:
И метод добавил:
Тут, дорогой Хабр Хабрович, коль в метод, правда-истина придёт, объявляю я об намерении создать задачу, которая будет периодически запускать службу AutomaticService (setService), носить тег PeriodicTask(setTag), вызываться раз в 30 секунд(setPeriod), работать после перезапуска(setPersisted), передавать случайное число, не работать пока сеть не подключится (setRequiredNetwork) и не требовать подключения к зарядке(setRequiresCharging). А коли в метод кто-то соврамши передаёт, то автоматическая работа прекращается.
Далее создал я службу AutomaticService, да не простую, а наследуемую от GcmTaskService:
Если служба хорошо отработала, то мы радуемся, а коли не судьба ей исполниться, то запускает BroadcastReceiver, который прописан в MainActivity. Дважды по десять пробует подключиться, с перерывом в 0.1 секунду, да плюнув в сердцах бросает это дело, до следующего тика.
В приложении тестовом я добавил галочку „Очень важная опция“. Коли она нажата, то благополучно задача отрабатывает.
И в onCreate:
Регистрирую этот ресивер».
Ванька оттер пот, покосился на заманчиво запотевший пузырёк с тёмным чаем, решительно тряхнул головой, и продолжил. «А ещё, хочу запускать я вручную задачу, не дожидаясь тика таймера. Для этого написал я службу ManualService наследующуюся от IntentService.
Запустил я приложение и радовался очень. Если в режим полёта перейти, да выключить интернеты — то автоматический запуск и не думает запускаться. А вот дорогой дедушка и все классы:
В общем, дорогой дедушка, получился таймер просто загляденье. Буду ждать, что дядьки скажут. А за меня не волнуйся. Хочу стать я разработчиком умным и стараться буду впредь. Засим желаю тебе здоровья крепкого и выходных увлекательных».
Ванька подвинул клавиатуру, набулькал из запотевшего пузырька чая и потянулся к кнопке «Опубликовать». Подумав немного, набрал в теге «На деревню дедушке». Почесал мышку за ухом, и добавил «Хабр Хабровичу».
Профессора из института рассказывали, что публикации разносятся по проводам оптоволоконным и медным, по всему интернету, управляемые веселыми админами. Ванька собрался с духом и нажал большую зелёную кнопку.
Убаюканный сладкими надеждами, он час спустя крепко спал… Ему снился Half-Life 3.
P.S.: Обновленный код, исправленный по замечаниям у��ажаемых комментаторов shakagamii и Parnt
«Здравствуй, милый дедушка Хабр Хабрович! — писал он. — Пишу тебе письмо. Поздравляю вас со светлой Пятницей, и желаю тебе всего на выходных».
Ванька покосился на Скайп и живо вообразил себе Хабра Хабровича. Образ получился впечатляющий, но слишком объёмный. Ванька вздохнул и продолжил писать.
«А вчерась мне была выволочка. Надумал я написать свой таймер, с автоматическим запуском и ручным управлением. Написал, и любовался им долго. Но дядьки, сурово отчитали меня. Ругали, но за чуб не таскали. Дали книжек умных, и советов пользительных.
Дядька Dimezis, ругался сильно за неакуратные имена переменных, да за ключи переменных захардкоженные. Кодстайл ругал тож. Сказал переписать и не позориться.
Дядьки ivazhnov и Alex837 ругали за неаккуратное использование батареи. В морду, мордой ейной не сували, но хмурились сильно. Сказали переписать и не позориться.
Дядька MetAmfetamin, утешил, но поддержал других. Сказал переписать и не позориться».
Ванька почесал за ухом, и продолжил стучать по клавишам.
«Сказали, что нельзя для отлова изменения состояния сети использовать BroadcastReceiver, для которого в манифесте прописано:
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
Нельзя так писать, ибо батарейку выносит не по-детски:
Образец плохого кода
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); } }
<receiver android:name=".UniversalReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver>
Сказали смотреть в сторону JobScheduler или GcmNetworkManager или SyncAdapter.
Долго я думал и решил остановиться на GcmNetworkManager, потому как он для старых версий Android подходит и универсальней мне кажется».
Ванька покосился на гору документации, прочитанной вчера, и зевнул.
«Удалил я для начала все упоминания о UniversalReceiver. Ликвидировал, так сказать, как класс. И из манифеста потёр. Далее создал класс служебный, в который вынес все теги.
Служебный класс Utils
public class Utils { public static final String EXTRA_KEY_OUT = "EXTRA_OUT"; public static final String ACTION_MYINTENTSERVICE = "ru.timgor.alerttest.RESPONSE"; public static final String TAG = "AlertTest"; public static final String SUCCESS = "success"; public static final String AUTOMATIC = "chbAutomatic"; }
Далее в зависимости gradle добавил строчку:
compile 'com.google.android.gms:play-services-gcm:8.1.0'
В MainActivity добавил изменения. Объявил:
private GcmNetworkManager mGcmNetworkManager;
В onCreate:
mGcmNetworkManager = GcmNetworkManager.getInstance(this); setAutoStart(true);
И метод добавил:
setAutoStart
public void setAutoStart(boolean isOn){ if(isOn){ Log.d(Utils.TAG, "Автозапуск задачи"); Random myRandom = new Random(); Bundle bundle = new Bundle(); bundle.putInt("randomNum", myRandom.nextInt(10)); PeriodicTask periodicTask = new PeriodicTask.Builder() .setService(AutomaticService.class) .setTag("PeriodicTask") .setPeriod(30) .setPersisted(true) .setExtras(bundle) .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) .setRequiresCharging(false) .build(); mGcmNetworkManager.schedule(periodicTask); } else { Log.d(Utils.TAG, "Остановка автозапуска задачи"); mGcmNetworkManager.cancelAllTasks(AutomaticService.class); }
Тут, дорогой Хабр Хабрович, коль в метод, правда-истина придёт, объявляю я об намерении создать задачу, которая будет периодически запускать службу AutomaticService (setService), носить тег PeriodicTask(setTag), вызываться раз в 30 секунд(setPeriod), работать после перезапуска(setPersisted), передавать случайное число, не работать пока сеть не подключится (setRequiredNetwork) и не требовать подключения к зарядке(setRequiresCharging). А коли в метод кто-то соврамши передаёт, то автоматическая работа прекращается.
Далее создал я службу AutomaticService, да не простую, а наследуемую от GcmTaskService:
AutomaticService
import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; import com.google.android.gms.gcm.GcmNetworkManager; import com.google.android.gms.gcm.GcmTaskService; import com.google.android.gms.gcm.TaskParams; public class AutomaticService extends GcmTaskService { @Override public int onRunTask(TaskParams taskParams) { Log.d(Utils.TAG, "Автоматический запуск. Начало работы"); Log.d(Utils.TAG, "Переданное число: "+ taskParams.getExtras().getInt("randomNum")); if (!verify()) { Log.d(Utils.TAG, "AUTO. Задача не отработала"); Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); Log.d(Utils.TAG, "Загрузка не произошла"); sendBroadcast(responseIntent); } else { Log.d(Utils.TAG, "AUTO. Задача отработала успешно"); } return GcmNetworkManager.RESULT_SUCCESS; } public boolean verify(){ SharedPreferences settings = getSharedPreferences(Utils.TAG, MODE_PRIVATE); boolean success = settings.getBoolean("success", false); return success; } }
Если служба хорошо отработала, то мы радуемся, а коли не судьба ей исполниться, то запускает BroadcastReceiver, который прописан в MainActivity. Дважды по десять пробует подключиться, с перерывом в 0.1 секунду, да плюнув в сердцах бросает это дело, до следующего тика.
В приложении тестовом я добавил галочку „Очень важная опция“. Коли она нажата, то благополучно задача отрабатывает.
BroadcastReceiver
public class MyBroadRec extends BroadcastReceiver { public int qnt = 0; @Override public void onReceive(Context context, Intent intent) { Boolean result = intent.getBooleanExtra(Utils.EXTRA_KEY_OUT, false); Intent intentRec = new Intent(MainActivity.this, ManualService.class); if(!result && qnt<20){ Log.d(Utils.TAG, "Новая попытка № "+qnt); qnt++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } startService(intentRec); } else { qnt=0; } } }
И в onCreate:
onCreate полностью
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); chbAuto = (CheckBox)findViewById(R.id.chb_Auto); chbVIP = (CheckBox)findViewById(R.id.chb_VIP); btnManual = (Button)findViewById(R.id.btn_Manual); mGcmNetworkManager = GcmNetworkManager.getInstance(this); sPref = getSharedPreferences(Utils.TAG, MODE_PRIVATE); editor = sPref.edit(); editor.putBoolean(Utils.AUTOMATIC, chbAuto.isChecked()); editor.putBoolean(Utils.SUCCESS, chbVIP.isChecked()); editor.commit(); chbAuto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editor.putBoolean(Utils.AUTOMATIC, isChecked); editor.commit(); setAutoStart(isChecked); } }); chbVIP.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editor.putBoolean(Utils.SUCCESS, isChecked); editor.commit(); } }); btnManual.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(Utils.TAG, "Загрузка в ручном режиме"); Intent intent = new Intent(MainActivity.this, ManualService.class); startService(intent); } }); MyBroadRec myBroadRec = new MyBroadRec(); IntentFilter intentFilter = new IntentFilter(Utils.ACTION_MYINTENTSERVICE); intentFilter.addCategory(Intent.CATEGORY_DEFAULT); registerReceiver(myBroadRec, intentFilter); setAutoStart(true); }
Регистрирую этот ресивер».
Ванька оттер пот, покосился на заманчиво запотевший пузырёк с тёмным чаем, решительно тряхнул головой, и продолжил. «А ещё, хочу запускать я вручную задачу, не дожидаясь тика таймера. Для этого написал я службу ManualService наследующуюся от IntentService.
ManualService
import android.app.IntentService; import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; public class ManualService extends IntentService { public ManualService() { super("ManualService"); } @Override protected void onHandleIntent(Intent intent) { if (!verify()) { Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); sendBroadcast(responseIntent); Log.d(Utils.TAG, "MANUAL. Задача не отработала"); } else { Log.d(Utils.TAG, "MANUAL. Задача отработала успешно"); } } public boolean verify(){ SharedPreferences settings = getSharedPreferences(Utils.TAG, MODE_PRIVATE); boolean success = settings.getBoolean(Utils.SUCCESS, false); return success; } }
Запустил я приложение и радовался очень. Если в режим полёта перейти, да выключить интернеты — то автоматический запуск и не думает запускаться. А вот дорогой дедушка и все классы:
MainActivity
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; 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; import com.google.android.gms.gcm.GcmNetworkManager; import com.google.android.gms.gcm.PeriodicTask; import com.google.android.gms.gcm.Task; import java.util.Random; public class MainActivity extends AppCompatActivity { CheckBox chbAuto, chbVIP; Button btnManual; SharedPreferences sPref; SharedPreferences.Editor editor; private GcmNetworkManager mGcmNetworkManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); chbAuto = (CheckBox)findViewById(R.id.chb_Auto); chbVIP = (CheckBox)findViewById(R.id.chb_VIP); btnManual = (Button)findViewById(R.id.btn_Manual); mGcmNetworkManager = GcmNetworkManager.getInstance(this); sPref = getSharedPreferences(Utils.TAG, MODE_PRIVATE); editor = sPref.edit(); editor.putBoolean(Utils.AUTOMATIC, chbAuto.isChecked()); editor.putBoolean(Utils.SUCCESS, chbVIP.isChecked()); editor.commit(); chbAuto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editor.putBoolean(Utils.AUTOMATIC, isChecked); editor.commit(); setAutoStart(isChecked); } }); chbVIP.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editor.putBoolean(Utils.SUCCESS, isChecked); editor.commit(); } }); btnManual.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(Utils.TAG, "Загрузка в ручном режиме"); Intent intent = new Intent(MainActivity.this, ManualService.class); startService(intent); } }); MyBroadRec myBroadRec = new MyBroadRec(); IntentFilter intentFilter = new IntentFilter(Utils.ACTION_MYINTENTSERVICE); intentFilter.addCategory(Intent.CATEGORY_DEFAULT); registerReceiver(myBroadRec, intentFilter); setAutoStart(true); } public class MyBroadRec extends BroadcastReceiver { public int qnt = 0; @Override public void onReceive(Context context, Intent intent) { Boolean result = intent.getBooleanExtra(Utils.EXTRA_KEY_OUT, false); Intent intentRec = new Intent(MainActivity.this, ManualService.class); if(!result && qnt<20){ Log.d(Utils.TAG, "Новая попытка № "+qnt); qnt++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } startService(intentRec); } else { qnt=0; } } } public void setAutoStart(boolean isOn){ if(isOn){ Log.d(Utils.TAG, "Автозапуск задачи"); Random myRandom = new Random(); Bundle bundle = new Bundle(); bundle.putInt("randomNum", myRandom.nextInt(10)); PeriodicTask periodicTask = new PeriodicTask.Builder() .setService(AutomaticService.class) .setTag("PeriodicTask") .setPeriod(30) .setPersisted(true) .setExtras(bundle) .setRequiresCharging(false) .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) .build(); mGcmNetworkManager.schedule(periodicTask); } else { Log.d(Utils.TAG, "Остановка автозапуска задачи"); mGcmNetworkManager.cancelAllTasks(AutomaticService.class); } } }
AutomaticService
import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; import com.google.android.gms.gcm.GcmNetworkManager; import com.google.android.gms.gcm.GcmTaskService; import com.google.android.gms.gcm.TaskParams; public class AutomaticService extends GcmTaskService { @Override public int onRunTask(TaskParams taskParams) { Log.d(Utils.TAG, "Автоматический запуск. Начало работы"); Log.d(Utils.TAG, "Переданное число: "+ taskParams.getExtras().getInt("randomNum")); if (!verify()) { Log.d(Utils.TAG, "AUTO. Задача не отработала"); Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); Log.d(Utils.TAG, "Загрузка не произошла"); sendBroadcast(responseIntent); } else { Log.d(Utils.TAG, "AUTO. Задача отработала успешно"); } return GcmNetworkManager.RESULT_SUCCESS; } public boolean verify(){ SharedPreferences settings = getSharedPreferences(Utils.TAG, MODE_PRIVATE); boolean success = settings.getBoolean("success", false); return success; } }
ManualService
import android.app.IntentService; import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; public class ManualService extends IntentService { public ManualService() { super("ManualService"); } @Override protected void onHandleIntent(Intent intent) { if (!verify()) { Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); sendBroadcast(responseIntent); Log.d(Utils.TAG, "MANUAL. Задача не отработала"); } else { Log.d(Utils.TAG, "MANUAL. Задача отработала успешно"); } } public boolean verify(){ SharedPreferences settings = getSharedPreferences(Utils.TAG, MODE_PRIVATE); boolean success = settings.getBoolean(Utils.SUCCESS, false); return success; } }
Utils
public class Utils { public static final String EXTRA_KEY_OUT = "EXTRA_OUT"; public static final String ACTION_MYINTENTSERVICE = "ru.timgor.alerttest.RESPONSE"; public static final String TAG = "AlertTest"; public static final String SUCCESS = "success"; public static final String AUTOMATIC = "chbAutomatic"; }
Зависимости gradle
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.google.android.gms:play-services-gcm:8.1.0' }
Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ru.alerttest"> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".AutomaticService" android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE" android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/> </intent-filter> </service> <service android:name=".ManualService"/> </application> </manifest>
activity_main
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="ru.alerttest.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Ручной запуск" android:id="@+id/btn_Manual" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Автоматический запуск" android:id="@+id/chb_Auto" android:checked="true"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Очень важная опция" android:id="@+id/chb_VIP" android:checked="true"/> </LinearLayout>
В общем, дорогой дедушка, получился таймер просто загляденье. Буду ждать, что дядьки скажут. А за меня не волнуйся. Хочу стать я разработчиком умным и стараться буду впредь. Засим желаю тебе здоровья крепкого и выходных увлекательных».
Ванька подвинул клавиатуру, набулькал из запотевшего пузырька чая и потянулся к кнопке «Опубликовать». Подумав немного, набрал в теге «На деревню дедушке». Почесал мышку за ухом, и добавил «Хабр Хабровичу».
Профессора из института рассказывали, что публикации разносятся по проводам оптоволоконным и медным, по всему интернету, управляемые веселыми админами. Ванька собрался с духом и нажал большую зелёную кнопку.
Убаюканный сладкими надеждами, он час спустя крепко спал… Ему снился Half-Life 3.
P.S.: Обновленный код, исправленный по замечаниям у��ажаемых комментаторов shakagamii и Parnt
MainActivity
public class MainActivity extends AppCompatActivity { CheckBox chbAuto, chbVIP; Button btnManual; SharedPreferences sPref; SharedPreferences.Editor editor; private GcmNetworkManager mGcmNetworkManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); chbAuto = (CheckBox)findViewById(R.id.chb_Auto); chbVIP = (CheckBox)findViewById(R.id.chb_VIP); btnManual = (Button)findViewById(R.id.btn_Manual); final MyApplicaion app = (MyApplicaion)getApplicationContext(); mGcmNetworkManager = GcmNetworkManager.getInstance(this); final PrefHelper prefHelper = PrefHelper.getInstance(); chbAuto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { prefHelper.setAutomatic(isChecked); setAutoStart(isChecked); } }); chbVIP.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { prefHelper.setSuccess(isChecked); } }); prefHelper.setAutomatic(chbAuto.isChecked()); prefHelper.setSuccess(chbVIP.isChecked()); btnManual.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(Utils.TAG, "Загрузка в ручном режиме"); Intent intent = new Intent(MainActivity.this, ManualService.class); startService(intent); } }); MyBroadRec myBroadRec = new MyBroadRec(); IntentFilter intentFilter = new IntentFilter(Utils.ACTION_MYINTENTSERVICE); intentFilter.addCategory(Intent.CATEGORY_DEFAULT); registerReceiver(myBroadRec, intentFilter); setAutoStart(prefHelper.isAutomatic()); } public class MyBroadRec extends BroadcastReceiver { public int qnt = 0; @Override public void onReceive(Context context, Intent intent) { Boolean result = intent.getBooleanExtra(Utils.EXTRA_KEY_OUT, false); Intent intentRec = new Intent(MainActivity.this, ManualService.class); if(!result && qnt<20){ Log.d(Utils.TAG, "Новая попытка № "+qnt); qnt++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } startService(intentRec); } else { qnt=0; } } } public void setAutoStart(boolean isOn){ if(isOn){ Log.d(Utils.TAG, "Автозапуск задачи"); Random myRandom = new Random(); Bundle bundle = new Bundle(); bundle.putInt(Utils.RANDOM_NUMS, myRandom.nextInt(10)); PeriodicTask periodicTask = new PeriodicTask.Builder() .setService(AutomaticService.class) .setTag("PeriodicTask") .setPeriod(30) .setPersisted(true) .setExtras(bundle) .setRequiresCharging(false) .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) .build(); mGcmNetworkManager.schedule(periodicTask); } else { Log.d(Utils.TAG, "Остановка автозапуска задачи"); mGcmNetworkManager.cancelAllTasks(AutomaticService.class); } } }
Новый класс, для работы с настройками
public class PrefHelper { private static PrefHelper mInstance; private static SharedPreferences sPref; private static SharedPreferences.Editor editor; public static void setInstance(Context context){ mInstance = new PrefHelper(context); } public static PrefHelper getInstance(){ return mInstance; } private PrefHelper(Context context){ this.sPref = PreferenceManager.getDefaultSharedPreferences(context); this.editor = this.sPref.edit(); } public boolean isAutomatic() { return sPref.getBoolean(Utils.AUTOMATIC, false); } public void setAutomatic(boolean automatic) { editor.putBoolean(Utils.AUTOMATIC,automatic); editor.apply(); } public boolean isSuccess() { return sPref.getBoolean(Utils.SUCCESS, false); } public void setSuccess(boolean success) { editor.putBoolean(Utils.SUCCESS, success); editor.apply(); } }
Наследник от Application
public class MyApplicaion extends Application { @Override public void onCreate() { super.onCreate(); PrefHelper.setInstance(this); } }
AutomaticService - автоматический запуск
public class AutomaticService extends GcmTaskService { @Override public int onRunTask(TaskParams taskParams) { Log.d(Utils.TAG, "Автоматический запуск. Начало работы"); Log.d(Utils.TAG, "Переданное число: "+ taskParams.getExtras().getInt(Utils.RANDOM_NUMS)); if (!PrefHelper.getInstance().isSuccess()) { Log.d(Utils.TAG, "AUTO. Задача не отработала"); Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); Log.d(Utils.TAG, "Загрузка не произошла"); sendBroadcast(responseIntent); } else { Log.d(Utils.TAG, "AUTO. Задача отработала успешно"); } return GcmNetworkManager.RESULT_SUCCESS; } }
ManualService - запуск задачи вручную
public class ManualService extends IntentService { public ManualService() { super("ManualService"); } @Override protected void onHandleIntent(Intent intent) { if (!PrefHelper.getInstance().isSuccess()) { Intent responseIntent = new Intent(); responseIntent.setAction(Utils.ACTION_MYINTENTSERVICE); responseIntent.addCategory(Intent.CATEGORY_DEFAULT); responseIntent.putExtra(Utils.EXTRA_KEY_OUT, false); sendBroadcast(responseIntent); Log.d(Utils.TAG, "MANUAL. Задача не отработала"); } else { Log.d(Utils.TAG, "MANUAL. Задача отработала успешно"); } } }
Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ru.cse.alerttest"> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:name=".MyApplicaion" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".AutomaticService" android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE" android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/> </intent-filter> </service> <service android:name=".ManualService"/> </application> </manifest>
Utils
public class Utils { public static final String EXTRA_KEY_OUT = "EXTRA_OUT"; public static final String ACTION_MYINTENTSERVICE = "ru.timgor.alerttest.RESPONSE"; public static final String TAG = "AlertTest"; public static final String SUCCESS = "success"; public static final String AUTOMATIC = "chbAutomatic"; public static final String RANDOM_NUMS = "randomNum"; }
