android6.0 wifi连接
来源:互联网 发布:如何把淘宝微信群做大 编辑:程序博客网 时间:2024/05/02 01:06
Android6.0Wifi连接过程基本和之前的版本一致,但是,在获取附近热点的时候,却出现了一些差别,这差别主要包括获取权限的方式发生了改变,以及getScanResults这个函数有点怪异的行为...
1.android6.0之前的版本获取附近的wifi热点
1.1打开和关闭wifi
setWifiEnabled(true/false);
1.2扫描附近热点
startScan();之后,接受WifiManager.SCAN_RESULTS_AVAILABLE_ACTION的广播会触发,在这个广播中调用getScanResults()方法可以获得一个List<ScanResult>,它里面的每一个条目就是一个可连接的热点。
1.3代码
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">public class MainActivity extends AppCompatActivity { WifiManager wifi; int size = 0; List<ScanResult> results; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); if (wifi.isWifiEnabled() == false) { Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show(); wifi.setWifiEnabled(true); Log.d("hello","wifi enabled"); } wifi.startScan(); registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context c, Intent intent) { results = wifi.getScanResults(); size = results.size(); for(int i=0;i<size;i++){ Log.d("hello",results.get(i).toString()); } } }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); }}</span>这样就可以打印出所有的可连接wifi信息。
总结来说第一步:setWifiEnabled(true);第二步:startScan();
2.android6.0获取wifi热点
然而同样的问题在android6.0中确实不可以的。原因有两个:
第一:没有权限
android6.0访问wifi新增了两个权限:
android6.0之前,这两个权限在AndroidMenifest文件中声明就可以了,但是android6.0中,又增加了运行时权限。运行是权限这里不多说,总之,这两个权限是要运行时获取的,在Menifest文件中声明是行不通的。当然,为了不那么麻烦,你可以把targetSdkVersion 改为23以下,这样就不存在运行时权限的问题了。如果你不想这么做,那么不妨试试android6.0的运行时权限:<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /></span>
首先,检查有没有该权限:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 111; private boolean checkPermission() { Log.d("hello","checkPermission"); List<String> permissionsList = new ArrayList<String>(); String[] permission = new String[2]; if (checkSelfPermission( Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { permission[0] = Manifest.permission.ACCESS_FINE_LOCATION; } if (checkSelfPermission( Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { permission[1] = Manifest.permission.ACCESS_COARSE_LOCATION; } if(permission[0] != null || permission[1] != null){ Log.d("hello","regist Permission"); requestPermissions(permission,REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); return false; } return true; }</span>这个方法中使用checkSelfPermisson方法检查有没有对应权限,最后使用requestPermissions方法请求运行时权限。这会导致界面弹出一个询问框,问你要不要允许什么什么权限。最终请求对导致一个回调方法被调用:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { Log.d("hello","onRequestPermissionsResult"); switch (requestCode) { case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: if (permissions.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED || (permissions.length == 2 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED)){ wifi.startScan(); Log.d("hello","permission allow"); Toast.makeText(this, "permission allow", Toast.LENGTH_LONG).show(); //list is still empty } else { // Permission Denied Toast.makeText(this, "permission deny", Toast.LENGTH_LONG).show(); Log.d("hello","permission deny"); } break; } }</span>在这个方法中你可以知道你是不是获得了对应的权限。这两个文法之间有个纽带就是REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS,你在请求权限的时候传入,在回调函数中通过它判断自己的请求有没有成功。
一旦请求成功,那么你已经成功了第一步。
第二:GPS没有打开
如果通过第一步,你获得了权限,可以是还是无法获取到附近的wifi热点,那么你不妨打开GPS试试。是的,就是这么神奇,打开后你就可以获得附近wifi热点了。那么,这到底是怎么回事呢?不妨看看getScanResults方法到底做了什么。
getScanResults是WifiManager中的一个方法,然后通过远程系统调用,调用到了WifiServiceImpl.java中的getScanResults方法,这个方法如下:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> public List<ScanResult> getScanResults(String callingPackage) { enforceAccessPermission(); int userId = UserHandle.getCallingUserId(); int uid = Binder.getCallingUid(); boolean canReadPeerMacAddresses = checkPeersMacAddress(); boolean isActiveNetworkScorer = NetworkScorerAppManager.isCallerActiveScorer(mContext, uid); boolean hasInteractUsersFull = checkInteractAcrossUsersFull(); long ident = Binder.clearCallingIdentity(); try { if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled() ) { return new ArrayList<ScanResult>(); } if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !checkCallerCanAccessScanResults(callingPackage, uid)) { return new ArrayList<ScanResult>(); } if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage) != AppOpsManager.MODE_ALLOWED) { return new ArrayList<ScanResult>(); } if (!isCurrentProfile(userId) && !hasInteractUsersFull) { return new ArrayList<ScanResult>(); } return mWifiStateMachine.syncGetScanResultsList(); } finally { Binder.restoreCallingIdentity(ident); } }</span>
这个方法的try语句块中,首先第一个if中,它居然会判断:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">isLocationEnabled() </span>如果它是false,!isLocationEnabled 就为true,再加上前面两个对位true了,那么if里面的就会执行,然后就会返回一个空的List.
第二个if中则会判断权限:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_FINE_LOCATION, uid) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(AppOpsManager.OP_FINE_LOCATION, callingPackage, uid)) { return true; } if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_COARSE_LOCATION, uid) == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(AppOpsManager.OP_COARSE_LOCATION, callingPackage, uid)) { return true; }</span>可以看到他就是判断我们之前说的那两个权限,如果不想这么麻烦,统统把它们干掉也是可以的。这可能不是好主意,不过把对Location有没有使能的判断干掉是合理的,谁会在获取wifi热点信息的时候关注GPS有没有打开呢?google的这点设计真的很奇怪。
3.按照信号强弱排序
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> public List<ScanResult> sortSSIDBySignalLevel(List<ScanResult> resultList){ List<ScanResult> wifiScanResults = new ArrayList<ScanResult>(); int length = resultList.size(); for (int i = 0; i < length; i++) { for (int j = 0; j < length - i - 1; j++) { boolean is2Swaped = false; int lvl1 = resultList.get(j).level; lvl1 = WifiManager .calculateSignalLevel(lvl1, 7); int lvl2 = resultList.get(j + 1).level; lvl2 = WifiManager .calculateSignalLevel(lvl2, 7); if (lvl1 < lvl2) { is2Swaped = true; } else if (lvl1 == lvl2) { String str1 = resultList.get(j).SSID; String str2 = resultList.get(j + 1).SSID; if (str1 != null && str2 != null && str1.compareToIgnoreCase(str2) > 0) { is2Swaped = true; } else if (str1 != null && str2 == null) { is2Swaped = true; } } if (is2Swaped) { ScanResult temp = resultList.get(j); resultList.set(j, resultList.get(j + 1)); resultList.set(j + 1, temp); } } } // key wifiScanResults = resultList; return wifiScanResults; }</span>
4.连接wifi
wifi的连接主要使用WifiManager.addNetwork(WifiConfiguration config)方法。
因此,主要工作就是配置一个WifiConfiguration。主要配置项有:
4.1配置
1.configration.SSID
2.安全类型
2.1SECURITY_NONE,没有密码
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);</span>2.2SECURITY_WEP
配置密码:
config.wepKeys[0] = passwd;
配置安全类型之类的信息。
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);</span>2.3SECURITY_PSK
配置密码:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">config.preSharedKey = passwd;</span>配置安全类型:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);">config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);</span>
通过以上配置,即可调用WifiManager.addNetwork连接wifi。
4.2完整配置的示例
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> private WifiConfiguration getNetConfig(){ WifiConfiguration configration = new WifiConfiguration(); String passwd = mPwdInput.getText().toString(); configration.SSID = return "\"" + selScanResult.SSID; switch(getSecurity(selScanResult.capabilities)){ case SECURITY_NONE: configration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); break; case SECURITY_WEP: if(passwd.equals("")){ return null; } if (passwd.length() != 0) { int length = passwd.length(); if ((length == 10 || length == 26 || length == 58) && passwd.matches("[0-9A-Fa-f]*")) { configration.wepKeys[0] = passwd; } else { configration.wepKeys[0] = "\"" + passwd + "\""; } } else{ return null; }configration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); configration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); configration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); break; case SECURITY_PSK: if(passwd.equals("")) { return null; } if (passwd.length() != 0) { if (passwd.matches("[0-9A-Fa-f]{64}")) { configration.preSharedKey = passwd; } else { configration.preSharedKey = "\"" + passwd + "\""; } }else{ return null; } configration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); break; default: break; }</span>添加示例代码如下:
<span style="font-family:SimSun;font-size:14px;background-color: rgb(255, 255, 255);"> int wifiAdd = mWifiManager.addNetwork(config); if(wifiAdd < 0){ //failed }else { //sucess }</span>这个,整个wifi的连接过程就做完了。
- android6.0 wifi连接
- Android6.0通过WiFi名称密码连接WiFi的方案
- [RK3288][Android6.0] WiFi之Framework连接过程小结
- [RK3288][Android6.0] WiFi之开机自动连接过程
- android6.0连接WIFI后显示“已连接,但无法访问互联网”实际可以上网
- [RK3288][Android6.0] WiFi之通过wpa_cli分析WPAS的连接过程
- Android6.0 扫描WiFi列表的问题
- android6.0 切换到指定wifi
- [RK3288][Android6.0] WiFi之WifiWatchdogStateMachine
- android6.0 wifi和以太网优先级修改
- Android6.0及以上版本Wifi开发,扫描Wifi信息,获取Wifi列表为空
- [RK3288][Android6.0] WiFi在Setting中的开启过程小结
- [RK3288][Android6.0] Wifi相关文件及类整理
- [RK3288][Android6.0] Wifi Service初始化流程小结
- android6.0获取wifi mac地址的一种方法
- [RK3288][Android6.0] WiFi的dts配置说明(AP6335)
- [RK3288][Android6.0] WiFi的驱动初始化过程小结
- [RK3288][Android6.0] WiFi的HAL层加载问题
- HDU 4910 / BC 3D Problem about GCD
- #1039 : 字符消除
- HDU 1879 继续畅通工程
- 开发中遇到的问题
- Codeforces Round #355 (Div. 2)E. Vanya and Balloons
- android6.0 wifi连接
- matlab中关于pushbotton的左键双击响应问题
- LeetCode刷题之路 - number 26 and number 9
- iOS中常用的几何方法
- 字符集的前世今生
- 1013 Problem M
- 通过 脚本执行 kettle 的作业 命令
- 不同部门员工吃饭时聊些什么,程序员那一段笑死我了…
- pull解析xml