Android手机创建热点,有很多兼容性问题,网上有很多例子,但是不够全,而且高版本反射很多奔溃,我这里再总结下。
1)AndroidMainifest.xml里面需要添加的权限
2)各个手机版本创建和权限说明
如果是7.1版本以下手机,我们除了在AndroidManifest.xml里面添加Manifest.permission.WRITE_SETTINGS权限,还需要申请这个权限Manifest.permission.WRITE_SETTINGS,
ActivityCompat.requestPermissions(this, permissions, REQUEST_SYSTEM_CANWRITE_CODE);
6.0到7.1版本我们可以用下面的代码检测是否有这个权限
Settings.System.canWrite(applicationContext)
6.0以下的手机可以用下面的代码检测权限
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED;
这里不需要上面AndroidMainifest.xml的定位权限,和手动打开GPS权限。 这里可以设置WiFi热点的用户名ssid和密码,当然也可以设置不要密码的形式。
如果发现是这个版本,跳转到热点配置页面,让客户自己去配置,然后在onActivityResult里面判断是否开启了热点,开启了再去读用户已经配置好的热点信息
这里其实不需要 Manifest.permission.WRITE_SETTINGS权限,也不需要申请这个权限,但是需要定位权限
这里需要动手请申请,就是6.0以后的普通权限申请,还需要手动打开GPS权限,如果发现没有打开GPS,则跳转到打开GPS权限的页面,让用户开起,然后在onActivityResult检测是否已经开启了GPS权限,有了申请的ACCESS_FINE_LOCATION权限和GPS权限,才能用下面的方式开启热点
var wifiManager:WifiManager = getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager
try {
wifiManager.startLocalOnlyHotspot(object : WifiManager.LocalOnlyHotspotCallback(){
override fun onStarted(reservation: WifiManager.LocalOnlyHotspotReservation?) {
super.onStarted(reservation)
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onStarted");
reserva = reservation
var wifiConfiguration = reservation!!.wifiConfiguration
var ssid = wifiConfiguration.SSID;
var password = wifiConfiguration.preSharedKey
Log.i(TAG, "ssid is:" + ssid + "password is:" + password);
}
override fun onStopped() {
super.onStopped()
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onStopped");
}
override fun onFailed(reason: Int) {
super.onFailed(reason)
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onFailed and reason isL" + reason);
openWifiAPFail()
}
}, handler)
} catch (e: Exception) {
e.printStackTrace();
Log.i(TAG, "open wifi Ap fail")
openWifiAPFail()
}
这里的热点用户名和密码是系统随机设置的,我们不能进行设置,然后关闭热点,调用代码如下
var reserva:WifiManager.LocalOnlyHotspotReservation? = null
if (reserva != null){
reserva!!.close();
}
3)热点开启后,手机热点服务器的IP地址是固定的,地址是192.168.43.1
主要创建类
class WifiAPActivity : BaseActivity() {
var loadingDialog : CreateWifiApLoadingDialog? = null
var wifiApAdmin: WifiApUtil? = null
var handler: Handler? = null
var counter: Counter? = null
var openGpsDialog: ShareCommonDialog? = null
var opeWifiDialog: ShareCommonDialog? = null
var isNeedOpenWifi = true
companion object {
const val REQUEST_GPS_CODE = 100
const val REQUEST_SYSTEM_CANWRITE_CODE = 200
const val REQUEST_SYSTEM_WIFIAP_PAGE_CODE = 300
}
override fun getLayoutResID(): Int {
return R.layout.activity_wifi_share
}
override fun initListener() {
}
fun showCreateWifiApLoading() {
if (loadingDialog == null)
loadingDialog = CreateWifiApLoadingDialog()
loadingDialog!!.show(supportFragmentManager,"")
}
fun closeWifiApLoading() {
loadingDialog?.dismiss()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.i(TAG, "onActivityResult start requestCode is:" + requestCode)
//Android8.0以上版本
if (requestCode == REQUEST_GPS_CODE) {
var result = GpsUtil.isOPen(this)
if (!result) {
cancelOpenGPS();
} else {
//开启8.0版本以上的热点
initWifiApGreaterThanEight(this)
}
}
//Android7.1以下版本
if (requestCode == REQUEST_SYSTEM_CANWRITE_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //Settings.System.canWrite方法检测授权结果
if (Settings.System.canWrite(applicationContext)) {
Log.i(TAG, "has ACTION_MANAGE_WRITE_SETTINGS ");
Log.i(TAG, "onActivityResult initData create wifi")
//开启7.1版本以下的热点
openWifiAP()
} else {
Log.i(TAG, "has no ACTION_MANAGE_WRITE_SETTINGS");
ToastUtils.showShort(R.string.text_please_allow_permisson)
finish()
}
} else {
Log.i(TAG, "Build.VERSION.SDK_INT < Build.VERSION_CODES.M");
}
}
//Android7.1版本
if (requestCode == REQUEST_SYSTEM_WIFIAP_PAGE_CODE) {
var result = WifiApUtil.checkWife()
Log.i(TAG, "requestCode == REQUEST_SYSTEM_WIFIAP_PAGE_CODE result is:" + result);
//这里不确定android7.1版本手机开启热点之后,这里立马检查会不会有延时,如果有可以用定时器来查询
if (!result) {
cancelGotoSetWifiPage();
} else {
//开启7.1版本热点已开启,这开启服务,并且获取配置热点的用户名和密码的配置信息显示在页面
//创建成功,然后开辟线程,启动服务
var getConfigResult = getWiFiAPConfig()
Log.i(TAG, "getConfigResult is:" + getConfigResult)
if (getConfigResult)
Thread(HttpServerThread(this)).start()
else
openWifiAPFail()
}
}
}
override fun initData() {
//这里需要传递能直接下载apk的链接地址作为content
handler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == 2020) {
}
}
}
setQRCode()
wifiApAdmin = WifiApUtil(this)
initWifiPermisson()
}
/**
* 打开wifi热点并且开始检测是否已经开启成功,这里是针对Android7.1以下的版本打开热点,不需要密码
*/
fun openWifiAP() {
//暂时用用户名作为创建热点的名字,怎么自动连接,不需要密码还需要研究
var wifiName = SPHelper.getInstance().getString(SpConstants.USER_NAME, Constants.DEFAULT_NAME)
wifiApAdmin!!.startWifiAp(wifiName, "");
counter = Counter(this)
handler!!.post(counter)
}
/**
* 定时检查开启热点是否生效的任务
*/
inner class Counter : Runnable {
var context: Context? = null
constructor(context: Context) {
this.context = context
}
override fun run() {
var result = false;
result = WifiApUtil.checkWife();
Log.i(TAG, "result is:" + result);
if (result) {
Thread(context?.let { HttpServerThread(it) }).start()
handler!!.removeCallbacks(this);
return
}
handler!!.postDelayed(this, 1000)
}
}
/**
* 设置二维码图片
*/
fun setQRCode() {
var ipAndPort = getIpAndPort()
var bitmap = QRCodeUtil.createQRCodeBitmap(ipAndPort, 500, 500,"UTF-8","H", "1", Color.BLACK, Color.WHITE);
iv_share_qr_code.setImageBitmap(bitmap);
}
/**
* 获取服务器的IP和端口
*/
fun getIpAndPort(): String {
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
return HTTP + SocketContants.HTTP_SERVER_IP + ":" + SocketContants.HTTP_SERVER_PORT;
// } else {
// //如果是Android9.0以上的手机,服务器IP地址是随机的,目前还没有找到办法获取,后续研究反射INetworkManagementService的getInterfaceConfig("wlan0")方法
// return SocketContants.HTTP_SERVER_IP + ":" + rrf.HTTP_SERVER_PORT;
// }
}
/**
* 设置页面wifi热点的名字和浏览器需要输入的IP和端口
*/
fun setViewWifiApName(wifiName :String) {
//暂时用用户名作为创建热点的名字
// var wifiName = SPHelper.getInstance().getString(SpConstants.USER_NAME, SpConstants.DEFAULT_NAME)
var hasColorWifiName = Constants.FONT_COLOR_START + wifiName + Constants.FONT_COLOR_END;
//这里需要获取热点的值
var connect = getResources().getString(R.string.tip_first_step_connect);
tv_wifi.setText(Html.fromHtml(connect + hasColorWifiName))
tv_ip.setText(getIpAndPort())
}
/**
* 设置页面wifi热点的密码
*/
fun setViewWifiApPassword(password: String) {
var hasColorWifiPassword = Constants.FONT_COLOR_START + password + Constants.FONT_COLOR_END;
tv_password.visibility = View.VISIBLE
//这里需要获取热点的值
var contentPassword = getResources().getString(R.string.text_wifi_ap_password);
tv_password.setText(Html.fromHtml(contentPassword + hasColorWifiPassword))
}
/**
* WRITE_SETTINGS权限申请,6.0以下不需要,6.0以上到7.1需要
*/
fun checkPermissionAndOpenWifiAP() {
var permission: Boolean = false
//大于6.0需要申请canWrite权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
permission = Settings.System.canWrite(this)
} else {
permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED;
}
if (permission) {
Log.i(TAG, "initData create wifi")
//创建热点
openWifiAP()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 判断是否有WRITE_SETTINGS权限if(!Settings.System.canWrite(this))
Log.i(TAG, "initData !Settings.System.canWrite(this)")
val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:$packageName"))
startActivityForResult(intent, REQUEST_SYSTEM_CANWRITE_CODE)
} else {
var permissions = arrayOf("Manifest.permission.WRITE_SETTINGS")
//这种情况还没有测试Androi6.0以下的手机,看是否需要回调onActivityResult进行处理
ActivityCompat.requestPermissions(this, permissions, REQUEST_SYSTEM_CANWRITE_CODE);
}
}
}
override fun injectorCompontent() {
}
override fun initView(savedInstanceState: Bundle?) {
// addStatusBar()
// mPTitleBarView.setSubPageTitle(null)
// mPTitleBarView.setSubPageTitle(R.string.text_hotspot_share)
addStatusBar(R.color.white)
mPTitleBarView.setSubPageTitle(R.string.text_hotspot_share)
mPTitleBarView.setBackgroundColorResource(getResources().getColor(R.color.white))
mPTitleBarView.setSubTitleColor(getResources().getColor(R.color.t1))
StatusBarUtil.setStatusBlackFontAndBgColor(this, getResources().getColor(R.color.white))
}
var serverSocket: ServerSocket? = null
var run = true
inner class HttpServerThread : Runnable {
var TAG = javaClass.name
var context : Context?= null
constructor(context : Context){
this.context = context
}
override fun run() {
Log.i(TAG, "await start")
try {
//Android9.0以下开启了热点服务器的IP值是192.168.43.1,如果Android版本大于9.0 IP服务器地址会随机变
serverSocket = ServerSocket(SocketContants.HTTP_SERVER_PORT)
// serverSocket = ServerSocket(SocketContants.HTTP_SERVER_PORT, 10, InetAddress.
// ("192.168.43.1"))
} catch (e: IOException) {
Log.i(TAG, "has error")
e.printStackTrace()
}
if (serverSocket == null) {
Log.i(TAG, "serverSocket == null")
return;
}
while (run) {
Log.i(TAG, "while (true) start")
var socket: Socket? = null
var input: InputStream? = null
var output: OutputStream? = null
try { //接收了客户端发来的请求,否则一致是等待状态
Log.i(TAG, "serverSocket.accept() start")
socket = serverSocket!!.accept()
Log.i(TAG, "serverSocket.accept() after")
input = socket.getInputStream()
output = socket.getOutputStream()
// create Request object and parse
val request = Request(input)
request.parse() //从请求中读取内容
Log.i(TAG, "shutdown.req=" + request.uri)
val response = Response(output, context)
response.setRequest(request)
response.sendDataToClient()
socket.close()
} catch (e: Exception) {
e.printStackTrace()
Log.i(TAG, "Exception has error ")
}
}
}
}
override fun onDestroy() {
super.onDestroy()
closeWifiApLoading()
if (handler != null && counter != null) {
handler!!.removeCallbacks(counter)
}
//关闭socket
if (serverSocket != null) {
Log.i(TAG, "serverSocket != null and close")
serverSocket!!.close()
}
run = false
//关闭8.0以上的热点
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
if (reserva != null){
reserva!!.close();
}
} else {
//关闭7.1热点的关闭
WifiApUtil.closeWifiAp(this);
}
//打开wifi
if (isNeedOpenWifi) {
var result = wifiApAdmin!!.openWifi()
Log.i(TAG, "result is :" + result);
}
}
var reserva:WifiManager.LocalOnlyHotspotReservation? = null
/**
* 申请ACCESS_FINE_LOCATION权限
*/
fun requestLocationPermission() {
val rxPermissions = RxPermissions(this)
rxPermissions.request(
Manifest.permission.ACCESS_FINE_LOCATION
).subscribe { aBoolean ->
Log.i(TAG, "ACCESS_FINE_LOCATION aBoolean isL" + aBoolean);
if (aBoolean) { //申请的权限全部允许
Log.i(TAG, "申请ACCESS_FINE_LOCATION权限 success");
var result = GpsUtil.isOPen(this)
Log.i(TAG, "result is:" + result)
if (!result) {
openGPSDialog()
} else {
//有了这2个权限,就可以正常开启热点,接下来开启热点
initWifiApGreaterThanEight(this)
}
} else { //只要有一个权限被拒绝,就会执行
Log.i(TAG, "ACCESS_FINE_LOCATION do not have");
//text_no_permisson
ToastUtils.showShort(R.string.text_please_allow_permisson)
finish()
}
}
}
/**
* 初始化WiFi权限
*/
fun initWifiPermisson() {
//8.0以上的版本需要申请位置权限和GPS服务
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//先需要申请Manifest.permission.ACCESS_FINE_LOCATION权限
requestLocationPermission()
//7.1版本需要单独处理
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1){
openWifiApManual()
//7.1以下版本初始化
} else {
//7.1以下版本用用户名作为WiFi热点名字,
var wifiName = SPHelper.getInstance().getString(SpConstants.USER_NAME, Constants.DEFAULT_NAME)
setViewWifiApName(wifiName)
checkPermissionAndOpenWifiAP()
}
}
/**
* 开启热点失败提示
*/
fun openWifiAPFail() {
ToastUtils.showShort(R.string.text_open_wifi_ap_fail)
finish()
}
/**
* 开启Android8.0版本手机以上的热点,热点名字和密码都是随机的。
*/
fun initWifiApGreaterThanEight(context: Context) {
var isCreatedWifiAp = WifiApUtil.checkWife()
Log.i(TAG, "isCreatedWifiAp is:" + isCreatedWifiAp)
if (isCreatedWifiAp) {
ToastUtils.showShort(R.string.text_please_close_wifiAp)
isNeedOpenWifi = false
finish()
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
showCreateWifiApLoading()
var wifiManager:WifiManager = getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager
try {
wifiManager.startLocalOnlyHotspot(object : WifiManager.LocalOnlyHotspotCallback(){
override fun onStarted(reservation: WifiManager.LocalOnlyHotspotReservation?) {
super.onStarted(reservation)
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onStarted");
reserva = reservation
var wifiConfiguration = reservation!!.wifiConfiguration
var ssid = wifiConfiguration.SSID;
var password = wifiConfiguration.preSharedKey
Log.i(TAG, "ssid is:" + ssid + "password is:" + password);
//创建成功,然后开辟线程,启动服务
Thread(HttpServerThread(context)).start()
setViewWifiApName(ssid)
setViewWifiApPassword(password)
closeWifiApLoading()
// connectWifiQRCode(ssid, password);
}
override fun onStopped() {
super.onStopped()
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onStopped");
}
override fun onFailed(reason: Int) {
super.onFailed(reason)
Log.i(TAG, "uild.VERSION.SDK_INT >= Build.VERSION_CODES.O initWifiAp onFailed and reason isL" + reason);
openWifiAPFail()
}
}, handler)
} catch (e: Exception) {
e.printStackTrace();
Log.i(TAG, "open wifi Ap fail")
openWifiAPFail()
}
}
}
/**
* 需要打开GPS的对话框
*/
fun openGPSDialog() {
var notice = getString(R.string.text_need_gps_permisson)
openGpsDialog = ShareCommonDialog(notice, { openGPS() }, {cancelOpenGPS()})
openGpsDialog!!.show(supportFragmentManager, TAG)
}
/**
* 跳转打开GPS页面
*/
fun openGPS() {
var intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivityForResult(intent, REQUEST_GPS_CODE)
}
/**
* 7.1版本需要手动开启热点
*/
fun openWifiApManual() {
var notice = getString(R.string.text_do_not_support_wifiAp)
opeWifiDialog = ShareCommonDialog(notice, { gotoOpenWifiPage() }, {cancelGotoSetWifiPage()})
opeWifiDialog!!.show(supportFragmentManager, TAG)
}
/**
* 跳转手动设置wifi热点页面
*/
fun gotoOpenWifiPage() {
var intent = Intent();
intent.setAction(Intent.ACTION_MAIN);
var com = ComponentName("com.android.settings", "com.android.settings.TetherSettings");
intent.setComponent(com);
startActivityForResult(intent, REQUEST_SYSTEM_WIFIAP_PAGE_CODE);
}
/**
* 取消跳转打开GPS页面
*/
fun cancelOpenGPS() {
ToastUtils.showShort(R.string.text_please_allow_gos_permisson)
finish()
}
/**
*
*/
fun cancelGotoSetWifiPage() {
ToastUtils.showShort(R.string.text_please_allow_goto_setwifap_page)
finish()
}
/**
* 设置wif二维码图片
*/
fun connectWifiQRCode(wifiName: String, password: String) {
var content = ""
if (TextUtils.isEmpty(password)) {
content = wifiName
} else {
content = wifiName + "&&" + password
}
var bitmap = QRCodeUtil.createQRCodeBitmap(content, 500, 500,"UTF-8","H", "1", Color.BLACK, Color.WHITE);
iv_share_qr_code.setImageBitmap(bitmap);
}
/**
* 得到wifi配置并且设置用户名或者密码页面显示
*/
fun getWiFiAPConfig():Boolean {
try {
var wifiManager = getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager
var method = wifiManager.javaClass.getMethod("getWifiApConfiguration")
var apConfig = method.invoke(wifiManager) as WifiConfiguration
if (apConfig == null) {
ToastUtils.showShort(R.string.text_do_not_setwifap)
//gotoOpenWifiPage()
return false;
}
var type = WifiApUtil.getSecurity(apConfig);
if (type != WifiApUtil.SECURITY_NONE) {
type = WifiApUtil.SECURITY_EAP
}
var wifiName = apConfig.SSID
if (type == WifiApUtil.SECURITY_NONE) {
setViewWifiApName(wifiName)
} else {
setViewWifiApName(wifiName)
setViewWifiApPassword(apConfig.preSharedKey)
}
return true;
} catch (e: NoSuchMethodException) {
e.printStackTrace()
Log.i(TAG, "NoSuchMethodException");
return false;
} catch (e: IllegalAccessException) {
e.printStackTrace()
Log.i(TAG, "IllegalAccessException");
return false;
} catch (e: InvocationTargetException) {
e.printStackTrace()
Log.i(TAG, "InvocationTargetException");
return false;
}
}
}
辅助类 WifiApUtil.java
package com.appsinnova.android.keepshare.util;
/**
* Created by mmsx
*/
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import com.appsinnova.android.keepshare.socket.HttpServer;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import static android.content.Context.WIFI_SERVICE;
import static com.facebook.FacebookSdk.getApplicationContext;
/**
* 创建热点
*/
public class WifiApUtil {
public static final String TAG = "WifiApAdmin";
public static final int SECURITY_NONE = 0;
public static final int SECURITY_WEP = 1;
public static final int SECURITY_PSK = 2;
public static final int SECURITY_EAP = 3;
public static void closeWifiAp(Context context) {
WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
closeWifiAp(wifiManager);
}
public void haddd() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
handler.removeCallbacks(this);
}
}, 1000);
}
/**
* 打开热点并且创建WiFi热点的方法7.1以下
* @param context 外部上下文
* @param ssid 要创建WiFi热点的账号名称
* @param password 要创建WiFi热点的密码
* 注意,此方法直接使用WPA2_PSK 的安全策略创建WiFi热点,低版本的Android系统如果需要使用请切换。
*/
public boolean openWiFiAP(String ssid, String password){
if (mWifiManager.isWifiEnabled()) {
//如果wifi处于打开状态,则关闭wifi,
mWifiManager.setWifiEnabled(false);
}
WifiConfiguration config = new WifiConfiguration();
config.SSID = ssid;
config.preSharedKey = password;
config.hiddenSSID = false;//是否隐藏热点true=隐藏
config.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.OPEN);//开放系统认证
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
int indexOfWPA2_PSK = 4;
//从WifiConfiguration.KeyMgmt数组中查找WPA2_PSK的值
for (int i = 0; i < WifiConfiguration.KeyMgmt.strings.length; i++)
{
if(WifiConfiguration.KeyMgmt.strings[i].equals("WPA2_PSK"))
{
indexOfWPA2_PSK = i;
break;
}
}
//WifiConfiguration.KeyMgmt.WPA_PSK
// config.allowedKeyManagement.set(indexOfWPA2_PSK);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
//通过反射调用设置热点
try {
Method method = mWifiManager.getClass().getMethod(
"setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
boolean enable = (Boolean) method.invoke(mWifiManager, config, true);
if (enable) {
Log.i("WiFiAP", "热点已开启 SSID:" + ssid + " Password:"+password);
return true;
} else {
Log.e("WiFiAP", "创建热点失败");
return false;
}
} catch (Exception e) {
e.printStackTrace();
Log.e("WiFiAP", "创建热点失败"+e);
return false;
}
}
/**
* 8.0以上,但是9.0测试失败,提示找不到startTethering这个方法
* @param isEnable
*/
public void start(boolean isEnable) {
ConnectivityManager connManager = (ConnectivityManager) mContext.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);
Log.i(TAG, "start success");
} else { //关闭
Log.i(TAG, "close");
Method startTethering = iConnMgrClass.getMethod("stopTethering", int.class);
startTethering.invoke(iConnMgr, 0);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
Log.i(TAG, "has error1");
} catch (NoSuchMethodException e) {
e.printStackTrace();
Log.i(TAG, "has error2");
} catch (IllegalAccessException e) {
e.printStackTrace();
Log.i(TAG, "has error3");
} catch (InvocationTargetException e) {
e.printStackTrace();
Log.i(TAG, "has error4");
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.i(TAG, "has error5");
}
}
public ConnectivityManager mConnectivityManager;
/**
* Android8.0以上,我用9.0测试,提示找不到这个方法setWifiApConfiguration
* @return
*/
public boolean startTethering() {
mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
if (mWifiManager != null) {
int wifiState = mWifiManager.getWifiState();
boolean isWifiEnabled = ((wifiState == WifiManager.WIFI_STATE_ENABLED) || (wifiState == WifiManager.WIFI_STATE_ENABLING));
if (isWifiEnabled)
mWifiManager.setWifiEnabled(false);
}
if (mConnectivityManager != null) {
try {
Field internalConnectivityManagerField = ConnectivityManager.class.getDeclaredField("mService");
internalConnectivityManagerField.setAccessible(true);
WifiConfiguration apConfig = new WifiConfiguration();
apConfig.SSID = "cuieney";
apConfig.preSharedKey = "12121212";
StringBuffer sb = new StringBuffer();
Class internalConnectivityManagerClass = Class.forName("android.net.IConnectivityManager");
ResultReceiver dummyResultReceiver = new ResultReceiver(null);
try {
WifiManager wifiManager = (WifiManager) mContext.getSystemService(WIFI_SERVICE);
Method mMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
mMethod.invoke(wifiManager, apConfig);
Method startTetheringMethod = internalConnectivityManagerClass.getDeclaredMethod("startTethering",
int.class,
ResultReceiver.class,
boolean.class);
startTetheringMethod.invoke(internalConnectivityManagerClass,
0,
dummyResultReceiver,
true);
Log.i(TAG, "successs");
return true;
} catch (NoSuchMethodException e) {
@SuppressLint("SoonBlockedPrivateApi") Method startTetheringMethod = internalConnectivityManagerClass.getDeclaredMethod("startTethering",
int.class,
ResultReceiver.class,
boolean.class,
String.class);
startTetheringMethod.invoke(internalConnectivityManagerClass,
0,
dummyResultReceiver,
false,
mContext.getPackageName());
Log.e(TAG, "NoSuchMethodException has error" + Log.getStackTraceString(e));
return false;
} catch (InvocationTargetException e) {
sb.append(11 + (e.getMessage()));
e.printStackTrace();
Log.e(TAG, "has error" + Log.getStackTraceString(e));
Log.e(TAG, "sb.toString() is: " + sb.toString());
return false;
} finally {
Log.e(TAG, "sb.toString() isL" + sb.toString());
}
} catch (Exception e) {
Log.e(TAG, "has error" + Log.getStackTraceString(e));
return false;
}
} else {
Log.i(TAG, "mConnectivityManager == null");
return false;
}
}
public boolean openWifi() {
if (mWifiManager != null) {
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
return true;
}
} else {
return false;
}
return true;
}
public boolean createAp(boolean isOpen) {
StringBuffer sb = new StringBuffer();
try {
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
sb.append(1);
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = "xiaomeng";
netConfig.preSharedKey = "11111111";
Log.d("oye", "WifiPresenter:createAp----->netConfig.SSID:"
+ netConfig.SSID + ",netConfig.preSharedKey:" + netConfig.preSharedKey + ",isOpen=" + isOpen);
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
sb.append(2);
if (isOpen) {
netConfig.allowedKeyManagement.set(4);
sb.append(3);
} else {
netConfig.allowedKeyManagement.set(4);
sb.append(4);
}
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
sb.append(5);
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
sb.append(9);
return (boolean) method.invoke(mWifiManager, netConfig, true);
} catch (NoSuchMethodException e) {
sb.append(10 + (e.getMessage()));
e.printStackTrace();
} catch (InvocationTargetException e) {
sb.append(11 + (e.getMessage()));
e.printStackTrace();
} catch (IllegalAccessException e) {
sb.append(12 + (e.getMessage()));
e.printStackTrace();
}
return false;
}
public static WifiManager mWifiManager = null;
private Context mContext = null;
public WifiApUtil(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(WIFI_SERVICE);
closeWifiAp(mWifiManager);
}
private String mSSID = "";
private String mPasswd = "";
public void startWifiAp(String ssid, String passwd) {
mSSID = ssid;
mPasswd = passwd;
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
// stratWifiAp();
// startTethering();
openWIFI(mSSID, mPasswd);
MyTimerCheck timerCheck = new MyTimerCheck() {
@Override
public void doTimerCheckWork() {
// TODO Auto-generated method stub
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
} else {
//小于8.0才这样操作
if (isWifiApEnabled(mWifiManager)) {
Log.i(TAG, "Wifi enabled success!");
this.exit();
} else {
Log.i(TAG, "Wifi enabled failed!");
}
}
}
@Override
public void doTimeOutWork() {
// TODO Auto-generated method stub
this.exit();
}
};
timerCheck.start(15, 1000);
}
public static int getSecurity(WifiConfiguration config) {
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
return SECURITY_PSK;
}
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
return SECURITY_EAP;
}
return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
}
public static boolean checkWife() {
if (mWifiManager == null)
return false;
return isWifiApEnabled(mWifiManager);
}
public void stratWifiAp() {
Method method1 = null;
try {
method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = mSSID;
netConfig.preSharedKey = mPasswd;
netConfig.status = WifiConfiguration.Status.ENABLED;
netConfig.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
netConfig.allowedKeyManagement
.set(WifiConfiguration.KeyMgmt.WPA_PSK);
netConfig.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.TKIP);
//6.0以上手机需要设置权限WRITE_SETTINGS 动态返回
method1.invoke(mWifiManager, netConfig, true);
Log.i(TAG, "open success");
} catch (IllegalArgumentException e) {
Log.i(TAG, "open fail");
e.printStackTrace();
} catch (IllegalAccessException e) {
Log.i(TAG, "open fail");
e.printStackTrace();
} catch (InvocationTargetException e) {
Log.i(TAG, "open fail");
Log.i("Show", e.toString());
e.printStackTrace();
} catch (SecurityException e) {
Log.i(TAG, "open fail");
e.printStackTrace();
} catch (NoSuchMethodException e) {
Log.i(TAG, "open fail");
e.printStackTrace();
}
}
private static void closeWifiAp(WifiManager wifiManager) {
if (isWifiApEnabled(wifiManager)) {
try {
Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
method.setAccessible(true);
WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method2.invoke(wifiManager, config, false);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} 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();
}
}
}
private static boolean isWifiApEnabled(WifiManager wifiManager) {
try {
Method method = wifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (Boolean) method.invoke(wifiManager);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public abstract class MyTimerCheck {
private int mCount = 0;
private int mTimeOutCount = 1;
private int mSleepTime = 1000; // 1s
private boolean mExitFlag = false;
private Thread mThread = null;
/**
* Do not process UI work in this.
*/
public abstract void doTimerCheckWork();
public abstract void doTimeOutWork();
public MyTimerCheck() {
mThread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (!mExitFlag) {
mCount++;
if (mCount < mTimeOutCount) {
doTimerCheckWork();
try {
mThread.sleep(mSleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exit();
}
} else {
doTimeOutWork();
}
}
}
});
}
/**
* start
* @param times How many times will check?
* @param sleepTime ms, Every check sleep time.
*/
public void start(int timeOutCount, int sleepTime) {
mTimeOutCount = timeOutCount;
mSleepTime = sleepTime;
mThread.start();
}
public void exit() {
mExitFlag = true;
}
}
/**
* android 8.0 open直接调用系统提供的Api 但是不稳定 不靠谱(而且热点的名称和密码都是随机的)
* @param context
* @param enable
*/
public void setApEnable(boolean enable) {
try {
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
if (wifiManager == null) {
return;
}
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 如果是Android 8.0系统
if (enable) {
// 打开热点
wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Log.d(TAG, "onStarted: ");
//可以通过config拿到开启热点的账号和密码
WifiConfiguration wifiConfiguration = reservation.getWifiConfiguration();
String ssid = wifiConfiguration.SSID;
String password = wifiConfiguration.preSharedKey;
Log.i(TAG, "ssid is:" + ssid);
Log.i(TAG, "password is:" + password);
}
@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());
} else {
// 关闭热点
@SuppressLint("SoonBlockedPrivateApi") Method method = wifiManager.getClass().getDeclaredMethod("stopSoftAp");
method.invoke(wifiManager);
}
} else {
Method method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
method.invoke(wifiManager, null, enable);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
// /**
// * 打开热点
// *
// * @param context 上下文
// * @param SSID 名称
// * @param password 密码
// * @param securityType 加密类型
// * @param band WIFI_FREQUENCY_BAND_5GHZ WIFI_FREQUENCY_BAND_2GHZ
// * @return 开启状态
// */
// private static final int WIFI_AP_2_4G_CHANNEL = 9;//2.4G热点信道
// private static final int WIFI_AP_5G_CHANNEL = 149;//5G热点信道
// public static boolean configAp(Context context, String SSID, String password, int securityType, int band) {
// if (TextUtils.isEmpty(SSID)) {
// return false;
// }
// WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
// if (wifiManager != null && wifiManager.isWifiEnabled()) {
// wifiManager.setWifiEnabled(false);
// }
// WifiConfiguration apConfig = new WifiConfiguration();
// apConfig.SSID = "cuieney";
// apConfig.preSharedKey = "12121212";
//
// Method method = null;
// Field field = null;
// try {
// method = wifiManager.getClass().getMethod("isDualBandSupported");
// //判断是否支持5G
// boolean isDualBandSupported = (boolean) method.invoke(wifiManager);
// LogUtils.i(TAG, "=====isDualBandSupported = " + isDualBandSupported + "====");
// if (isDualBandSupported && band == 1) {
// field = wifiCfg.getClass().getField("apBand");
// field.setInt(wifiCfg, 1);
// field = wifiCfg.getClass().getField("apChannel");
// field.setInt(wifiCfg, WIFI_AP_5G_CHANNEL);
// } else {
// field = wifiCfg.getClass().getField("apBand");
// field.setInt(wifiCfg, 0);
// field = wifiCfg.getClass().getField("apChannel");
// field.setInt(wifiCfg, WIFI_AP_2_4G_CHANNEL);
// }
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Method configMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
// boolean isConfigured = (Boolean) configMethod.invoke(wifiManager, wifiCfg);
// method = wifiManager.getClass().getMethod("startSoftAp", WifiConfiguration.class);
// //返回热点打开状态
// return (Boolean) method.invoke(wifiManager, wifiCfg);
// } else {
// method = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
// method.invoke(wifiManager, wifiCfg, true);
// return true;
// }
// } catch (NoSuchMethodException | NoSuchFieldException | InvocationTargetException | IllegalAccessException e) {
// e.printStackTrace();
// LogUtils.i(TAG, "=====Exception==" + e.getMessage());
// }
// return false;
// }
public void openWIFI(String name, String password) {
Log.i(TAG, "Build.VERSION.SDK_INT is" + Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// setApEnable(true);
} else {
//这是7.0版本,还需要研究7.1版本 8.0版本和9.0版本
openWiFiAP(name, password);
}
}
/**
* 打开系统的便携式热点界面 针对7.1版本
*/
private void openAP() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
ComponentName com = new ComponentName("com.android.settings", "com.android.settings.TetherSettings");
intent.setComponent(com);
// mContext.startActivityForResult(intent, 1000);
}
public static final int WIFICIPHER_NOPASS = 1;
public static final int WIFICIPHER_WEP = 2;
public static final int WIFICIPHER_WPA = 3;
/**
* 创建WifiConfiguration配置
* @param ssid
* @param password
* @param type
* @return
*/
public static WifiConfiguration createWifiCfg(String ssid, String password, int type){
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + ssid + "\"";
if (type == WIFICIPHER_NOPASS){
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
} else if (type == WIFICIPHER_WEP){
config.hiddenSSID = true;
config.wepKeys[0]= "\""+password+"\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
}else if(type == WIFICIPHER_WPA){// WPA/WPA2 PSK的加密方式都可以通过此方法连上热点 也就是说我们连接热点只用分为有密码和无密码情况
config.preSharedKey = "\""+password+"\"";
config.hiddenSSID = true;
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
}
return config;
}
/*连接到热点*/
public boolean connectToHotpot(WifiConfiguration wifiConfig){
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
int wcgID = wifiManager.addNetwork(wifiConfig);
boolean flag=wifiManager.enableNetwork(wcgID, true);
System.out.println("connect success? "+flag);
return flag;
}
/**
* 8.0 开启wifi热点方法
* @param apName wifi热点帐号
* @param apPassword wifi热点密码
*/
public boolean setWifiAp(String apName, String apPassword) {
Method method;
try {
//热点的配置类
WifiConfiguration apConfig = new WifiConfiguration();
//配置热点的名称(可以在名字后面加点随机数什么的)
apConfig.SSID = apName;
apConfig.preSharedKey = apPassword;
//不设置密码
apConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
//android 8.0开启wifi热点
if (Build.VERSION.SDK_INT >= 26) {
Method configMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
boolean isConfigured = (Boolean) configMethod.invoke(mWifiManager, apConfig);
method = mWifiManager.getClass().getMethod("startSoftAp", WifiConfiguration.class);
//返回热点打开状态
return (Boolean) method.invoke(mWifiManager, apConfig);
} else {
//通过反射调用设置热点
method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
//返回热点打开状态
return (Boolean) method.invoke(mWifiManager, apConfig, true);
}
} catch (NoSuchMethodException e) {
e.getMessage();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
} catch (InvocationTargetException e) {
e.printStackTrace();
return false;
}
}
/**
* 关闭wifi 热点
* @return
*/
public boolean closeWifiAp() {
//热点的配置类
Method method;
WifiConfiguration apConfig = new WifiConfiguration();
try {
//android 8.0关闭wifi热点
if (Build.VERSION.SDK_INT >= 26) {
method = mWifiManager.getClass().getDeclaredMethod("stopSoftAp");
return (Boolean) method.invoke(mWifiManager);
} else {
method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
//返回热点关闭状态
return (Boolean) method.invoke(mWifiManager, apConfig, false);
}
} catch (Exception e) {
e.getMessage();
return false;
}
}
/**
* 打开移动网络
* @param context
* @param enabled 是否打开
*/
public void setMobileDataState(Context context, boolean enabled) {
TelephonyManager telephonyService = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Method setDataEnabled = telephonyService.getClass().getDeclaredMethod("setDataEnabled",boolean.class);
if (null != setDataEnabled) {
setDataEnabled.invoke(telephonyService, enabled);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// private String getIpAddress() {
// IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
// INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
//
// InterfaceConfiguration ifcg = null;
// String address = null;
// try {
// ifcg = service.getInterfaceConfig("wlan0");
// if (ifcg != null) {
// LinkAddress linkAddr = ifcg.getLinkAddress();
// Log.d("test" , "linkAddr" + linkAddr.toString());
// if (linkAddr != null) {
// InetAddress Inetaddr = linkAddr.getAddress();
// Log.d("test" , "Inetaddr" + Inetaddr.toString());
// if (Inetaddr != null) {
// address = Inetaddr.getHostAddress();
// if (address != null) {
// Log.d("test" , "address " + address.toString());
// }
// }
// }
// }
// } catch (Exception e) {
// Log.e("test", "Error configuring interface :" + e);
// return null;
// }
// return address;
// }
}