重置Android手机网络信号?

6
我需要我的应用程序重置设备的移动网络信号。这将产生与切换飞行模式相同的效果,其中连接暂时丢失,在重新连接时分配新的IP地址,并且状态栏中的LTE /信号图标应在重新连接后消失然后重新出现。我在Play商店上找到了一个名为an app的应用程序,我在运行Android 4.4.4和CyanogenMod的手机上对其进行了测试,它确实可以达到这个效果,但我不确定如何在自己的应用程序中实现这一点。我认为这与CHANGE_NETWORK_STATE权限有关。我正在寻找文档或一些简单的示例代码,以重置网络连接。
请注意,我并没有特别尝试切换飞行模式,而是像上面链接的应用程序那样重置移动数据,因为我已经测试过它确实可以在不需要root权限的情况下工作。

3
请您能否提供一下您的反对意见并解释一下,这样我就可以改进我的问题了。我看到您将其标记为“过于宽泛”进行关闭投票。我认为我的问题很明确,并询问如何实现一个非常具体的任务,我已经给出了示例(连接暂时丢失、新IP、信号图标更改)。我添加了一个结论句,更好地表达了我所寻求的答案类型(文档或示例代码)。这个变化是否缩小了它的广泛性?如果没有,我该如何改进呢? - Keavon
1
一个改进的建议是展示一些你当前尝试的代码。 - Marcus
1
@Marcus 我已经查看了大约10个不同的StackOverflow问题和其他Google帖子,其中大多数都是关于切换飞行模式的,但在较新版本的Android中这是不可能的,并尝试使用这些中提到的代码,但它们都已过时或无法工作。我真的没有任何我尝试过的代码,因为我不知道要使用API的哪一部分。然而,我确实找到了原始问题中链接的应用程序,它可以在不需要root权限重置信号的情况下工作,这意味着它是可能的,但我不知道要使用API的哪一部分。 - Keavon
有人找到在Marshmallow 6.0或更新版本上实现此功能的方法吗?问题中链接的应用程序适用于Android 6/7,但是提供的答案没有根权限无法使用。 - lanrat
@Keavon,我也需要在Android 10中实现类似的场景。我有不同的按钮来选择首选移动网络类型,如4g、3g和2g。我希望一旦我们选择了按钮,移动网络就会刷新并更改为选择的网络类型。但作为初始步骤,我想要刷新网络。需要你的帮助。 - Roohi Zuwairiyah
2个回答

3
棒棒糖版本的支持需要一个新的系统级别权限android.permission.MODIFY_PHONE_STATE才能正常工作。
private static boolean setMobileConnectionEnabled(Context context, boolean enabled)
{
    try{
        // Requires: android.permission.CHANGE_NETWORK_STATE
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD){
            // pre-Gingerbread sucks!
            final TelephonyManager telMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            final Method getITelephony = telMgr.getClass().getDeclaredMethod("getITelephony");
            getITelephony.setAccessible(true);
            final Object objITelephony = getITelephony.invoke(telMgr);
            final Method toggleDataConnectivity = objITelephony.getClass()
                .getDeclaredMethod(enabled ? "enableDataConnectivity" : "disableDataConnectivity");
            toggleDataConnectivity.setAccessible(true);
            toggleDataConnectivity.invoke(objITelephony);
        }
        // Requires: android.permission.CHANGE_NETWORK_STATE
        else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
            final ConnectivityManager connMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
            // Gingerbread to KitKat inclusive
            final Field serviceField = connMgr.getClass().getDeclaredField("mService");
            serviceField.setAccessible(true);
            final Object connService = serviceField.get(connMgr);
            try{
                final Method setMobileDataEnabled = connService.getClass()
                    .getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
                setMobileDataEnabled.setAccessible(true);
                setMobileDataEnabled.invoke(connService, Boolean.valueOf(enabled));
            }
            catch(NoSuchMethodException e){
                // Support for CyanogenMod 11+
                final Method setMobileDataEnabled = connService.getClass()
                    .getDeclaredMethod("setMobileDataEnabled", String.class, Boolean.TYPE);
                setMobileDataEnabled.setAccessible(true);
                setMobileDataEnabled.invoke(connService, context.getPackageName(), Boolean.valueOf(enabled));
            }
        }
        // Requires: android.permission.MODIFY_PHONE_STATE (System only, here for completions sake)
        else{
            // Lollipop and into the Future!
            final TelephonyManager telMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
            final Method setDataEnabled = telMgr.getClass().getDeclaredMethod("setDataEnabled", Boolean.TYPE);
            setDataEnabled.setAccessible(true);
            setDataEnabled.invoke(telMgr, Boolean.valueOf(enabled));
        }
        return true;
    }
    catch(NoSuchFieldException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(IllegalAccessException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(IllegalArgumentException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(NoSuchMethodException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(InvocationTargetException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    return false;
}

需要权限。

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>

这个更改只是刷新移动数据的状态(启用和禁用),还是像飞行模式一样刷新移动网络本身,即先禁用移动网络,然后再重新启用? - Roohi Zuwairiyah

1
从4.4.2版本开始,无法获得切换飞行模式或移动数据的权限。但是,使用反射可以绕过这个限制。
以下是如何切换飞行模式的方法: 在Android中切换飞行模式 以下是一个在4.4.2之前和之后切换移动数据的方法(使用反射): 在Android 4.4.2上以编程方式切换移动数据 注意,我在我的最爱搜索引擎上搜索“android toggle airplane mode”和“android toggle mobile data”不到3分钟就找到了所有内容。
注意2:您也可以使用反射来切换飞行模式,但您可能需要挖掘一些必要的ASOP API或查看其他人(例如CyanogenMod)是否已经完成了它。

也许你可以提供一个链接到你的搜索引擎。如果我在谷歌中使用你的搜索词,我得不到编码方面的结果(如几乎所有关于Android主题的问题一样,除非我添加一些SDK / API相关的内容)。这些术语太笼统了。 - The incredible Jan
@TheincredibleJan 我使用了谷歌。此外,我是两年前写的那篇答案,所以搜索结果可能略有变化。然而,今天,第一个搜索词的第一个结果仍然是我为“如何切换飞行模式”提供的链接。使用第二个搜索词,我没有得到我的链接。但是,添加“编程方式”这个词,我得到了与我答案中的第一个结果相同的链接。重点是使用搜索引擎轻松找到问题的答案。如果您需要帮助学习如何制作搜索词...请使用您喜欢的搜索引擎。 - iheanyi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接