package cm.android.apn;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A utility available to control APN settings The utility object requires a
* {@link Context} object to access the
* {@link ContentResolverandroid.content.ContentResolver} object which modifies
* the APN settings The manifest file of the project which calls the utility
* must have the following permissions: <uses-permission
* android:name="android.permission.WRITE_APN_SETTINGS" /> As it is defined in
* the manifest file for this project and must be able to pass it's context. If
* it's an {@link android.test.ActivityInstrumentationTestCase2} Then it
* requires the following code in the class mContext =
* getInstrumentation().getContext(); If it's an
* {@link android.test.AndroidTestCase} Then it requires the following code in
* the class mContext = getContext();
*
* @author whatsthebeef
*/
public class NetworkManager {
/**
* Object used to interact with APN
*/
private ApnDao mApnDao;
private volatile AtomicBoolean wait = new AtomicBoolean(false);
/**
* Context used to interface with APN settings
*/
private Context mContext;
private ConnectivityManager mConnectivityManager;
private NetworkInfo mNetworkInfo;
private SynchronizableBoolean mDataConnectionStatus;
/**
* Object class allows it to be locked without problem of JVM interning
* the object
*
* @author wtb
*/
private class SynchronizableBoolean {
/**
* The constructor gets the desired reference to pull the information
*/
public SynchronizableBoolean() {
mConnectivityManager = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
}
/**
* @return boolean, is there a data connection
*/
public boolean isDataConnection() {
mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
return (mNetworkInfo == null || !mNetworkInfo.isConnected()) ? false : true;
}
}
/**
* Constructor requires context belonging to an application with sufficient
* privileges as described in class definition
*/
public NetworkManager(Context aContext) {
mContext = aContext;
init();
}
/**
* Initializes object used to interact with APN
*/
private void init() {
mApnDao = new ApnDao(mContext.getContentResolver());
mDataConnectionStatus = new SynchronizableBoolean();
}
/**
* Method used to switch the connectivity on
*
* @return true if operation was successful and network is enable
*/
public void enableNetwork() {
Timer connectivityChangeDetectonTimer = new Timer();
connectivityChangeDetectonTimer.scheduleAtFixedRate(
new ConnectivityChangeDetectionTimerTask(), 1000, 1000);
mApnDao.setDataEnabled(true);
while (!mDataConnectionStatus.isDataConnection()) {
try {
synchronized (mDataConnectionStatus) {
wait.set(true);
while (wait.get()) {
mDataConnectionStatus.wait();
}
}
} catch (InterruptedException e) {
// If interrupt doesn't change connectivity carry on
}
}
connectivityChangeDetectonTimer.cancel();
}
/**
* Method used to switch the connectivity off
*
* @return true if operation was successful and network is disabled
*/
public void disableNetwork() {
Timer connectivityChangeDetectonTimer = new Timer();
connectivityChangeDetectonTimer.scheduleAtFixedRate(
new ConnectivityChangeDetectionTimerTask(), 1000, 1000);
mApnDao.setDataEnabled(false);
while (mDataConnectionStatus.isDataConnection()) {
try {
synchronized (mDataConnectionStatus) {
wait.set(true);
while (wait.get()) {
mDataConnectionStatus.wait();
}
}
} catch (InterruptedException e) {
// If interrupt doesn't change connectivity carry on
}
}
connectivityChangeDetectonTimer.cancel();
}
/**
* Task is used by timer to wake up and check connectivity
*
* @author wtb
*/
private class ConnectivityChangeDetectionTimerTask extends TimerTask {
@Override
public void run() {
synchronized (mDataConnectionStatus) {
wait.set(false);
mDataConnectionStatus.notifyAll();
}
cancel();
}
}
}