Asked  7 Months ago    Answers:  5   Viewed   39 times

I have a commercial app that has a completely legitimate reason to see the SSID of the network it is connected to: If it is connected to a Adhoc network for a 3rd party hardware device it needs to be functioning in a different manner than if it is connected to the internet.

Everything I've seen about getting the SSID tells me I have to use Apple80211, which I understand is a private library. I also read that if I use a private library Apple will not approve the app.

Am I stuck between an Apple and a hard place, or is there something I'm missing here?

 Answers

61

As of iOS 7 or 8, you can do this (need Entitlement for iOS 12+ as shown below):

@import SystemConfiguration.CaptiveNetwork;

/** Returns first non-empty SSID network info dictionary.
 *  @see CNCopyCurrentNetworkInfo */
- (NSDictionary *)fetchSSIDInfo {
    NSArray *interfaceNames = CFBridgingRelease(CNCopySupportedInterfaces());
    NSLog(@"%s: Supported interfaces: %@", __func__, interfaceNames);

    NSDictionary *SSIDInfo;
    for (NSString *interfaceName in interfaceNames) {
        SSIDInfo = CFBridgingRelease(
            CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName));
        NSLog(@"%s: %@ => %@", __func__, interfaceName, SSIDInfo);

        BOOL isNotEmpty = (SSIDInfo.count > 0);
        if (isNotEmpty) {
            break;
        }
    }
    return SSIDInfo;
}

Example output:

2011-03-04 15:32:00.669 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: Supported interfaces: (
    en0
)
2011-03-04 15:32:00.693 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: en0 => {
    BSSID = "ca:fe:ca:fe:ca:fe";
    SSID = XXXX;
    SSIDDATA = <01234567 01234567 01234567>;
}

Note that no ifs are supported on the simulator. Test on your device.

iOS 12

You must enable access wifi info from capabilities.

Important To use this function in iOS 12 and later, enable the Access WiFi Information capability for your app in Xcode. When you enable this capability, Xcode automatically adds the Access WiFi Information entitlement to your entitlements file and App ID. Documentation link

Swift 4.2

func getConnectedWifiInfo() -> [AnyHashable: Any]? {

    if let ifs = CFBridgingRetain( CNCopySupportedInterfaces()) as? [String],
        let ifName = ifs.first as CFString?,
        let info = CFBridgingRetain( CNCopyCurrentNetworkInfo((ifName))) as? [AnyHashable: Any] {

        return info
    }
    return nil

}
Tuesday, June 1, 2021
 
dmp
answered 7 Months ago
dmp
63

Without the use of private library (Apple80211) you can only get the SSID of the network your device is currently connected to.

Monday, June 7, 2021
 
ramdemon
answered 7 Months ago
51

You can update to the latest version of Xcode using the OS X App Store application.

Edit:

App Store link

Developer Center link

Thursday, August 12, 2021
 
Jon
answered 4 Months ago
Jon
57

If you want to get all available wifi :

   List<ScanResult> mScanResults = mWifiManager.getScanResults();

If you want to connected wifi ssid :

   WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
   WifiInfo wifiInfo = wifiManager.getConnectionInfo();
   Log.d("wifiInfo", wifiInfo.toString());
   Log.d("SSID",wifiInfo.getSSID());

