/*
* This source is part of the
* _____ ___ ____
* __ / / _ \/ _ | / __/___ _______ _
* / // / , _/ __ |/ _/_/ _ \/ __/ _ `/
* \___/_/|_/_/ |_/_/ (_)___/_/ \_, /
* /___/
* repository.
*
* Copyright (C) 2015 Carmen Alvarez (c@rmen.ca)
*
* 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 ca.rmen.android.networkmonitor.app.service.scheduler;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import ca.rmen.android.networkmonitor.Constants;
import ca.rmen.android.networkmonitor.app.prefs.NetMonPreferences;
import ca.rmen.android.networkmonitor.util.Log;
/**
* Execute the runnable when the network changes.
*/
public class NetworkChangeScheduler implements Scheduler {
private static final String TAG = Constants.TAG + NetworkChangeScheduler.class.getSimpleName();
private Context mContext;
private Runnable mRunnableImpl;
private Handler mHandler;
private HandlerThread mHandlerThread;
private long mLastPollTime;
private TelephonyManager mTelephonyManager;
@Override
public void onCreate(Context context) {
Log.v(TAG, "onCreate");
mContext = context;
// Register the broadcast receiver in a background thread
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION), null, mHandler);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
}
@Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
mContext.unregisterReceiver(mBroadcastReceiver);
if (mTelephonyManager != null)
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
mHandlerThread.quit();
}
@Override
public void schedule(Runnable runnable, int interval) {
Log.v(TAG, "schedule at interval " + interval);
mRunnableImpl = runnable;
}
@Override
public void setInterval(int interval) {
// We ignore the interval.
}
/**
* Prevent running our task too many times successively.
* If we've already run the task recently, schedule it
* to run in a few seconds. Otherwise just run it right now.
*/
private final Runnable mBufferedRunnable = new Runnable() {
@Override
public void run() {
Log.v(TAG, "mBufferedRunnable.run()");
// If we have bad luck, we might be created,
// and receive a broadcast before schedule was called
if (mRunnableImpl == null) return;
long now = System.currentTimeMillis();
if (now - mLastPollTime > NetMonPreferences.PREF_MIN_POLLING_INTERVAL) {
Log.v(TAG, "Will run the task now");
try {
mRunnableImpl.run();
mLastPollTime = System.currentTimeMillis();
} catch (Throwable t) {
Log.v(TAG, "Error executing task: " + t.getMessage(), t);
}
} else {
Log.v(TAG, "Ran the task too recently: will schedule it for later");
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(mBufferedRunnable, NetMonPreferences.PREF_MIN_POLLING_INTERVAL);
}
}
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "onReceive: intent = " + intent);
mHandler.post(mBufferedRunnable);
}
};
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
Log.v(TAG, "onServiceStateChanged " + serviceState);
mHandler.post(mBufferedRunnable);
}
};
}