如何在Android Studio中用按钮实现安卓5.0及以上系统移动数据开关
问题排查与解决
现有代码核心问题
ConnectivityManager.requestNetwork()API 不是用来操作系统层面移动数据开关的接口:它的作用是在用户已经开启移动数据的前提下,请求系统为你的应用单独分配蜂窝网络通道,允许你的应用优先通过蜂窝传输数据,不会触发系统移动数据开关的状态变更,所以你点击按钮看不到任何系统层面的变化。- 你使用了匿名
NetworkCallback实例,既没有处理请求结果回调,也没有在页面销毁时释放请求,会产生内存泄漏。
实现移动数据开关的适配方案
首先明确权限限制:Android 系统从高版本开始逐步收紧第三方应用修改移动数据开关的权限,不同版本适配规则如下:
- Android 5.0 ~ Android 7.1.1(API 21~25):普通应用申请对应权限后,可通过反射调用系统隐藏API实现开关控制
- Android 8.0 ~ Android 9(API 26~28):需要应用获取
WRITE_SECURE_SETTINGS权限(普通应用无法通过应用市场上架流程获取,只能通过adb命令手动授权) - Android 10及以上(API 29+):系统完全禁止第三方应用修改移动数据开关,只有系统预装应用、运营商签名应用可使用该能力
适配代码实现
1. 补充Manifest权限
在你现有权限基础上新增:
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
2. 移动数据开关工具类
public class MobileDataUtil { // 切换移动数据开关状态,不会修改WiFi状态 public static void setMobileDataEnabled(Context context, boolean enabled) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10及以上第三方应用无法修改,可提示用户手动跳转设置页 Intent intent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS); context.startActivity(intent); return; } try { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); Method setDataEnabledMethod = TelephonyManager.class.getDeclaredMethod("setDataEnabled", boolean.class); setDataEnabledMethod.invoke(telephonyManager, enabled); } catch (Exception e) { // 权限不足时捕获异常 e.printStackTrace(); } } // 获取当前移动数据开关状态 public static boolean isMobileDataEnabled(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); try { Method getMobileDataEnabledMethod = ConnectivityManager.class.getDeclaredMethod("getMobileDataEnabled"); return (boolean) getMobileDataEnabledMethod.invoke(cm); } catch (Exception e) { e.printStackTrace(); return false; } } }
3. 修正后的MainActivity代码
public class MainActivity extends AppCompatActivity { Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.download); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean currentState = MobileDataUtil.isMobileDataEnabled(MainActivity.this); MobileDataUtil.setMobileDataEnabled(MainActivity.this, !currentState); } }); } }
补充说明
如果你的应用仅需要自身业务使用蜂窝网络,不需要修改系统全局的移动数据开关,可以保留原有的requestNetwork逻辑,通过绑定蜂窝网络通道实现应用内流量走蜂窝、其他应用仍走WiFi的效果,且不需要修改系统开关,适配全版本Android系统。
内容的提问来源于stack exchange,提问作者SRI VINOD PALACHARLA
相关产品推荐
相关产品推荐

