在看这一篇文章之前,读者先得知道安卓系统中:
(1)、在开启wifi的情况下必须先关闭wifi才能开启热点。
(2)、热点可以没有密码,即加密方式为open,如果有密码,并且采用WPA—PSK的加密模式,密码长度至少为八位数。
下面进入正题,首先,在manifest中添加用户权限,因为要操作热点和变更wifi状态。
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
紧接着,新建一个热点管理的类,源代码如下:
public class WifiApConnector { private static final String SETUP_WIFIAP_METHOD = "setWifiApEnabled"; private static final String TAG="wifi_test"; Context context = null; WifiManager wifiManager = null; static WifiApConnector wifiApConnector = null; public static WifiApConnector getInstance(Context context) { if (wifiApConnector == null) { wifiApConnector = new WifiApConnector(); wifiApConnector.context = context.getApplicationContext(); wifiApConnector.wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); } return wifiApConnector; } public void setupWifiAp(String name, String password) throws Exception { if (wifiManager.isWifiEnabled()) { Log.i(TAG,"手机wifi开启了"+wifiManager.isWifiEnabled()); wifiManager.setWifiEnabled(false); Log.i(TAG,"手机wifi被强行"); if (name == null || "".equals(name)) { throw new Exception("the name of the wifiap is cannot be null"); } else{ stratWifiAp(name, password); Log.i(TAG,"手机关闭wifi之后成功调用startwifiap方法"); } } if (!wifiManager.isWifiEnabled()) { Log.i(TAG,"手机wifi未开启"+wifiManager.isWifiEnabled()); if (name == null || "".equals(name)) { throw new Exception("the name of the wifiap is cannot be null"); }else{ stratWifiAp(name, password); Log.i(TAG,"手机不需要关闭wifi之后热点创建成功"); } } } private void stratWifiAp(String name, String password) { Method method1 = null; try { method1 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); WifiConfiguration netConfig = new WifiConfiguration(); netConfig.SSID = name; netConfig.preSharedKey = password; 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(wifiManager, netConfig, true); Log.i(TAG,"成功启动start方法创建wifi热点"); } 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(); } } public boolean isWifiApEnabled() { try { Method method = wifiManager.getClass().getMethod("isWifiApEnabled"); method.setAccessible(true); return (Boolean) method.invoke(wifiManager); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return true; } public void closeWifiAp() { WifiManager wifiManager = (WifiManager) context.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(); } } } }
Context context = null; WifiManager wifiManager = null; static WifiApConnector wifiApConnector = null;关于contex的意义,在上一篇文章中已经指出,这里先实例化一个WifiManager,同时还实例化出一个本类的对象wifiApconector。
public boolean isWifiApEnabled() { }此方法用于判定当前系统wifi是否打开,若打开,则返回true,若没有打开,则返回false。
public void setupWifiAp(String name, String password) throws Exception { }在设置热点的方法中,首先对当前wifi状态进行判定,若wifi打开,则关闭wifi,执行start方法,若没有打开,则直接执行。
private void stratWifiAp(String name, String password) { }启动wifi的方法,设置用户名、密码,并且捕获异常。
public void closeWifiAp() { }关闭热点的方法,若重新设置了名称或者密码,需要先关闭热点,再重新开启。
public class MainActivity extends Activity { public static final String TAG = "wifi_test"; @SuppressLint("ShowToast") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final WifiApConnector ApConnector = WifiApConnector.getInstance(this); final EditText apName=(EditText)this.findViewById(R.id.wifiap_name); final EditText apPassWord=(EditText)this.findViewById(R.id.wifiap_password); Button setup_btn=(Button)this.findViewById(R.id.setup_wifiap_btn); Button close_btn=(Button)this.findViewById(R.id.close_wifiap_btn); setup_btn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ShowToast") @Override public void onClick(View v) { final String ap_name=apName.getText().toString(); Log.i(TAG,"wifi_test"+ap_name); final String ap_password=apPassWord.getText().toString(); Log.i(TAG,"wifi_test"+ap_password); if (ap_name!=null && ap_password!=null&&(!"".equals(ap_name))&&(!"".equals(ap_password))){ try { ApConnector.setupWifiAp(ap_name,ap_password); Toast.makeText(getApplicationContext(), "热点已经创建 ", 1).show(); } catch (Exception e) { } Log.i(TAG,"wifi_test"+ap_password); } if (ap_name==null||"".equals(ap_name)||ap_password==null||"".equals(ap_password)){ Toast.makeText(getApplicationContext(), "请正确输入ssid和密码 ", 1).show(); Log.i(TAG,"请正确输入ssid和密码"); } } }); close_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ApConnector.closeWifiAp(); Toast.makeText(getApplicationContext(), "热点已经关闭", 1).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }在开启热点之前,先要对输入框的内容进行判断,若用户名和密码有一个为空,则提示正确输入,若都不为空,则判定密码是否满足八位数,并且传入相应的参数。
若要建立没有密码的热点,可以根据多态的性能,重写一个start方法,并且只传入name参数。
如下为布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/wifiap_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginTop="28dp" android:ems="10" > </EditText> <!-- android:hint="请输入SSID" --> <EditText android:id="@+id/wifiap_password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/wifiap_name" android:layout_below="@+id/wifiap_name" android:ems="10" android:inputType="textPassword" /> <!-- android:hint="请输入 密码" --> <Button android:id="@+id/setup_wifiap_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/wifiap_password" android:layout_marginTop="20dp" android:text="开启热点" /> <Button android:id="@+id/close_wifiap_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/setup_wifiap_btn" android:layout_alignBottom="@+id/setup_wifiap_btn" android:layout_alignRight="@+id/wifiap_name" android:text="关闭热点" /> </RelativeLayout>