/* * Copyright (C) 2010-2017 Stichting Akvo (Akvo Foundation) * * This file is part of Akvo Flow. * * Akvo Flow is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Akvo Flow is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Akvo Flow. If not, see <http://www.gnu.org/licenses/>. */ package org.akvo.flow.service; import android.content.Context; import android.support.v4.util.Pair; import com.google.android.gms.gcm.GcmNetworkManager; import com.google.android.gms.gcm.GcmTaskService; import com.google.android.gms.gcm.PeriodicTask; import com.google.android.gms.gcm.Task; import com.google.android.gms.gcm.TaskParams; import org.akvo.flow.data.preference.Prefs; import org.akvo.flow.domain.apkupdate.ApkUpdateStore; import org.akvo.flow.domain.apkupdate.GsonMapper; import org.akvo.flow.domain.apkupdate.ViewApkData; import org.akvo.flow.util.ConnectivityStateManager; import org.akvo.flow.util.ConstantUtil; import timber.log.Timber; /** * This background service will check the rest api for a new version of the APK. * If found, it will display a {@link org.akvo.flow.activity.AppUpdateActivity}, requesting * permission to download and installAppUpdate it. * * @author Christopher Fagiani */ public class ApkUpdateService extends GcmTaskService { /** * Tag that is unique to this task (can be used to cancel task) */ private static final String TAG = "APK_UPDATE_SERVICE"; private ApkUpdateHelper apkUpdateHelper; public static void scheduleFirstTask(Context context) { schedulePeriodicTask(context, ConstantUtil.FIRST_REPEAT_INTERVAL_IN_SECONDS, ConstantUtil.FIRST_FLEX_INTERVAL_IN_SECOND); } private static void schedulePeriodicTask(Context context, int repeatIntervalInSeconds, int flexIntervalInSeconds) { try { PeriodicTask periodic = new PeriodicTask.Builder() .setService(ApkUpdateService.class) //repeat every x seconds .setPeriod(repeatIntervalInSeconds) //specify how much earlier the task can be executed (in seconds) .setFlex(flexIntervalInSeconds) .setTag(TAG) //whether the task persists after device reboot .setPersisted(true) //if another task with same tag is already scheduled, replace it with this task .setUpdateCurrent(true) //set required network state .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) //request that charging needs not be connected .setRequiresCharging(false).build(); GcmNetworkManager.getInstance(context).schedule(periodic); } catch (Exception e) { Timber.e(e, "scheduleRepeat failed"); } } /** * Cancels the repeated task */ public static void cancelRepeat(Context context) { GcmNetworkManager.getInstance(context).cancelTask(TAG, ApkUpdateService.class); } /** * Called when app is updated to a new version, reinstalled etc. * Repeating tasks have to be rescheduled */ @Override public void onInitializeTasks() { super.onInitializeTasks(); scheduleFirstTask(this); } /** * Check if new FLOW versions are available to installAppUpdate. If a new version is available, * we display {@link org.akvo.flow.activity.AppUpdateActivity}, requesting the user to download * it. */ @Override public int onRunTask(TaskParams taskParams) { //after the first time the task is run we reschedule to a higher interval schedulePeriodicTask(this, ConstantUtil.REPEAT_INTERVAL_IN_SECONDS, ConstantUtil.FLEX_INTERVAL_IN_SECONDS); Context applicationContext = getApplicationContext(); apkUpdateHelper = new ApkUpdateHelper(applicationContext); ConnectivityStateManager connectivityStateManager = new ConnectivityStateManager( applicationContext); Prefs prefs = new Prefs(applicationContext); if (!syncOverMobileNetworksAllowed(prefs) && !connectivityStateManager.isWifiConnected()) { Timber.d("No available authorised connection. Can't perform the requested operation"); return GcmNetworkManager.RESULT_SUCCESS; } try { Pair<Boolean, ViewApkData> booleanApkDataPair = apkUpdateHelper.shouldUpdate(); if (booleanApkDataPair.first) { //save to shared preferences ApkUpdateStore store = new ApkUpdateStore(new GsonMapper(), prefs); store.updateApkData(booleanApkDataPair.second); } return GcmNetworkManager.RESULT_SUCCESS; } catch (Exception e) { Timber.e(e, "Error with apk version service"); return GcmNetworkManager.RESULT_FAILURE; } } private boolean syncOverMobileNetworksAllowed(Prefs prefs) { return prefs.getBoolean(Prefs.KEY_CELL_UPLOAD, Prefs.DEFAULT_VALUE_CELL_UPLOAD); } }