如何以编程方式WEP/EAP WiFi configurations在Android中创建和阅读?
我看到很多人在各种论坛和整个社区的这个问题上苦苦挣扎.我知道这不是那么直接(尤其是EAP)要弄清楚因为当我想要实现同样的目标时我也非常挣扎.很好,代码分析和搜索互联网上各种实现的所有艰苦工作都是我用的终于能够实现目标了.所有的功劳归功于开源项目及其开发人员的数量.
我想与所有人分享这些知识,因为SO 鼓励这样做:"只要你假装自己在Jeopardy上,就问问并回答你自己的问题也是完全没问题的:用问题的形式说出来."
我可以枚举范围内的所有wifi网络(使用startScan + SCAN_RESULTS_AVAILABLE_ACTION + getScanResults)并获取其SSID和BSSID值,但我无法弄清楚如何确定每个网络的安全类型.
在我的主要对象中:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
registerReceiver(scanReceiver, intentFilter);
((WifiManager)getSystemService(Context.WIFI_SERVICE)).startScan();
Run Code Online (Sandbox Code Playgroud)
在我的scanReceiver对象中:
public void onReceive(Context c, Intent intent) {
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())){
mainObject.scanComplete();
}
}
Run Code Online (Sandbox Code Playgroud)
再次在我的主要对象中:
public void scanComplete()
{
List<ScanResult> networkList = ((WifiManager)getSystemService.(Context.WIFI_SERVICE)).getScanResults();
for (ScanResult network : networkList)
{
<do stuff>
}
}
Run Code Online (Sandbox Code Playgroud)
代码工作,因为scanComplete最终被调用,我可以成功枚举所有附近的无线网络并获得他们的SSID和BSSID,但我无法弄清楚如何确定他们的安全类型.
有没有办法做到这一点?
提前致谢.
我想开发一个可以阻止连接到WiFi网络的应用程序,除非我批准它.我希望能够查询接入点的MAC地址,并将其与SSID对应的已知地址列表进行比较.该应用程序的目标是保护用户免于意外连接到恶意访问点,例如可以使用菠萝设备生成的类型.
我不清楚我的研究如何实现这一目标.诸如如何通知wifi网络状态变化等问题?解释如何检测连接已经发生,但对于我的用例已经太晚了.
无论是ConnectivityManager 也WifiManager似乎提供方法补充说,可能会打断正在进行的连接监听器.
我有一些解决方案的想法:
安装自己作为代理,并决定是否允许数据通过.但是,这似乎不是基于Do Android代理设置适用于设备上的所有应用程序的选项吗?(提示:答案是"不").
用我自己创建的东西替换现有的WiFi管理器.但是,我真的很难在Android开发人员指南中找到有关更换系统组件的任何信息.因此,我不确定这在非根电话上是否可行.
将网络密码存储在我的应用程序中,并将WiFi管理器中的密码设置为无意义的值.然后捕获一个广播消息,警告连接失败(可能是类似的东西.我发现菠萝设备可能会接受任何密码,从而使这种方法无效.WifiManager.WPS_AUTH_FAILURE)并有选择地决定重新连接回该网络.可能是一个可能的(如果丑陋的)解决方案,但我可以在网络仍然连接时将密码设置回无意义的值,以确保我们不会安静地连接到另一个同名的SSID吗?我不确定
找到一些方法来阻止Android自动连接到已知网络(即之前使用过的网络或者密码存储在其中).然后我可以管理我的应用程序中的所有连接/断开连接.但是,我无法在手机上看到如何手动执行此操作,因此我怀疑这是可行的.
任何人都可以建议一种可以在非根电话上运行的方法吗?
我使用下面的代码连接到加密网络.但是,如果网络不安全并且我将密钥留空("")则会失败.有谁知道如何解决这个问题?此外,是否可以使用ssid/bssid检测网络是否打开?或者我必须使用过滤器进行扫描?
public void connectToSSID(final String ssid, final String key) {
Log.i("wifimaster", "connection to "+ssid);
WifiConfiguration wc = new WifiConfiguration();
wc.SSID = "\""+ssid+"\""; //IMPORTANT! This should be in Quotes!!
wc.priority = 40;
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wc.preSharedKey = "\""+key+"\"";
wc.wepKeys[0] = "\""+key+"\""; //This is the WEP Password
wc.wepTxKeyIndex = 0;
wc.preSharedKey = "\""+key+"\"";
int res = wifiManager.addNetwork(wc);
Log.d("WifiPreference", "add Network returned " + res );
boolean es = wifiManager.saveConfiguration();
Log.d("WifiPreference", "saveConfiguration …Run Code Online (Sandbox Code Playgroud) 我的应用需要与Sony Wifi相机通信.用户指定相机Wifi SSID和密码,应用程序连接,拍照并将其检索到Android设备.当应用程序完成拍照时,我希望它恢复应用程序启动之前存在的Wifi连接(如果有的话).例如,当用户启动wifi摄像头应用程序时,用户可能已经连接到咖啡店热点,因此应用程序应该在完成后自动重新连接到热点.
要恢复预先存在的连接,我认为应用程序需要知道SSID - 以及密码.应用程序很容易确定预先存在的SSID - 只需在切换到摄像头Wifi SSID之前调用WifiManager.getConnectionInfo().getSSID().但是如何获得预先存在的密码?我不想要求用户重新输入该密码.这个功能可以吗?
谢谢,汤姆
我用下面的代码,但它运作良好,但一些一个月后我得到的结果作为任何不但得不到BSSID值.这是我的代码.请指导我任何其他替代方式.
@SuppressLint("LongLogTag")
public void loadWifiAvailableList() {
WifiManager wifiMan = (WifiManager) getApplicationContext().getSystemService(
Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiMan.getConnectionInfo();
String macAddr = wifiInfo.getMacAddress();
String bssid = wifiInfo.getBSSID();
//here i am getting the proper bssid
Log.d("bssid from get connection info",bssid);
List<WifiConfiguration> list = wifiMan.getConfiguredNetworks();
for( WifiConfiguration i : list ) {
if(i.BSSID!=null)
//here i am getting any from i.BSSID
Log.d("bssid from get configured network",i.BSSID);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经成功地在我的设备上使用指定的SSID创建了一个可移植的热点.现在我想从另一台设备连接到它!我正在使用此代码:
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + "TinyBox" + "\"";
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiManager.addNetwork(conf);
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for( WifiConfiguration i : list ) {
if(i.SSID != null && i.SSID.equals("\"" + "TinyBox" + "\"")) {
wifiManager.disconnect();
wifiManager.enableNetwork(i.networkId, true);
wifiManager.reconnect();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
但没有任何反应.哪里出错了?谢谢
有人可以帮我解决这个问题吗?
这是我的代码,并且mWifi.enableNetwork(netID, true)它无法启用网络,无法自动连接到指定的网络.所以我想知道我犯了什么错误?
public class WifiConnActivity extends Activity {
/** Called when the activity is first created. */
final String tag = "WifiConn:...";
EditText txt;
WifiManager mWifi;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
txt = (EditText)findViewById(R.id.editText1);
Button b1 = (Button)findViewById(R.id.B1);
b1.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v)
{
if (mWifi.startScan()) //scan now
{
Log.d(tag, "startScan()");
List<ScanResult> sRet = mWifi.getScanResults(); //scan results.
for (int i=0; i<sRet.size(); i++)
{
ScanResult retS = sRet.get(i);
txt.append("resT: " …Run Code Online (Sandbox Code Playgroud) 我有这样的事情:
wifiNetworks = (ArrayList<ScanResult>) mWifiManager.getScanResults();
Run Code Online (Sandbox Code Playgroud)
现在我可以简单地获得wifi SSID:
wifiNetworks.get(0).SSID
Run Code Online (Sandbox Code Playgroud)
我不知道网络是WEP,WPA,它是否有密码,所以我只想创建一个Intent,把SSID或ScanResult放到设置或任何地方,以便让用户输入密码和连接到该网络.可能吗?如果没有,获取网络类型信息并以编程方式连接的最简单方法是什么?
我注意到,在WifiManager类中有一个名为addNetwork的函数,如果我想恢复或保存网络信息(网络名称AKA SSID以及密码和类型),该功能可能很有用,以便我也可以连接到它。
我找不到有关如何执行此操作的太多信息。我在StackOverflow上看到了各种示例,并且如果我以Android API 28(或更低版本)为目标,那么我确实成功地使它添加了网络,甚至连接到它。
但是,以Android 29(Android Q)为目标时,它无法添加网络。
由于我正在尝试使用Android Q beta 4的Pixel 2,我认为可能是因为addNetwork已弃用,所以文档甚至说了这一点,并且如果我定位到Android Q,它将无法正常工作,并且确实无法使用工作:
兼容性说明:对于面向Build.VERSION_CODES.Q或更高版本的应用程序,此API始终返回-1。
通过准备WifiConfiguration和添加,看来它应该可以运行到Android Q(不包括)的方式。以后,我也可以根据需要连接到它。在Android Q上,它似乎已由WifiNetworkSuggestion取代,但似乎根本就不是在添加网络:
网络建议对象用于提供Wi-Fi网络,以便在自动连接到网络时进行考虑。应用无法直接创建此对象,它们必须使用WifiNetworkSuggestion.Builder#build()来获取此对象的实例。
应用可以使用WifiManager#addNetworkSuggestions(List)向平台提供此类网络的列表。
这是我当前的代码,适用于Android-Q之前的版本
@WorkerThread
fun addNetwork(context: Context, networkName: String, networkPassword: String? = null, keyMgmt: Int = WifiConfiguration.KeyMgmt.NONE) {
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val conf = WifiConfiguration()
conf.SSID = "\"$networkName\""
conf.preSharedKey = if (networkPassword.isNullOrEmpty()) "" else "\"$networkPassword\""
conf.allowedKeyManagement.set(keyMgmt)
when (keyMgmt) {
WifiConfiguration.KeyMgmt.WPA_PSK -> {
//WPA/WPA2
}
WifiConfiguration.KeyMgmt.IEEE8021X -> …Run Code Online (Sandbox Code Playgroud) android ×10
android-wifi ×7
wifi ×5
java ×2
security ×2
wifimanager ×2
android-10.0 ×1
bssid ×1
connect ×1
encryption ×1