org.site_monitor.service.NetworkService.java Source code

Java tutorial

Introduction

Here is the source code for org.site_monitor.service.NetworkService.java

Source

/*
 * Copyright (c) 2016 Martin Norbert
 *  Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.site_monitor.service;

import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.util.Pair;

import org.site_monitor.BuildConfig;
import org.site_monitor.R;
import org.site_monitor.activity.MainActivity;
import org.site_monitor.activity.PrefSettingsActivity;
import org.site_monitor.model.bo.NetworkCallResult;
import org.site_monitor.model.bo.SiteCall;
import org.site_monitor.model.bo.SiteSettings;
import org.site_monitor.model.db.DBHelper;
import org.site_monitor.model.db.DBSiteCall;
import org.site_monitor.model.db.DBSiteSettings;
import org.site_monitor.util.BroadcastUtil;
import org.site_monitor.util.NetworkUtil;
import org.site_monitor.util.NotificationUtil;
import org.site_monitor.widget.WidgetManager;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 */
public class NetworkService extends JobIntentService {

    public static final String ACTION_SITE_START_REFRESH = "org.site_monitor.service.action.SITE_START_REFRESH";
    public static final String ACTION_SITE_END_REFRESH = "org.site_monitor.service.action.SITE_END_REFRESH";
    public static final String REQUEST_REFRESH_SITES = "refreshSites";
    public static final String COMA = ",";
    private static final String TAG = NetworkService.class.getSimpleName();
    private NetworkUtil networkUtil = new NetworkUtil();

    /**
     * @param context
     * @return intent to call start service
     */
    public static Intent intentToCheckSites(Context context) {
        return new Intent(context, NetworkService.class).setAction(REQUEST_REFRESH_SITES);
    }

    public static void enqueueCheckSitesWork(@NonNull Context context) {
        NetworkService.enqueueWork(context, NetworkService.class, JobEnum.CHECK_SITES.ordinal(),
                intentToCheckSites(context));
    }

    /**
     * Called serially for each work dispatched to and processed by the service.  This
     * method is called on a background thread, so you can do long blocking operations
     * here.  Upon returning, that work will be considered complete and either the next
     * pending work dispatched here or the overall service destroyed now that it has
     * nothing else to do.
     * <p>
     * <p>Be aware that when running as a job, you are limited by the maximum job execution
     * time and any single or total sequential items of work that exceeds that limit will
     * cause the service to be stopped while in progress and later restarted with the
     * last unfinished work.  (There is currently no limit on execution duration when
     * running as a pre-O plain Service.)</p>
     *
     * @param intent The intent describing the work to now be processed.
     */
    @Override
    public void onHandleWork(@NonNull Intent intent) {
        if (intent.getAction() == null) {
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "onHandleIntent: no action");
            }
            return;
        }
        DBHelper dbHelper = DBHelper.getHelper(this);
        try {
            DBSiteSettings siteSettingDao = dbHelper.getDBSiteSettings();
            if (intent.getAction().equals(REQUEST_REFRESH_SITES)) {
                DBSiteCall dbSiteCall = dbHelper.getDBSiteCall();
                refreshSites(siteSettingDao, dbSiteCall);
            }
        } catch (SQLException e) {
            Log.e(TAG, "onHandleWork", e);
        } finally {
            if (dbHelper != null) {
                dbHelper.release();
            }
        }
    }

    public void refreshSites(DBSiteSettings siteSettingDao, DBSiteCall dbSiteCall) throws SQLException {
        List<SiteSettings> siteSettingList = siteSettingDao.queryForAll();
        List<Pair<SiteSettings, SiteCall>> failsPairs = new LinkedList<>();
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "action: " + REQUEST_REFRESH_SITES + " nbSites: " + siteSettingList.size());
        }
        for (SiteSettings siteSettings : siteSettingList) {
            if (BuildConfig.DEBUG) {
                Log.v(TAG, "call: " + siteSettings);
            }
            BroadcastUtil.broadcast(this, ACTION_SITE_START_REFRESH, siteSettings);
            SiteCall siteCall = networkUtil.buildHeadHttpConnectionThenDoCall(this, siteSettings);
            siteCall.setSiteSettings(siteSettings);
            BroadcastUtil.broadcast(this, ACTION_SITE_END_REFRESH, siteSettings, siteCall);

            if (siteCall.getResult() == NetworkCallResult.FAIL) {
                failsPairs.add(new Pair<>(siteSettings, siteCall));
            }
            dbSiteCall.create(siteCall);
        }

        boolean atLeastOneToNotify = false;
        if (!failsPairs.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
            boolean limitToNewFail = preferences.getBoolean(PrefSettingsActivity.NOTIFICATION_LIMIT_TO_NEW_FAIL,
                    true);
            for (Pair<SiteSettings, SiteCall> pair : failsPairs) {
                // never break to get all sites in fail
                if (sb.length() > 0) {
                    sb.append(COMA);
                }
                sb.append(pair.first.getName());
                if (pair.first.isNotificationEnabled()) {
                    if (limitToNewFail) {
                        if (pair.first.getSiteCalls().isEmpty()) {
                            atLeastOneToNotify = true;
                        } else {
                            List<SiteCall> siteCalls = new ArrayList<>(pair.first.getSiteCalls());
                            Collections.sort(siteCalls, SiteCall.DESC_DATE);
                            SiteCall previousCall = siteCalls.get(0);
                            if (previousCall.getResult() == NetworkCallResult.SUCCESS) {
                                atLeastOneToNotify = true;
                            }
                        }
                    } else {
                        atLeastOneToNotify = true;
                    }
                }
            }
            if (atLeastOneToNotify) {
                PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                        new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
                NotificationCompat.Builder notificationBuilder = NotificationUtil.build(this,
                        failsPairs.size() + " " + getString(R.string.state_unreachable), sb.toString(),
                        pendingIntent);
                NotificationUtil.send(this, NotificationUtil.ID_NOT_REACHABLE, notificationBuilder.build());
            }
        }
        WidgetManager.refresh(this);
    }

}