用过360的面对面快传,快牙的朋友应该都知道,它们在两台设备间实现文件传输都是通过WiFi热点实现的,下面我们就来探讨一下如何设置热点名和密码,并自动创建一个wifi热点吧,以及如何监听热点的打开与关闭。
一、创建WiFi热点
其实创建热点很简单,先获取到wifi的服务,再配置热点名称、密码等等,然后再通过反射打开它就OK了,需要注意的是手机的WiFi连接与热点是不可同时打开的,也就是说如果手机连上了一个现有WiFi,就无法打开自身热点,反之亦然。所以在打开热点是先判断WiFi是否打开,如果打开则先关闭WiFi,然后再根据设定的热点名和密码创建热点。废话少说,直接上代码:
package com.wjj.wifihotmanager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
/**
* @ClassName: WifiHotUtil
* @Description: 打印日志信息WiFi热点工具
* @author: jajuan.wang
* @date: 2015-05-28 15:12
* version:1.0.0
*/
public class WifiHotUtil {
public static final String TAG = "WifiApAdmin";
private WifiManager mWifiManager = null;
private Context mContext = null;
public WifiHotUtil(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
}
public void startWifiAp(String ssid, String passwd)
{
//wifi和热点不能同时打开,所以打开热点的时候需要关闭wifi
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
if (!isWifiApEnabled()) {
stratWifiAp(ssid, passwd);
}
}
/**
* 设置热点名称及密码,并创建热点
* @param mSSID
* @param mPasswd
*/
private void stratWifiAp(String mSSID, String mPasswd) {
Method method1 = null;
try {
//通过反射机制打开热点
method1 = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = mSSID;
netConfig.preSharedKey = mPasswd;
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);
method1.invoke(mWifiManager, netConfig, true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* 热点开关是否打开
* @return
*/
public boolean isWifiApEnabled() {
try {
Method method = mWifiManager.getClass().getMethod("isWifiApEnabled");
method.setAccessible(true);
return (Boolean) method.invoke(mWifiManager);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 关闭WiFi热点
*/
public void closeWifiAp() {
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
if (isWifiApEnabled()) {
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) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
调用方式:在activity中:
//实例化WiFi热点工具类
wifiHotUtil = new WifiHotUtil(this);
//创建热点
wifiHotUtil.startWifiAp(defaultHotName, defaultHotPwd);
//关闭热点
wifiHotUtil.closeWifiAp();
二、监听热点的打开与关闭
经过查找资料发现,android的便携式热点打开与关闭都会发出 android.net.wifi.WIFI_AP_STATE_CHANGED 的广播,但是便携式热点相关的信息在WiFimanage中是隐藏的,这个广播是隐藏的。那我们怎么监听呢?好不容易在stackoverflow上找到了解决办法,连接地址:Monitoring the Hotspot state in Android,实现代码如下:
private BroadcastReceiver wifiReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(action)) {
//便携式热点的状态为:10---正在关闭;11---已关闭;12---正在开启;13---已开启
int state = intent.getIntExtra("wifi_state", 0);
Log.i(TAG, "state= "+state);
wiFiAPObserver.stateChanged(state);
}
}
};
注册这个广播监听器,就可以监听热点的打开与关闭状态了。
我使用的是服务+观察者模式,应用启动时启动热点监听服务,用于监听热点打开与关闭的状态。activity或其他需要获取热点状态的地方可以通过服务注册监听器,当热点状态改变时会遍历通知每个注册的实例。上代码:
package com.wjj.wifihotmanager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
/**
* @ClassName: WiFiAPService
* @Description: wifi hot manage service
* @author: jajuan.wang
* @date: 2015-06-09 00:43
* version:1.0.0
*/
public class WiFiAPService extends Service {
private static String TAG = "WiFiAPService";
public static String ACTION_START_SERVICE = "action_start_service";
public static String ACTION_STOP_SERVICE = "action_stop_service";
private static WiFiAPObserver wiFiAPObserver = new WiFiAPObserver();
/**
* static method to start service
* @param context
*/
public static void startService(Context context) {
Intent intent = new Intent(context, WiFiAPService.class);
intent.setAction(ACTION_START_SERVICE);
context.startService(intent);
}
/**
* static method to stop service
* @param context
*/
public static void stopService(Context context) {
Intent intent = new Intent(context, WiFiAPService.class);
intent.setAction(ACTION_STOP_SERVICE);
context.startService(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.i(TAG, "intent.getAction()="+intent.getAction());
// option based on action
if (intent.getAction().equals(ACTION_START_SERVICE) == true) {
//startService();
} else if (intent.getAction().equals(ACTION_STOP_SERVICE) == true) {
stopSelf();
}
//重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
return Service.START_REDELIVER_INTENT;
}
@Override
public void onCreate() {
registerReceiver(wifiReceiver,new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED"));
super.onCreate();
}
@Override
public void onDestroy() {
unregisterReceiver(wifiReceiver);
wiFiAPObserver.clearWiFiAPListener();
super.onDestroy();
}
/**
* register wiFiAPListener
* @param wiFiAPListener
*/
public static void addWiFiAPListener(WiFiAPListener wiFiAPListener) {
wiFiAPObserver.addWiFiAPListener(wiFiAPListener);
}
/**
* remove wiFiAPListener
* @param wiFiAPListener
*/
public static void removeWiFiAPListener(WiFiAPListener wiFiAPListener) {
wiFiAPObserver.removeWiFiAPListener(wiFiAPListener);
}
private BroadcastReceiver wifiReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(action)) {
//便携式热点的状态为:10---正在关闭;11---已关闭;12---正在开启;13---已开启
int state = intent.getIntExtra("wifi_state", 0);
Log.i(TAG, "state= "+state);
wiFiAPObserver.stateChanged(state);
}
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
热点监听器:
package com.wjj.wifihotmanager;
/**
* @ClassName: WiFiAPListener
* @Description: Listenning the state of wifi hot
* @author: jajuan.wang
* @date: 2015-06-09 00:52
* version:1.0.0
*/
public interface WiFiAPListener {
public static final int WIFI_AP_CLOSEING = 10; //wifi hot is closeing
public static final int WIFI_AP_CLOSE_SUCCESS = 11; //wifi hot close success
public static final int WIFI_AP_OPENING = 12; //WiFi hot is opening
public static final int WIFI_AP_OPEN_SUCCESS = 13; //WiFi hot open success
/**
* the state of wifi hot changed
* @param state
*/
public void stateChanged(int state) ;
}
热点状态观察者:
package com.wjj.wifihotmanager;
import java.util.HashSet;
/**
* @ClassName: WiFiAPObserver
* @Description: Listenning the state of wifi hot
* @author: jajuan.wang
* @date: 2015-06-09 00:58
* version:1.0.0
*/
public class WiFiAPObserver implements WiFiAPListener {
/**
* the set to save all registed listener
*/
private HashSet<WiFiAPListener> listenerSet = new HashSet<WiFiAPListener>();
/**
* add wiFiAPListener
* @param wiFiAPListener
*/
public void addWiFiAPListener(WiFiAPListener wiFiAPListener) {
if (!listenerSet.contains(wiFiAPListener)) {
listenerSet.add(wiFiAPListener);
}
}
/**
* remove the wiFiAPListener
* @param wiFiAPListener
*/
public void removeWiFiAPListener(WiFiAPListener wiFiAPListener) {
if (listenerSet.contains(wiFiAPListener)) {
listenerSet.remove(wiFiAPListener);
}
}
/**
* remove all WiFiAPListener
*/
public void clearWiFiAPListener() {
listenerSet.clear();
}
@Override
public void stateChanged(int state) {
//notify all Listener the state changed
for (WiFiAPListener wiFiAPListener : listenerSet) {
wiFiAPListener.stateChanged(state);
}
}
}