Note that there are some explanatory texts on larger screens.

plurals
  1. POCreate an access point with the Nexus 7
    primarykey
    data
    text
    <h2>What's the aim?</h2> <p>Create an Access Point with an Android device (Nexus 7 in my case). The final purpose is to connect a WiFly card to this created network and exchange data between these devices. </p> <h2>Hardware:</h2> <ul> <li>Nexus 7 with the Android version 4.2.2 <strong>rooted</strong> with the ROM CyanogenMod 10.1</li> <li>WiFly card: Arduino shield with the same layout as Zigbee cards that use Wifi (<a href="https://www.sparkfun.com/products/10822" rel="nofollow noreferrer">the product</a>)</li> </ul> <h2>Software:</h2> <p>I understood that the Android version 4.2.2 does not allow to create an Access Point (the service is disabled programmatically). This is why I rooted my device with the ROM from CyanogenMod. This ROM enable this service. </p> <p>Google has hidden some methods from the class <code>WifiManager</code>. Specifically, the method <code>setWifiApEnabled</code>. This is why I use reflection to call methods on the code below.</p> <p><em>The source code is massive!</em> Focus on the method <code>createAccessPoint()</code>. I chose to put the whole source code to help people that want to know how I did all of this. </p> <pre class="lang-java prettyprint-override"><code>public class TestAccessPoint extends Activity { static final String TAG = "AP_TEST"; static final String SSID = "\"Awesome Access Point\""; static final String PSK = "\"helloworld\""; String numberOfClientsConnected; String wifiApEnable; String wifiApState; WifiConfiguration wifiApConfig; WifiManager wifiManager; WifiConfiguration wifiConfiguration; BroadcastReceiver receiver; BroadcastReceiver receiverWifiDisabled; TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.accesspoint_test); textView = (TextView) findViewById(R.id.textView); wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); wifiConfiguration = new WifiConfiguration(); if(wifiManager.isWifiEnabled()) { createAccessPoint(); } else { Log.d(TAG, "Set wifi Enable"); wifiManager.setWifiEnabled(true); receiverWifiDisabled = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN); if ( wifiState == WifiManager.WIFI_STATE_ENABLED ) { Log.d(TAG, "Wifi enable"); createAccessPoint(); } } }; registerReceiver(receiverWifiDisabled, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); } final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: textView.setText( wifiApEnable + "\n" + wifiApState + "\n" + "Nb of clients connected: " + numberOfClientsConnected + "\n" + "Wifi AP configuration: " + "\n" + wifiApConfig.toString() + "\n" + "WifiManager connection info: " + "\n" + wifiManager.getConnectionInfo().toString() + "DHCP state: " + wifiManager.getDhcpInfo().toString() ); break; } } }; Thread thread = new Thread(new Runnable() { boolean alive = true; @Override public void run() { while(alive) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } numberOfClientsConnected = numberOfClientsConnected(); wifiApEnable = isWifiApEnabled(); wifiApState = getWifiApState(); wifiApConfig = getWifiApConfiguration(); mHandler.sendMessage(mHandler.obtainMessage(1)); } } }); thread.start(); } @Override public void onDestroy() { super.onDestroy(); if(receiver != null) { unregisterReceiver(receiver); } if(receiverWifiDisabled != null) { unregisterReceiver(receiverWifiDisabled); } } protected void createAccessPoint() { // Check if the Wifi configuration already exists List&lt;WifiConfiguration&gt; list = wifiManager.getConfiguredNetworks(); int networkID = -1; if(list != null){ for(WifiConfiguration conf : list) { Log.d(TAG, "Network ID: " + String.valueOf(conf.networkId) + " ; Network SSID: " + conf.SSID); if(conf.SSID.equals(SSID)) { Log.d(TAG, "SSID found"); networkID = conf.networkId; wifiConfiguration = conf; break; } } } else Log.d(TAG, "List of WifiConfiguration is null"); // If the configuration exists, remove it to recreate it from scratch if(networkID != -1) { wifiManager.removeNetwork(networkID); } // Create a new WiFi configuration wifiConfiguration.SSID = SSID; wifiConfiguration.preSharedKey = PSK; wifiConfiguration.hiddenSSID = false; wifiConfiguration.status = WifiConfiguration.Status.ENABLED; wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // Catch Enumeration IpAssignment and ProxySettings from WifiConfiguration Enum ipAssignment = catchEnumIpAssignmentFromWifiConfiguration(); Enum proxySettings = catchEnumProxySettingsFromWifiConfiguration(); // Set IP address, gateway, DNS, etc try { Log.d(TAG, "Try to set IP, gateway and DNS"); setIpAssignment(ipAssignment, wifiConfiguration); Log.d(TAG, "IpAssignment: Ok"); setProxySettings(proxySettings, wifiConfiguration); Log.d(TAG, "ProxySettings: Ok"); setIpAddress(InetAddress.getByName("192.168.2.100"), 24, wifiConfiguration); Log.d(TAG, "IpAddress: Ok"); setGateway(InetAddress.getByName("192.168.2.1"), wifiConfiguration); Log.d(TAG, "Gateway: Ok"); setDNS(InetAddress.getByName("192.168.2.1"), wifiConfiguration); Log.d(TAG, "DNS: Ok"); } catch(Exception e) { e.printStackTrace(); } // Add this new configuration to the wpa_supplicant file networkID = wifiManager.addNetwork(wifiConfiguration); if(networkID != -1) Log.d(TAG, "Succeed to update the WiFi configuration: " + networkID); else Log.d(TAG, "Failed to update the WiFi configuration"); // Save the new configuration on the wpa_supplicant if(wifiManager.saveConfiguration()) Log.d(TAG, "Succeed to save the wpa_supplicant"); else Log.d(TAG, "Failed to save the wpa_supplicant"); // Set the Wifi disable to be able to start the Access Point Log.d(TAG, "Set wifi disable"); wifiManager.setWifiEnabled(false); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN); if ( wifiState == WifiManager.WIFI_STATE_DISABLED ) { Log.d(TAG, "Wifi disabled"); // When the Wifi is disable // Create the Access Point with the WiFi configuration try { Method m = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); boolean succeed = (Boolean) m.invoke(wifiManager, wifiConfiguration, true); if(succeed) Log.d(TAG, "Succeed to set wifi AP"); else Log.d(TAG, "A problem occured while setting the wifi AP"); } catch (Exception e) { Log.e(TAG, "Failed to set wifi AP", e); } } } }; registerReceiver(receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); } protected String getWifiApState() { try { Method m3 = wifiManager.getClass().getMethod("getWifiApState"); return "WiFi Ap State: " + String.valueOf(m3.invoke(wifiManager)); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } protected WifiConfiguration getWifiApConfiguration() { WifiConfiguration wifiConfiguration = null; try { Method m4 = wifiManager.getClass().getMethod("getWifiApConfiguration"); wifiConfiguration = (WifiConfiguration) m4.invoke(wifiManager); } catch (Exception e) { e.printStackTrace(); } return wifiConfiguration; } protected String isWifiApEnabled() { try { Method m = wifiManager.getClass().getMethod("isWifiApEnabled"); if((Boolean) m.invoke(wifiManager)) return "WiFiAP enabled"; else return "WiFiAP not enabled"; } catch (Exception e) { e.printStackTrace(); } return null; } protected String numberOfClientsConnected() { int macCount = 0; BufferedReader br = null; try { br = new BufferedReader(new FileReader("/proc/net/arp")); String line; while ((line = br.readLine()) != null) { String[] splitted = line.split(" +"); if (splitted != null &amp;&amp; splitted.length &gt;= 4) { String mac = splitted[3]; if (mac.matches("..:..:..:..:..:..")) { macCount++; } } } } catch (Exception e) { e.printStackTrace(); } finally { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } return String.valueOf(macCount); } @SuppressWarnings({ "unchecked", "rawtypes" }) protected Enum catchEnumIpAssignmentFromWifiConfiguration() { Enum DHCP = null; try { Class&lt;Enum&gt; enumIpAssignment = (Class&lt;Enum&gt;) Class.forName("android.net.wifi.WifiConfiguration$IpAssignment"); DHCP = Enum.valueOf(enumIpAssignment, "DHCP"); } catch (ClassNotFoundException e) { e.printStackTrace(); } return DHCP; } @SuppressWarnings({ "unchecked", "rawtypes" }) protected Enum catchEnumProxySettingsFromWifiConfiguration() { Enum ProxySet = null; try { Class&lt;Enum&gt; enumProxySettings = (Class&lt;Enum&gt;) Class.forName("android.net.wifi.WifiConfiguration$ProxySettings"); ProxySet = Enum.valueOf(enumProxySettings, "NONE"); } catch (ClassNotFoundException e) { e.printStackTrace(); } return ProxySet; } public static void setIpAssignment(Object assign , WifiConfiguration wifiConf) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException { setEnumField(wifiConf, assign, "ipAssignment"); } public static void setProxySettings(Object assign , WifiConfiguration wifiConf) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException { setEnumField(wifiConf, assign, "proxySettings"); } @SuppressWarnings({ "rawtypes", "unchecked" }) 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); } @SuppressWarnings({ "rawtypes", "unchecked" }) 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); } @SuppressWarnings("unchecked") public static void setDNS(InetAddress dns, WifiConfiguration wifiConf) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException { Object linkProperties = getField(wifiConf, "linkProperties"); if(linkProperties == null)return; ArrayList&lt;InetAddress&gt; mDnses = (ArrayList&lt;InetAddress&gt;)getDeclaredField(linkProperties, "mDnses"); mDnses.clear(); 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; } public static void setEnumField(Object obj, Object value, String name) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field f = obj.getClass().getField(name); f.set(obj, value); } } </code></pre> <p>This code works fine on my Nexus 7. It creates an Access Point. My laptop see the network link this: <img src="https://i.stack.imgur.com/QcC4c.png" alt="enter image description here"></p> <p>It asks me to enter the WPA key. I need to write it wrapped with quotes whether it does not work (<code>"helloworld"</code>).</p> <p>After that, my laptop is connected to the network but with the software <a href="http://www.xirrus.com/Products/Wi-Fi-Inspector.aspx" rel="nofollow noreferrer">Xirrus</a> I realized that the DHCP module doesn't give any IP address. </p> <h2>Logs:</h2> <p>I get two interesting logs. This one is when I start the application: </p> <pre><code>E/hostapd(): Configuration file: /data/misc/wifi/hostapd.conf E/hostapd(): HT (IEEE 802.11n) in 11b mode is not allowed, disabling HT capabilites I/hostapd(): rfkill: Cannot open RFKILL control device W/hostapd(): wlan0: Could not connect to kernel driver E/hostapd(): Using interface wlan0 with hwaddr 02:1a:11:fd:32:58 and ssid "\"Awesome Access Point\"" E/hostapd(): random: Cannot read from /dev/random: Try again I/hostapd(): random: Only 0/20 bytes of strong random data available from /dev/random I/hostapd(): random: Allow operation to proceed based on internal entropy </code></pre> <p>And this one is when I connect and disconnect my laptop from/to the Access Point: </p> <pre><code>I/hostapd(): wlan0: AP-STA-DISCONNECTED 00:27:10:ca:f0:80 I/hostapd(): wlan0: AP-STA-CONNECTED 00:27:10:ca:f0:80 </code></pre> <h2>Questions:</h2> <ul> <li>If you think that I'm doing the wrong way, could you tell me a better way? </li> <li>Do you know why I didn't get IP address from the DHCP module? </li> <li>Do you know I could get more information/logs from the DHCP module?</li> </ul> <p>Thank you for your support.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload