Toggle airplane mode in Android
Did I make a mistake? It's not working.
public void airplane() {
boolean isEnabled = Settings.System.getInt(this.getApplicationContext().getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1;
Settings.System.putInt(context.getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
//Settings.System.putInt(this.getApplicationContext().getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
Intent intent = new Intent(Intent.ACTION_AIRP开发者_如何学JAVALANE_MODE_CHANGED);
}
This answer contains code necessary to do this. Also make sure you have the WRITE_SETTINGS
permission.
Adapted from Controlling Airplane Mode:
// read the airplane mode setting
boolean isEnabled = Settings.System.getInt(
getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1;
// toggle airplane mode
Settings.System.putInt(
getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);
// Post an intent to reload
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);
Works for all API versions.
- switch authomaticaly for API < 17
- open Default Activity of Airplane mode for user actions for API >= 17
no root, no system level permission!
in AndroidManifest.xml add permission:
<!--airplane mode-->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
then:
@SuppressWarnings("deprecation")
private void initAirplanemodeBtn() {
airplanemodeButton = (ToggleButton) findViewById(R.id.airplanemode_btn);
airplanemodeButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (android.os.Build.VERSION.SDK_INT < 17) {
try {
// read the airplane mode setting
boolean isEnabled = Settings.System.getInt(
getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1;
// toggle airplane mode
Settings.System.putInt(
getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);
// Post an intent to reload
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, e.getMessage());
}
} else {
try {
Intent intent = new Intent(android.provider.Settings.ACTION_AIRPLANE_MODE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (ActivityNotFoundException e) {
try {
Intent intent = new Intent("android.settings.WIRELESS_SETTINGS");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (ActivityNotFoundException ex) {
Toast.makeText(buttonView.getContext(), R.string.not_able_set_airplane, Toast.LENGTH_SHORT).show();
}
}
}
}
});
}
The following can be used on a rooted device.
From commandline, you can toggle airplane mode on/off with the following:
ON:
settings put global airplane_mode_on 1
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
OFF:
settings put global airplane_mode_on 0
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false
This works with android 4.4.2+
Note: it was pointed out by NarendraR that this is not working on the latest version.
I think "Settings.System.AIRPLANE_MODE_ON" is deprecated, Im using:
public class AirplaneModeService {
public boolean run(Context context) {
boolean isEnabled = isAirplaneModeOn(context);
// Toggle airplane mode.
setSettings(context, isEnabled?1:0);
// Post an intent to reload.
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
context.sendBroadcast(intent);
return true;
}
public static boolean isAirplaneModeOn(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.System.getInt(context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
} else {
return Settings.Global.getInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
}
public static void setSettings(Context context, int value) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Settings.System.putInt(
context.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, value);
} else {
Settings.Global.putInt(
context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, value);
}
}
}
I hope this help someone.
As @eggyal mentioned toggling Airplane Mode cannot be done from version 4.2 and up.
But what we can do is turn each of the wireless services:
Wifi can be controlled using WifiService ~ getSystemService(Context.WIFI_SERVICE). Bluetooth can be controlled using BluetoothAdapter- getSystemService(Context.BLUETOOTH_SERVICE).
After some research I found that using Java Reflection you can still control the Android Radios (Wifi, Network, Bluetooth) what Airplane Mode basically does is toggle the state of Bluetooth, Wifi and Networks.
So by controlling the Radios you can in effect create your own Airplane Mode.
WARNING: Using Reflection might fail on some devices (depends on manufacturer implementation of the classes).
This sample code toggles Mobile Network:
private void setMobileRadioEnabled(boolean enabled) {
try {
final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(conman);
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final Method setRadio = iConnectivityManagerClass.getDeclaredMethod("setRadio", Integer.TYPE , Boolean.TYPE);
setRadio.setAccessible(true);
for (NetworkInfo networkInfo : conman.getAllNetworkInfo()) {
if(isNetworkTypeMobile(networkInfo.getType())) {
setRadio.invoke(iConnectivityManager, networkInfo.getType(), enabled);
}
}
} catch (Exception e) {
Log.e(TAG, "Opss...", e);
}
}
public static boolean isNetworkTypeMobile(int networkType) {
switch (networkType) {
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_MMS:
case ConnectivityManager.TYPE_MOBILE_SUPL:
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
case 10:
case 11:
case 12:
case 14:
return true;
default:
return false;
}
}
here before every settings use android.provider like this :
public class MainActivity extends Activity implements OnClickListener {
Button air;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
air = (Button) findViewById(R.id.button1);
air.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// read the airplane mode setting
boolean isEnabled = android.provider.Settings.System.getInt(
getContentResolver(),
android.provider.Settings.System.AIRPLANE_MODE_ON, 0) == 1;
// toggle airplane mode
android.provider.Settings.System.putInt(
getContentResolver(),
android.provider.Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);
// Post an intent to reload
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);
}
}
After lollipop, you can use below method, but it is hidden api and your application needs system level permission
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL"/>
ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mgr.setAirplaneMode(true);
Note that, as documented under Android 4.2 APIs (emphasis added):
New Global Settings
The system settings have been updated to support multiple users with the addition of
Settings.Global
. This collection of settings is similar toSettings.Secure
settings because they are read-only, but applies globally across all user spaces on the device.Several existing settings were relocated here from either
Settings.System
orSettings.Secure
. If your app is currently making changes to settings previously defined inSettings.System
(such asAIRPLANE_MODE_ON
), then you should expect that doing so will no longer work on a device running Android 4.2 or higher if those settings were moved toSettings.Global
. You can continue to read settings that are inSettings.Global
, but because the settings are no longer considered safe for apps to change, attempting to do so will fail silently and the system will write a warning to the system log when running your app on Android 4.2 or higher.
This one works for me
public static boolean isAirplaneModeOn() {
return Settings.System.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
public static void setAirPlaneMode(boolean airplaneMode) {
Logger.d(LOG_TAG + "setAirPlaneMode airplaneMode: " + airplaneMode) ;
int state = airplaneMode ? 1 : 0;
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
state);
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", state);
mContext.sendBroadcast(intent);
}
But you need system permissions though
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
I found this workaround for 17+ if you want to shut off the internet this will work.
permission
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
method
@SuppressWarnings({ "unchecked", "rawtypes" })
private void setMobileDataEnabled(boolean state) {
try {
final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(conman);
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, state);
} catch (Exception e) {
e.printStackTrace();
}
}
精彩评论