三、Android开启wifi热点

        前两篇博文我们说到了如何开启和连接wifi, 现在我们再来说说Android如何开启wifi热点。相对于开启wifi,开启热点会麻烦很多。不同版本的SDK方法都是不一样的。这篇文章主要来说说不同版本间是如何打开热点的。


方法一、

注:这种方法只适用于安卓7.0或7.0以下版本且版本>=4.0,4.0之前的手机没有测试过,不知道行不行,有兴趣的同学去试试哈,因为现在几乎很少有4.0以下的手机了,我们平时开发的应用也都是基于4.0+,所以这时就不探讨4.0之前的系统了。

废话不多说,直接上代码:

/* 开启/关闭热点 */
    public static boolean setWifiApEnabled(final Context context, String ssid, String password, final boolean enabled) {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        if (enabled) { 
            // 因为wifi和热点不能同时打开,所以打开热点的时候需要关闭wifi
            wifiManager.setWifiEnabled(false);
        }

        if(Build.VERSION.SDK_INT >= 26){
            ((Activity)context).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    setWifiApEnabledForAndroidO(context, enabled);
                }
            });
            return true;
        }

        WifiConfiguration ap = null;

        try {
            // 热点的配置类
            WifiConfiguration apConfig = new WifiConfiguration();
            // 配置热点的名称(可以在名字后面加点随机数什么的)
            apConfig.SSID = ssid;
            apConfig.preSharedKey = password;
            apConfig.allowedKeyManagement.set(4);//设置加密类型,这里4是wpa加密

            Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
            // 返回热点打开状态
            return (Boolean) method.invoke(wifiManager, apConfig, enabled);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

上面是开启热点ssid 和密码的热点,我们也可以通过这个方法获取系统热点的账号与密码:

Method localmethod = wifiManager.getClass().getMethod("getWifiApConfiguration", new Class[0]);
WifiApConfiguration ap = (WifiConfiguration) localmethod.invoke(wifiManager, new Object[0]);
String ssid = ap.SSID;//热点名称
String password = ap.preSharedKey;//热点密码

在7.0之前这种方式获取系统热点名称和密码是可以,很遗憾的是在7.1开始这种方法已经无法使用了,通过查看7.0的代码我们发现getWifiApConfiguration已经被标注为@SystemApi,意思是系统api只有系统应用可以调用 ,我们应用层是无法调用的,除非给应用加上系统签名。


方法二、

注:此方法只对安卓8.0可用

/**
     * 8.0 开启热点方法
     * 注意:这个方法开启的热点名称和密码是手机系统里面默认的那个
     * @param context
     */
    public static void setWifiApEnabledForAndroidO(Context context, boolean isEnable){
        ConnectivityManager connManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);

        Field iConnMgrField = null;
        try {
            iConnMgrField = connManager.getClass().getDeclaredField("mService");
            iConnMgrField.setAccessible(true);
            Object iConnMgr = iConnMgrField.get(connManager);
            Class<?> iConnMgrClass = Class.forName(iConnMgr.getClass().getName());

            if(isEnable){
                Method startTethering = iConnMgrClass.getMethod("startTethering", int.class, ResultReceiver.class, boolean.class);
                startTethering.invoke(iConnMgr, 0, null, true);
            }else{
                Method startTethering = iConnMgrClass.getMethod("stopTethering", int.class);
                startTethering.invoke(iConnMgr, 0);
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

附上另一位大神关于8.0开启热点的文章Android8.0 WiFi热点适配,这位大神对源码进行了深入的分析,希望对大家有用。


方法三、

这种方式适合7.1-8.1之间的安卓版本,不过这种方式打开的热点ssid是用UUID随机生成的,类似:AndroidShare_7640,其中AndroidShare_是固定的,而后面的数字则是随机的,我们打开热点前并不知道热点的名称和密码,但是可以在打开后在回调中通过LocalOnlyHotspotReservation获取:

WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        //cancelLocalOnlyHotspotRequest 是关闭热点
        //打开热点
        manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback(){

            @Override
            public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
                super.onStarted(reservation);
                Log.d(TAG, "Wifi Hotspot is on now");
            }

            @Override
            public void onStopped() {
                super.onStopped();
                Log.d(TAG, "onStopped: ");
            }

            @Override
            public void onFailed(int reason) {
                super.onFailed(reason);
                Log.d(TAG, "onFailed: ");
            }
        },new Handler());

注意:

1、前面7.0之前的方式是可以自由配置热点的ssid和密码的,8.0这种方式就只能是打开系统默认那个ssid和密码的热点了。

2、第一种方式可运行在子线程,而第二种方式只能运行在UI主线程。

3、以上方式最好加上定位权限,否则有些手机可能无法打开热点。



好了,热点的分享就说到这里,从4.0到8.1开热点的方式其实换了很多种,据说安卓9.0所有隐式api将不再对应用程开放,那样的话开启wifi获取热点的打开都会受到很多影响,那些依赖于热点和wifi的应用就要多多关注各个安卓版本间对于api的改变了,可以遇见的是google未来对权限的控制肯定会越来越紧届时api肯定也会变,我们要时刻关注。


  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值