If you want to add new wifi settings i have written demo app below :

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    connectToAP("12345", "12345");

    WifiConfiguration wifiConf = null;
    WifiManager wifiManager = (WifiManager) getSystemService(MainActivity.WIFI_SERVICE);
    WifiInfo connectionInfo = wifiManager.getConnectionInfo();
    List<WifiConfiguration> configuredNetworks = wifiManager
    .getConfiguredNetworks();
    for (WifiConfiguration conf : configuredNetworks) {
    if (conf.networkId == 13) {
    wifiConf = conf;
    try {
    setIpAssignment("STATIC", wifiConf); // or "DHCP" for
    // dynamic setting
    setIpAddress(InetAddress.getByName("192.168.0.100"), 24,
    wifiConf);
    setGateway(InetAddress.getByName("4.4.4.4"), wifiConf);
    setDNS(InetAddress.getByName("4.4.4.4"), wifiConf);
    wifiManager.updateNetwork(wifiConf); // apply the setting
    wifiManager.saveConfiguration(); // Save it
    } catch (Exception e) {
    e.printStackTrace();
    }
    break;
    }
    }

    }

    public static void setIpAssignment(String assign, WifiConfiguration wifiConf)
    throws SecurityException, IllegalArgumentException,
    NoSuchFieldException, IllegalAccessException {
    setEnumField(wifiConf, assign, "ipAssignment");
    }

    public static void setEnumField(Object obj, String value, String name)
    throws SecurityException, NoSuchFieldException,
    IllegalArgumentException, IllegalAccessException {
    Field f = obj.getClass().getField(name);
    f.set(obj, Enum.valueOf((Class<Enum>) f.getType(), value));
    }

    public static void setIpAddress(InetAddress addr, int prefixLength,
    WifiConfiguration wifiConf) throws SecurityException,
    IllegalArgumentException, NoSuchFieldException,
    IllegalAccessException, NoSuchMethodException,
    ClassNotFoundException, InstantiationException,
    InvocationTargetException {
    Object linkProperties = getField(wifiConf, "linkProperties");
    if (linkProperties == null)
    return;
    Class laClass = Class.forName("android.net.LinkAddress");
    Constructor laConstructor = laClass.getConstructor(new Class[] {
    InetAddress.class, int.class });
    Object linkAddress = laConstructor.newInstance(addr, prefixLength);

    ArrayList mLinkAddresses = (ArrayList) getDeclaredField(linkProperties,
    "mLinkAddresses");
    mLinkAddresses.clear();
    mLinkAddresses.add(linkAddress);
    }

    public static void setGateway(InetAddress gateway,
    WifiConfiguration wifiConf) throws SecurityException,
    IllegalArgumentException, NoSuchFieldException,
    IllegalAccessException, ClassNotFoundException,
    NoSuchMethodException, InstantiationException,
    InvocationTargetException {
    Object linkProperties = getField(wifiConf, "linkProperties");
    if (linkProperties == null)
    return;
    Class routeInfoClass = Class.forName("android.net.RouteInfo");
    Constructor routeInfoConstructor = routeInfoClass
    .getConstructor(new Class[] { InetAddress.class });
    Object routeInfo = routeInfoConstructor.newInstance(gateway);

    ArrayList mRoutes = (ArrayList) getDeclaredField(linkProperties,
    "mRoutes");
    mRoutes.clear();
    mRoutes.add(routeInfo);
    }

    public static void setDNS(InetAddress dns, WifiConfiguration wifiConf)
    throws SecurityException, IllegalArgumentException,
    NoSuchFieldException, IllegalAccessException {
    Object linkProperties = getField(wifiConf, "linkProperties");
    if (linkProperties == null)
    return;

    ArrayList<InetAddress> mDnses = (ArrayList<InetAddress>) getDeclaredField(
    linkProperties, "mDnses");
    mDnses.clear(); // or add a new dns address , here I just want to
    // replace DNS1
    mDnses.add(dns);
    }

    public static Object getField(Object obj, String name)
    throws SecurityException, NoSuchFieldException,
    IllegalArgumentException, IllegalAccessException {
    Field f = obj.getClass().getField(name);
    Object out = f.get(obj);
    return out;
    }

    public static Object getDeclaredField(Object obj, String name)
    throws SecurityException, NoSuchFieldException,
    IllegalArgumentException, IllegalAccessException {
    Field f = obj.getClass().getDeclaredField(name);
    f.setAccessible(true);
    Object out = f.get(obj);
    return out;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
    return true;
    }
    return super.onOptionsItemSelected(item);
    }

    String TAG = "wifi";
    WifiManager wifiManager;

    public void connectToAP(String ssid, String passkey) {
    Log.i(TAG, "* connectToAP");
    wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
    WifiConfiguration wifiConfiguration = new WifiConfiguration();

    String networkSSID = ssid;
    String networkPass = passkey;

    Log.d(TAG, "# password " + networkPass);

    // for (ScanResult result : scanResultList) {
    // if (result.SSID.equals(networkSSID)) {
    if (true) {
    // String securityMode = getScanResultSecurity(result);
    String securityMode = "WEP";
    if (securityMode.equalsIgnoreCase("OPEN")) {

    wifiConfiguration.SSID = """ + networkSSID + """;
    wifiConfiguration.allowedKeyManagement
    .set(WifiConfiguration.KeyMgmt.NONE);
    int res = wifiManager.addNetwork(wifiConfiguration);
    Log.d(TAG, "# add Network returned " + res);

    boolean b = wifiManager.enableNetwork(res, true);
    Log.d(TAG, "# enableNetwork returned " + b);

    wifiManager.setWifiEnabled(true);

    } else if (securityMode.equalsIgnoreCase("WEP")) {

    wifiConfiguration.SSID = """ + networkSSID + """;
    wifiConfiguration.wepKeys[0] = """ + networkPass + """;
    wifiConfiguration.wepTxKeyIndex = 0;
    wifiConfiguration.allowedKeyManagement
    .set(WifiConfiguration.KeyMgmt.NONE);
    wifiConfiguration.allowedGroupCiphers
    .set(WifiConfiguration.GroupCipher.WEP40);
    int res = wifiManager.addNetwork(wifiConfiguration);
    Log.d(TAG, "### 1 ### add Network returned " + res);

    boolean b = wifiManager.enableNetwork(res, true);
    Log.d(TAG, "# enableNetwork returned " + b);

    wifiManager.setWifiEnabled(true);
    }

    wifiConfiguration.SSID = """ + networkSSID + """;
    wifiConfiguration.preSharedKey = """ + networkPass + """;
    wifiConfiguration.hiddenSSID = true;
    wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
    wifiConfiguration.allowedGroupCiphers
    .set(WifiConfiguration.GroupCipher.TKIP);
    wifiConfiguration.allowedGroupCiphers
    .set(WifiConfiguration.GroupCipher.CCMP);
    wifiConfiguration.allowedKeyManagement
    .set(WifiConfiguration.KeyMgmt.WPA_PSK);
    wifiConfiguration.allowedPairwiseCiphers
    .set(WifiConfiguration.PairwiseCipher.TKIP);
    wifiConfiguration.allowedPairwiseCiphers
    .set(WifiConfiguration.PairwiseCipher.CCMP);
    wifiConfiguration.allowedProtocols
    .set(WifiConfiguration.Protocol.RSN);
    wifiConfiguration.allowedProtocols
    .set(WifiConfiguration.Protocol.WPA);

    int res = wifiManager.addNetwork(wifiConfiguration);
    Log.d(TAG, "### 2 ### add Network returned " + res);

    wifiManager.enableNetwork(res, true);

    boolean changeHappen = wifiManager.saveConfiguration();

    if (res != -1 && changeHappen) {
    Log.d(TAG, "### Change happen");

    // AppStaticVar.connectedSsidName = networkSSID;

    } else {
    Log.d(TAG, "*** Change NOT happen");
    }

    wifiManager.setWifiEnabled(true);
    }
    // }
    }

    public String getScanResultSecurity(ScanResult scanResult) {
    Log.i(TAG, "* getScanResultSecurity");

    final String cap = scanResult.capabilities;
    final String[] securityModes = { "WEP", "PSK", "EAP" };

    for (int i = securityModes.length - 1; i >= 0; i--) {
    if (cap.contains(securityModes[i])) {
    return securityModes[i];
    }
    }

    return "OPEN";
    }
}
Saturday, August 21, 2021
 
Aducci
answered 4 Months ago
92

I figured out what is going on here.
First, it is not related to the archive process itself but to the build in Release mode.
The reason that I had the problem during archive is because then it builds in release mode.

About the issue itself:
It seems that there is some sort of an Apple compiler bug in xcode 4.5.1.
I'm using the Apple LLVM compiler 4.1. During compilation it has different optimization levels.
In Debug - the optimization is set to 'None' and is off. In release it is set to 'Fastest, Smallest [-Os]'. When I turn off the optimization in release mode (set it to 'None') - the issue does not happen.

More info:
After digging in my code, and trying to figure out what would cause a compiler bug during optimization, I saw that I had the following:

__weak ProfileButton *tmp = myButton;

Where ProfileButton is just a regular button inherits from UIButton.
When I remove the __weak everything works just fine. Even when I set the compiler optimization to 'Fastest, Smallest [-Os]'.

Wednesday, October 20, 2021
 
Hat
answered 2 Months ago
Hat
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share