Android 2.2 Wifi Hotspot API

Android 2.2 wifi hotspot API

You can call

private boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled);

using reflection :)

after getting the WifiManager use the reflection to get the WifiManager declared methods, look for this method name setWifiApEnabled and invoke it through the WifiManager object

These API are marked as @hide, so currently you cannot use them directly, but they appear on the AIDL for the WifiManager so their are accessible!

An example can be:

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Method[] wmMethods = wifi.getClass().getDeclaredMethods();
for(Method method: wmMethods){
if(method.getName().equals("setWifiApEnabled")){
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = "\"PROVAAP\"";
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);

try {
method.invoke(wifi, netConfig,true);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

It works but I cannot change the current configuration with my own, and getting the current WifiConfiguration of an active AP drive me to an empty configuration.Why?

Android 2.3 wifi hotspot API

There is no official API, but you can use reflection to handle it. I know some say, it's not recommended, however imho I say, screw it if Google doesn't want to provide an API for whatever reason.

Below is the code of an activity I used in my application, where the user can enable/disable the Wifi AP.
When you enable Wifi AP, usually the regular Wifi will be turned off, so after the user disables the Wifi AP again, we'll be activating regular wifi again.

The code sample below is taken from one of my projects, hope you can get the logic there easily. Let me know if you have further questions.

Code is tested on Nexus One 2.2 (and I think also 2.3) as well as on Samsung Galaxy S (2.2).

package com.myapp.android.activity.wifi;

import android.app.ProgressDialog;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

import java.lang.reflect.Method;

public class WifiAP extends BaseActivity {

// boolean mIsWifiEnabled = false;
private static final int WIFI_AP_STATE_UNKNOWN = -1;
private static final int WIFI_AP_STATE_DISABLING = 0;
private static final int WIFI_AP_STATE_DISABLED = 1;
private static final int WIFI_AP_STATE_ENABLING = 2;
private static final int WIFI_AP_STATE_ENABLED = 3;
private static final int WIFI_AP_STATE_FAILED = 4;

private final String[] WIFI_STATE_TEXTSTATE = new String[] {
"DISABLING","DISABLED","ENABLING","ENABLED","FAILED"
};

private WifiManager wifi;

@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.wifi);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|WindowManager.LayoutParams.FLAG_DIM_BEHIND
);

wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
}

@Override
public void onResume() {
super.onResume();
updateStatusDisplay();
}

public void toggleWifi(View v) {
boolean wifiApIsOn = getWifiAPState()==WIFI_AP_STATE_ENABLED || getWifiAPState()==WIFI_AP_STATE_ENABLING;
new SetWifiAPTask(!wifiApIsOn,false).execute();
}

public void close(View v) {
boolean wifiApIsOn = getWifiAPState()==WIFI_AP_STATE_ENABLED || getWifiAPState()==WIFI_AP_STATE_ENABLING;
if (wifiApIsOn) {
new SetWifiAPTask(false,true).execute();
} else {
finish();
}
}

/**
* Endable/disable wifi
* @param enabled
* @return WifiAP state
*/
private int setWifiApEnabled(boolean enabled) {
Log.d("WifiAP", "*** setWifiApEnabled CALLED **** " + enabled);
if (enabled && wifi.getConnectionInfo() !=null) {
wifi.setWifiEnabled(false);
try {Thread.sleep(1500);} catch (Exception e) {}
}

//int duration = Toast.LENGTH_LONG;
//String toastText = "MobileAP status: ";
int state = WIFI_AP_STATE_UNKNOWN;
try {
wifi.setWifiEnabled(false);
Method method1 = wifi.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, boolean.class);
method1.invoke(wifi, null, enabled); // true
Method method2 = wifi.getClass().getMethod("getWifiApState");
state = (Integer) method2.invoke(wifi);
} catch (Exception e) {
Log.e(WIFI_SERVICE, e.getMessage());
// toastText += "ERROR " + e.getMessage();
}

if (!enabled) {
int loopMax = 10;
while (loopMax>0 && (getWifiAPState()==WIFI_AP_STATE_DISABLING
|| getWifiAPState()==WIFI_AP_STATE_ENABLED
|| getWifiAPState()==WIFI_AP_STATE_FAILED)) {
try {Thread.sleep(500);loopMax--;} catch (Exception e) {}
}
wifi.setWifiEnabled(true);
} else if (enabled) {
int loopMax = 10;
while (loopMax>0 && (getWifiAPState()==WIFI_AP_STATE_ENABLING
|| getWifiAPState()==WIFI_AP_STATE_DISABLED
|| getWifiAPState()==WIFI_AP_STATE_FAILED)) {
try {Thread.sleep(500);loopMax--;} catch (Exception e) {}
}
}

return state;
}

private int getWifiAPState() {
int state = WIFI_AP_STATE_UNKNOWN;
try {
Method method2 = wifi.getClass().getMethod("getWifiApState");
state = (Integer) method2.invoke(wifi);
} catch (Exception e) {}
Log.d("WifiAP", "getWifiAPState.state " + (state==-1?"UNKNOWN":WIFI_STATE_TEXTSTATE[state]));
return state;
}

private void updateStatusDisplay() {

if (getWifiAPState()==WIFI_AP_STATE_ENABLED || getWifiAPState()==WIFI_AP_STATE_ENABLING) {
((Button)findViewById(R.id.btnWifiToggle)).setText("Turn off");
findViewById(R.id.bg).setBackgroundResource(R.drawable.bg_wifi_on);
} else {
((Button)findViewById(R.id.btnWifiToggle)).setText("Turn on");
findViewById(R.id.bg).setBackgroundResource(R.drawable.bg_wifi_off);
}

}

class SetWifiAPTask extends AsyncTask<Void, Void, Void> {

boolean mMode;
boolean mFinish;

public SetWifiAPTask(boolean mode, boolean finish) {
mMode = mode;
mFinish = finish;
}

ProgressDialog d = new ProgressDialog(WifiAP.this);

@Override
protected void onPreExecute() {
super.onPreExecute();
d.setTitle("Turning WiFi AP " + (mMode?"on":"off") + "...");
d.setMessage("...please wait a moment.");
d.show();
}

@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
try {d.dismiss();} catch (IllegalArgumentException e) {};
updateStatusDisplay();
if (mFinish) finish();
}

@Override
protected Void doInBackground(Void... params) {
setWifiApEnabled(mMode);
return null;
}
}

}

On Android 2.2: Being in Tethering mode and scanning wifi at the SAME time

seems that you cannot do this by default way in android: if you have the wifi tethering enabled you cant use any wifi connectivity features (scan included). This is an exclusive functionality: tether or wifi client.
The WifiManager seems to be in WIFI_UNKNOW state when you have the tethering enabled.
I'm also investigating on this but I can't find any solution till now.

These are from the latest Froyo API (this method is marked as @hide) but i think you can access it throught reflection, I hope.

 public boolean setWifiApEnabled(WifiConfiguration  wifiConfig, boolean enabled)

Start AccessPoint mode with the specified configuration. If the radio is already running in AP mode, update the new configuration Note that starting in access point mode disables station mode operation

As you can see the AP mode will disable station mode operation (scanning etc)

I just tried it: you can use reflection and invoke the method to start the WifiAP.
Then if you call the method startScan() on the WifiManager you will get a false response so the scan doesn't work with the WifiAP enabled.

Marco

To share data through wifi-hotspot between two mobiles?

I wrote some small awful library that did this. You can use Java Sockets.

Have one device run ServerSocket in your app, this socket can listen for connections (like server). You need to check on which port this ServerSocket is listening (google about it). You will also need to get IP address of this device, there are few way: you can get it from WifiManager (google it).

Other device will use Socket class to connect to it. You can send data in multiple forms: plain strings or if you use same app you can serialize/deserialize objects.

Read a bit about sockets, but after ServerSocket get connection from other device, you can exchange messages (just keep listening in some loop on other thread).



Related Topics



Leave a reply



Submit