package com.bwx.bequick.handlers;
import static com.bwx.bequick.handlers.apn.ApnControl.STATE_OFF;
import java.lang.reflect.Method;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import com.bwx.bequick.Constants;
import com.bwx.bequick.MainSettingsActivity;
import com.bwx.bequick.R;
import com.bwx.bequick.fwk.Setting;
import com.bwx.bequick.fwk.SettingHandler;
import com.bwx.bequick.handlers.apn.ApnControl;
import com.bwx.bequick.preferences.MobileDataPrefs;
/**
* Does not work in 2.3.3
* http://android.git.kernel.org/?p=platform/frameworks/base.git;a=commit;h=f4ece2086f3b7060edc4b93a12f04c9af648867a
* http://stackoverflow.com/questions/4715250/how-to-grant-modify-phone-state-permission-for-apps-ran-on-gingerbread
*
* @author sergej@beworx.com
*/
public class MobileDataSettingHandler2 extends SettingHandler {
private static final String TAG = "qs.md";
private static class TelephonyManagerExt {
private final TelephonyManager mTelManager;
private final ConnectivityManager mConnManager;
public TelephonyManagerExt(Context context) {
mTelManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mConnManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
public boolean setMobileDataEnabled(boolean enabled) {
try {
Method m = mTelManager.getClass().getDeclaredMethod("getITelephony"); m.setAccessible(true);
Object telephony = m.invoke(mTelManager);
m = telephony.getClass().getMethod((enabled ? "enable" : "disable") + "DataConnectivity");
m.invoke(telephony);
return true;
} catch (Exception e) {
Log.e(TAG, "cannot fake telephony", e);
return false;
}
}
public NetworkInfo getMobileDataInfo() {
return mConnManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
}
public NetworkInfo getWiFiInfo() {
return mConnManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
}
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
updateState(info.getState());
}
}
};
private TelephonyManagerExt mTelephonyManager;
private int mTryCounter;
public MobileDataSettingHandler2(Setting setting) {
super(setting);
}
@Override
public void activate(MainSettingsActivity activity) throws Exception {
mActivity = activity;
mTelephonyManager = new TelephonyManagerExt(activity);
activity.registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
updateState(mTelephonyManager.getMobileDataInfo().getState());
}
@Override
public void deactivate() {
mActivity.unregisterReceiver(mReceiver);
}
@Override
public void onSelected(int buttonIndex) {
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName("com.android.phone", "com.android.phone.Settings");
mActivity.startActivitiesSafely(intent, new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}
@Override
public void onSwitched(boolean enable) {
boolean maySwitchDirectly = MobileDataPrefs.detectMobileDataMode(mActivity.getSharedPreferences(Constants.PREFS_COMMON, 0));
if (Constants.DEBUG) {
Log.d(TAG, "may switch data directly: " + maySwitchDirectly);
}
if (maySwitchDirectly) {
switchMobileDataDirectly(enable);
} else {
onSelected(0); // just shortcut
}
}
private void switchMobileDataDirectly(boolean enable) {
boolean mobileDataAllowed = Settings.Secure.getInt(mActivity.getContentResolver(), "mobile_data", 1) == 1;
if (enable && !mobileDataAllowed) {
// cannot switch - system Mobile Data should be enabled first
Toast.makeText(mActivity, R.string.txt_enable_data_access_first, Toast.LENGTH_LONG).show();
onSelected(0); // open system settings
return;
}
boolean wifiConnected = mTelephonyManager.getWiFiInfo().getState() == State.CONNECTED;
if (enable && wifiConnected) {
// cannot switch - WiFi should be disabled first
WifiManager wifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
}
if (enable) {
// is APN is disabled we need to enable it first
Context context = mActivity;
SharedPreferences prefs = mActivity.getApp().getPreferences();
int state = ApnControl.getApnState(context, prefs);
if (state == STATE_OFF) {
ApnControl.setApnState(context, prefs, true);
}
}
// now try to enable connection
mTelephonyManager.setMobileDataEnabled(enable);
if (enable) {
if (++mTryCounter > 2) {
// show 2G hint
Toast.makeText(mActivity, R.string.msg_2g_hint, Toast.LENGTH_LONG).show();
if (mTryCounter > 3) {
onSelected(0); // open system settings
}
} else {
Toast.makeText(mActivity, R.string.msg_enabling_mobile_data, Toast.LENGTH_SHORT).show();
}
}
updateState(enable ? mTelephonyManager.getMobileDataInfo().getState() : State.DISCONNECTING);
}
@Override
public void onValueChanged(int value) {
// do nothing
}
void updateState(State state) {
if (state != State.DISCONNECTED) {
mTryCounter = 0;
}
Setting s = mSetting; int resId;
switch (state) {
case CONNECTED: s.checked = true; s.enabled = true; resId = R.string.txt_net_status_connected; break;
case CONNECTING: s.checked = false; s.enabled = false; resId = R.string.txt_net_status_connecting; break;
case DISCONNECTED: s.checked = false; s.enabled = true; resId = R.string.txt_net_status_disconnected; break;
case DISCONNECTING: s.checked = true; s.enabled = false; resId = R.string.txt_net_status_disconnecting; break;
default: s.checked = s.enabled = false; resId = R.string.txt_status_unknown; break;
}
s.descr = getString(resId);
s.updateView();
}
}