Android7.1之WIFI热点问题
背景
项目需求,需要在Android应用中打开关闭和配置WIFI热点,开始以为只需要简单地调用几下系统API就可以了,后来发现是个大坑。
不同的Android版本操作热点的方式还不一样
Android7.0及以前的版本是通过WifiManager
的setWifiApEnabled
,具体方式如下:
WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
//反射
method.invoke(mWifiManager, null, false);
在Android7.1及后面的版本,主要是通过ConnectivityManager
的startTethering
方法来操作的。
而且对于Android7.1比较奇葩!有的机型可以通过
Wifimanager
的方式进行开启,也能正常连接,但是有的能开启但是无法正常连接.
那么Android7.1的版本怎么用代码去操作WIFI热点呢?主要有以下3种方式:
通过编译修改源码的方式进行,把ConnectivityManager这个包下面的源码单独编译一个jar 然后导入jar包到项目中使用。
源码路径:base/core/java/android/net/ConnectivityManager.java
修改ConnectivityManager
源码,将TETHERING_WIFI
字段、startTethering
方法及OnStartTetheringCallback
类中隐藏相关的标志去掉,然后单独编译一个jar包.
将jar包拷贝到工程中
该jar包会和官方sdk中的android.jar会有冲突,所以需要配置jar包的优先级。
在app的build.gradle
中配置provided files('src/main/libs/WifiAp8.jar')
在工程下的
build.gradle
中添加如下配置:allprojects { gradle.projectsEvaluated { tasks.withType(JavaCompile) { //设置jar相对包路径或绝对路径 options.compilerArgs.add('-Xbootclasspath/p:app/src/main/libs/WifiAp8.jar') } } }
开启热点
if(getWifiAPState() != WIFI_AP_STATE_ENABLED){ //Android8.0及以上版本//需改为7.1 if (Build.VERSION.SDK_INT >= 26) { mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI, true, new ONStartTetheringCallback()); } }
在AS中上述代码会有红色显示,但是不影响编译使用。可以正常编译生成apk。使用该方法不需要提前关闭wifi。
ONStartTetheringCallback
类继承了OnStartTetheringCallback
抽象类。class ONStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback { }
关闭热点
if(getWifiAPState() != WIFI_AP_STATE_DISABLED){ //Android8.0及以上版本//需改为7.1 if (Build.VERSION.SDK_INT >= 26) { mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI); } }
权限
使用上述功能需要这三个权限:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />
还需要在代码中申请
WRITE_SETTINGS
权限,否则不能正常使用。通过8.0的方式走ConnectivityManager 的startTethering方式进行开启热点,但是要注意的是7.1的startTethering 参数和8.0的startTethering参数有所不同注意修改。但是即使这样还是会报一个错误(need MANAGE_USERS or CREATE_USERS permission to: query user)没有权限调用这个Api同时还会出现一个Exec异常InvocationTargetException 就是说你这个app不是系统app需要权限,那我们就把他变成系统app,如何才能变成呢?使用系统签名就可以,具体操作就不在这说了。可参考链接(https://blog.csdn.net/u013340360/article/details/80341833)
这种主要针对有的机型可以通过Wifimanager的方式进行开启,无法正常连接的情况。之所以开启了wifi热点成功,但是却没有成功连接是因为DHCP没有给这个热点分配IP地址,也就导致不能正常使用。