【问题标题】:Ethernet Connectivity through Programmatically (Android) (Rooted Device)通过编程方式 (Android) 的以太网连接(有根设备)
【发布时间】:2014-03-11 20:33:07
【问题描述】:

我有一个关于以太网的小问题。

我的三个问题是:

  1. 我们能否以编程方式开启/关闭Ethernet

  2. 我们能否以编程方式启用/禁用Ethernet

  3. 我们能否以编程方式连接Ethernet

以上问题均使用Wifi 完成。喜欢

  1. 我们可以通过编程方式开启/关闭Wifi

  2. 我们可以通过编程方式启用/禁用Wifi

  3. 我们可以使用WifiManager 以编程方式连接Wifi

android 是否提供任何EthernetManager 之类的WifiManager 来处理Ethernet

或者,如果这似乎不可行,那么我最初的要求是:

我要明确的第一件事是“DEVICE IS ROOTED”。

我可以操作设置(默认)吗?就像我不想要Settings.apk 中除了WIFIEthernet 之外的任何其他选项。它应该只显示WifiEthernet。而已。我可以从“设置”中禁用所有选项,还是可以从“设置”中删除所有其他选项?

【问题讨论】:

    标签: android ethernet android-networking


    【解决方案1】:

    以上问题的三个答案:

    1. 是的。您可以尝试使用ifconfig eth0 down ; ifconfig eth0 up。但我还没有自己测试过。
    2. 可以,但您不必这样做。 Android 会为您进行切换。如果您连接到 WiFi,以太网将禁用。如果您已经连接到 WiFi 并且将以太网电缆插入设备;您只需要禁用 WiFi(您知道如何操作),android 就会自动切换到以太网。
    3. 并不像您想象的那么容易。我有同样的问题,直到现在我只找到了一个我还没有测试过的解决方案。由于 android 在 linux 内核上运行,我们可以使用 ifconfig 来操作以太网连接。

    这里隐藏了一个解释: http://elinux.org/images/9/98/Dive_Into_Android_Networking-_Adding_Ethernet_Connectivity.pdf

    还有本次讲座的 youtube 视频

    http://www.youtube.com/watch?v=LwI2NBq7BWM

    以及如何使用 ifconfig for android 的参考

    Android ethernet configure IP using dhcp

    因此,如果您找到可能的解决方案,请分享!如果我会在你之前做这件事,我一定会。

    【讨论】:

    • 你成功了吗?我也遇到了
    • 不,很遗憾没有:( ...对不起
    • 运气不好..和你一样..找到有用的东西会在这里更新
    【解决方案2】:

    好的,这里有一些我用来操作以太网接口 (eth0) 的方法。

    1) 一种检查以太网接口是否存在的方法

    public static boolean doesEthExist() {
            List<String> list = getListOfNetworkInterfaces();
    
            return list.contains("eth0");
        }
    
    public static List<String> getListOfNetworkInterfaces() {
    
            List<String> list = new ArrayList<String>();
    
            Enumeration<NetworkInterface> nets;
    
            try {
                nets = NetworkInterface.getNetworkInterfaces();
            } catch (SocketException e) {
    
                e.printStackTrace();
                return null;
            }
    
            for (NetworkInterface netint : Collections.list(nets)) {
    
                list.add(netint.getName());
            }
    
            return list;
    
        }
    

    2) 一种检查 ETHERNET 是否启用或开启的方法

    public static boolean isEthOn() {
    
            try {
    
                String line;
                boolean r = false;
    
                Process p = Runtime.getRuntime().exec("netcfg");
    
                BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));   
                while ((line = input.readLine()) != null) {   
    
                    if(line.contains("eth0")){
                        if(line.contains("UP")){
                            r=true;
                        }
                        else{
                            r=false;
                        }
                    }
                }   
                input.close();
    
                Log.e("OLE","isEthOn: "+r);
                return r; 
    
            } catch (IOException e) {
                Log.e("OLE","Runtime Error: "+e.getMessage());
                e.printStackTrace();
                return false;
            }
    
        }
    

    3) 一种根据以太网状态启用或禁用以太网的方法

    public static void turnEthOnOrOff() {
    
            try {
    
                if(isEthOn()){
                    Runtime.getRuntime().exec("ifconfig eth0 down");
    
                }
                else{
                    Runtime.getRuntime().exec("ifconfig eth0 up");
                }
    
            } catch (IOException e) {
                Log.e("OLE","Runtime Error: "+e.getMessage());
                e.printStackTrace();
            }
        }
    

    4) 一种通过以太网连接的方法,具体取决于所选类型(dhcp/static)

    private boolean connectToStaticSettingsViaIfconfig(StaticConnectionSettings scs) {
    
    
            try {
    
                if(typeChosen.equalsIgnoreCase("dhcp")){
    
                    Runtime.getRuntime().exec("ifconfig eth0 dhcp start");
                }
                else{
    
                    Runtime.getRuntime().exec("ifconfig eth0 "+scs.getIp()+" netmask "+scs.getNetmask()+" gw "+scs.getGateway());
                }
    
            } catch (IOException e) {
                Log.e("OLE","Runtime Error: "+e.getMessage());
                e.printStackTrace();
                return false;
            }
    
            return true;
        }
    

    我还创建了一个类来存储所需的所有 eth 值。这个类是用用户插入的值初始化的。

    public class StaticConnectionSettings {
    
        private String ip, netmask, dns, mac, gateway, type;
    
    //Getters and Setters
    }
    

    就是这样...我将很快对其进行测试...此代码缺少测试阶段(ping)。也许它需要设置DNS。但这很容易做到。我没有包含它,因为我认为在我们的设备上它也可以在没有 DNS 设置的情况下工作。

    【讨论】:

    • 根据我的经验:1)ifconfig eth0 down 不起作用,Android 会自动重新启动界面,2)ifconfig eth0 dhcp start 也不起作用。
    • 没有。 ifconfig 在我的情况下不起作用。它仅适用于busybox ifconfig。显然,它需要 root 权限,但我不能假设生产设备是 root 的。
    • 一旦发现您已连接到以太网,我们如何将数据发送到以太网?
    • 这一行:Runtime.getRuntime().exec("ifconfig eth0 "+scs.getIp()+" netmask "+scs.getNetmask()+" gw "+scs.getGateway()); 可能不起作用。您将需要使用超级用户模式来应用此方法。试试:Runtime.getRuntime().exec(new String[] {"su", "-c", "ifconfig eth0 "+scs.getIp()+" netmask "+scs.getNetmask()+" gw "+scs.getGateway()});
    • 打开和关闭连接工作正常,但我无法使用上述命令设置 ip 和网关。它不断抛出错误。
    【解决方案3】:

    我将在此处介绍的解决方案是使用反射的 hack,并且仅适用于有根的 android 系统。

    您的设备可能有流行的 android.net.ethernet 包。在 Activity 中,尝试

    Object emInstance = getSystemService("ethernet");
    

    它返回一个有效的 EthernetManager 实例或 null。 Null 表示你运气不好。

    附加要求可能取决于您的设备:以太网和 Wifi 可能只能单独使用。您可能需要禁用 Wifi 才能启用以太网,反之亦然。

    要通过反射启用以太网,请使用您的 EthernetManager 实例。 你要调用的方法是setEthEnabled(boolean enabled)

        Class<?> emClass = null;
        try {
            emClass = Class.forName("android.net.ethernet.EthernetManager");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        Object emInstance = getSystemService("ethernet");
    
        Method methodSetEthEnabled = null;
        try {
            methodSetEthEnabled = emClass.getMethod("setEthEnabled", Boolean.TYPE);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        methodSetEthEnabled.setAccessible(true);
        try {
            // new Boolean(true) to enable, new Boolean(false) to disable
            methodSetEthEnabled.invoke(emInstance, new Boolean(false));
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    

    您的应用清单需要这些权限

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

    WRITE_SECURE_SETTINGS 权限只能由系统应用获取。该应用程序不需要由系统密钥签名。它可以是任何有效的标志(如常规的 Android 应用程序导出功能)。使用 busybox 重新挂载系统分区以进行写访问,并将您的 apk 移动到 /system/app 文件夹中。重新启动设备,它应该可以工作了。

    我们能否以编程方式连接以太网?

    没有接入点可以像 Wifi 一样连接您。您可以为 DHCP 配置它或提供静态值。这当然也可以通过反射来完成。 为此,您将需要 EthernetDevInfo 类。

    EthernetManager 和 EthernetDevInfo 的实际实现可能在 Android 版本和设备之间略有不同,因为它不必(目前)符合公共 api,甚至可能是自定义版本。 要获取 getter 和 setter 列表,您可以使用 Introspector 或一般反射。

    【讨论】:

    • 在我的情况下(android 2.3)它是 android.net.EthernetManager 和 setEthernetEnabled 方法。但后来我得到错误 java.lang.reflect.InvocationTargetException
    • @Robin 你做错了。您需要将getSystemService("ethernet") 转换为EthernetManager。更好的是,使用getSystemService(Context.ETHERNET_SERVICE) 并投射它。然后,您可以为该管理器/服务使用适当的接口。
    • @ChefPharaoh 我知道这是一个旧帖子,但只是想从你们那里得到一些东西。尝试在 Android 11 中执行此操作,但似乎 Context.ETHERNET_SERVICE 不再可用。我需要做些什么才能访问它吗?
    • 法老大厨说您需要使用 Context.ETHERNET_SERVICE 而不是“以太网”,这是错误的。事实上两者都是一样的。 ->公共静态最终字符串ETHERNET_SERVICE =“以太网”;但该变量是隐藏的,因此 Android 公共 API 无法使用。这就是使用反射的全部意义。访问存在但未通过公共 api 公开的内容。我个人在 Android 11 上没有这方面的经验,所以我无法在那里指导你。但是你可能会在 frameworks/opt/ethernet 中找到一些有用的东西:android.googlesource.com/platform/frameworks/opt/net/ethernet
    【解决方案4】:

    适用于 Android 6.0.1

    Class<?> ethernetManagerClass = Class.forName("android.net.ethernet.EthernetManager");
    
    Method methodGetInstance = ethernetManagerClass.getMethod("getInstance");
    Object ethernetManagerObject = methodGetInstance.invoke(ethernetManagerClass);
    
    Method methodSetEthEnabled = ethernetManagerClass.getMethod("setEthernetEnabled", Boolean.TYPE);
    methodSetEthEnabled.invoke(ethernetManagerObject, isEnabled);
    

    【讨论】:

    • 这需要root吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多