I've tried to create a Wi-Fi tethering hotspot in Android Marshmallow using the following code.
public class WifiAccessManager {
private static final String SSID = "1234567890abcdef";
public static boolean setWifiApState(Context context, boolean enabled) {
//config = Preconditions.checkNotNull(config);
try {
WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (enabled) {
mWifiManager.setWifiEnabled(false);
}
WifiConfiguration conf = getWifiApConfiguration();
mWifiManager.addNetwork(conf);
return (Boolean) mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class).invoke(mWifiManager, conf, enabled);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static WifiConfiguration getWifiApConfiguration() {
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = SSID;
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
return conf;
}
}
But it shows the following permission problem:
java.lang.SecurityException: googleplus.tarun.info.hotspotcreation was not granted either of these permissions: android.permission.CHANGE_NETWORK_STATE, android.permission.WRITE_SETTINGS.
Even though I have already added those on the manifest.
How can I solve the problem?
I was working in Android Marshmallow and have found a way to create WiFi tethering as describe below. Note that according to Android 6.0 Changes Your apps can now change the state of WifiConfiguration objects only if you created these objects. And beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. Read this article to know more about this. I can see you are creating Hotspot by your own. So no issue. The permission in Manifest is given below:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
I am using the following function to create WiFi tethering Hotspot in android marshmallow:
public void setWifiTetheringEnabled(boolean enable) {
//Log.d(TAG,"setWifiTetheringEnabled: "+enable);
String SSID=getHotspotName(); // my function is to get a predefined SSID
String PASS=getHotspotPassword(); // my function is to get a predefined a Password
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
if(enable){
wifiManager.setWifiEnabled(!enable); // Disable all existing WiFi Network
}else {
if(!wifiManager.isWifiEnabled())
wifiManager.setWifiEnabled(!enable);
}
Method[] methods = wifiManager.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("setWifiApEnabled")) {
WifiConfiguration netConfig = new WifiConfiguration();
if(!SSID.isEmpty() || !PASS.isEmpty()){
netConfig.SSID=SSID;
netConfig.preSharedKey = PASS;
netConfig.hiddenSSID = false;
netConfig.status = WifiConfiguration.Status.ENABLED;
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
}
try {
method.invoke(wifiManager, netConfig, enable);
Log.e(TAG,"set hotspot enable method");
} catch (Exception ex) {
}
break;
}
}
}
Enabling the Hotspot the function call is: setWifiTetheringEnabled(true) and for disable setWifiTetheringEnabled(false).
That's it.
N.B. Be noted that SIM less devices are not supported to use Hotspot. You will not be able to create the Hotspot on those devices without root.
Hope this will be helpful for upcoming visitors.
Related
In Android Q and above (API >= 29), the WifiManager.disconnect() method has been deprecated.
What would be the solution to disconnect from the Wi-Fi network in Android 10 and above?
I have implemented the next code, yet it fails always returning:
STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID.
I guess the reason for the failure could be that removeNetworkSuggestions maybe is expected to work in conjunction with addNetworkSuggestions, but I don't need to add any networks, on the contrary, to disconnect from the active one.
public final class WifiUtils {
private static final String TAG = "WifiUtils";
public static void disconnect(final Context context) {
// Sanity check
if (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
// Without the <Fine location> permission the returned SSID is always: '<unknown ssid>'.
// Note: The <Coarse location> permission is not enough.
Log.e(WifiUtils.TAG, "Missing <ACCESS_FINE_LOCATION> permission. Required to obtain the Wifi SSID.");
return;
}
final WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
if (!manager.isWifiEnabled())
return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
final WifiInfo wifiInfo = manager.getConnectionInfo();
if (wifiInfo == null) {
Log.w(WifiUtils.TAG, "Failed to get connection details.");
return;
}
final String ssid = wifiInfo.getSSID();
if (TextUtils.isEmpty(ssid)) {
Log.e(WifiUtils.TAG, "Unable to resolve Wifi SSID.");
} else {
Log.i(WifiUtils.TAG, "Resolved Wifi SSID: " + ssid);
final List<WifiNetworkSuggestion> suggestions = new ArrayList<>();
suggestions.add(new WifiNetworkSuggestion.Builder()
.setSsid(wifiInfo.getSSID())
.build());
final int status = manager.removeNetworkSuggestions(suggestions);
Log.d(WifiUtils.TAG, "Wifi disconnection status result: " + status);
}
} else {
manager.disconnect();
}
}
}
I have the required permissions in the manifest, granted at runtime:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I struggled with this for a while. Best thing to do is have the Android System take care of it with the following intent.
startActivity(new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY));
This will show a number of WiFi SSIDs around the user's location and they are able to pick one of the WiFis to connect to.
Is there any way besides the standard ConnectivityManager-API to modify wifi state in android q? I've just read google removed the api in android 10. Im willing to give the app android device administrator status, grant all permissions with adb, etc as I wont publish the app and will only use it for myself.
Your app must be a device owner as a variant to use wifiManager.setWifiEnabled(false) method that is deprecated started from Q.
Deprecation Exemptions:
Device Owner (DO), Profile Owner (PO) and system apps.
WifiManager
You can use the following code to disable wifi :
try {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
return wifiManager.setWifiEnabled(false);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
to disconnect wifi :
WifiManager wifiManager = (WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.disconnect();
and the following code to forget a particular wifi network :
try {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
List wifiNetworks = wifiManager.getConfiguredNetworks();
for (Object wifiConf : wifiNetworks) {
if (((WifiConfiguration) wifiConf).SSID.equalsIgnoreCase(SSID)) {
return wifiManager.removeNetwork(wifiManager.getConnectionInfo().getNetworkId()) && wifiManager.saveConfiguration();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
Hello Given link question is just showing how to turn on/off wifi hotspot but i want to add create wifi hotspot with SSID and password.
I written code for creating wifihotspot(in both NONE and WPA2 PSK) in android and its working fine upto android 7 but in oreo it returning me false value.The summary of my code is-
private WifiManager wifiManager;
private Method method;
private WifiConfiguration config;
config.SSID = ssid;
config.status = WifiConfiguration.Status.ENABLED;
method = wifiManager.getClass().getMethod("setWifiApEnabled",
WifiConfiguration.class, Boolean.TYPE);
boolean status = (Boolean) method.invoke(wifiManager, config, true);
So my question is how to create wifihotspot in both NONE and WPA2 PSK format for android oreo? Is it possible?
Oreo doesnot support to create hotspot programmatically with no password. It always creates hotspot with unique ssid and key generated randomly.
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiManager.LocalOnlyHotspotReservation mReservation;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
assert manager != null;
manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
#SuppressLint("SetTextI18n")
#Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Timber.d("Wifi Hotspot is on now , reservation is : %s", reservation.toString());
mReservation = reservation;
key = mReservation.getWifiConfiguration().preSharedKey;
ussid = mReservation.getWifiConfiguration().SSID;
}
#Override
public void onStopped() {
super.onStopped();
Timber.d("onStopped: ");
}
#Override
public void onFailed(int reason) {
super.onFailed(reason);
Timber.d("onFailed: ");
}
}, new Handler());
}
thanks, bro finally I found the solution on your answer,
first adding this (enable the modify setting)
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + this.getPackageName()));
startActivity(intent);
After pasting your code
then adding permissions in manifast
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
location mainly needs
<uses-feature android:name="android.hardware.wifi" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
The setWifiApEnabled will be deprecated. Looking at the source code, it always returns false :
/**
* This call will be deprecated and removed in an upcoming release. It is no longer used to
* start WiFi Tethering. Please use {#link ConnectivityManager#startTethering(int, boolean,
* ConnectivityManager#OnStartTetheringCallback)} if
* the caller has proper permissions. Callers can also use the LocalOnlyHotspot feature for a
* hotspot capable of communicating with co-located devices {#link
* WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)}.
*
* #param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
* #return {#code false}
*
* #hide
*/
#SystemApi
#RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
String packageName = mContext.getOpPackageName();
Log.w(TAG, packageName + " attempted call to setWifiApEnabled: enabled = " + enabled);
return false;
}
You can try using ConnectivityManager#startTethering(int, boolean, ConnectivityManager#OnStartTetheringCallback) as said in the javadoc. I personnally never tried it.
I'm using in the app
setWifiApEnabled()
from Hidden API (access by reflection). In some older phone it´s working (also with Samsung Galaxy S3, some phones with 4.4,...) but I tested it with Samsung Galaxy S5 and I get
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
...
I'm using similar code like there Android 2.2 wifi hotspot API or How and what to set to Android WifiConfiguration.preSharedKey to connect to the WPA2 PSK WiFi network but It´s a little old code.
Do you have experience with it? What do you suggest?
P.S. it's not working also in some Android 4.4 devices (but I don't get InvocationTargetException).
Try This.
ConnectivityManager cman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Method[] methods = cman.getClass().getMethods();
try
{
wifiManager.setWifiEnabled(false);
Method enableWifi = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
String ssid = " " //your SSID
String pass = " " // your Password
WifiConfiguration myConfig = new WifiConfiguration();
myConfig.SSID = ssid;
myConfig.preSharedKey = pass ;
myConfig.status = WifiConfiguration.Status.ENABLED;
myConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
myConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
myConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
myConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
myConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
myConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
myConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
result = (Boolean) enableWifi.invoke(wifiManager, myConfig, true);
}
catch (Exception e)
{
e.printStackTrace();
result = false;
}
In case of your exception try add this permission to your Manifest
android.permission.WRITE_SETTINGS
You need to add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
It works for me.
I had the same problem.
Added android.permission.WRITE_SETTINGS to the manifest file and it worked. Try this.
public void setWiFiApMode(boolean mode) {
if (mContext == null) return;
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
if (wifiManager == null) return;
try {
Method setWifiApEnabled = WifiManager.class.getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
setWifiApEnabled.invoke(wifiManager, null, mode);
} catch (Exception e) {
}
}
and
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
Fully works on Android N.
I found the cause:
Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10260 nor current process has android.permission.CONNECTIVITY_INTERNAL.
Info:
How can system app located in /system/app have system permission in Android 4.4 KitKat build?
It´s a little big problem :)
I use the connection manager class and get the network info, I just get if network type is Wifi or ethernet. But When my network type is Wifi, I would like to know if its static or dynamic.
Can someone help me out with this
below You can find simple (not optimised) code adapted from this thread.
Code is written for Android 4.0.
Remember to add additional user permissions:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Method:
public String getIpAssignment(){
String myenumvalue="";
WifiConfiguration wifiConf = null;
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
for (WifiConfiguration conf : configuredNetworks){
if (conf.networkId == connectionInfo.getNetworkId()){
wifiConf = conf;
break;
}
}
if(wifiConf != null){
try {
Object Enumer = getDeclaredField(wifiConf, "ipAssignment");
myenumvalue = Enumer.toString();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return myenumvalue;
}
It returns one of enum fields from ipAssignment: UNASSIGNED | STATIC | DHCP
my android test device android version 5.1.1(embedded board)
I used the code above, but it fell into the error
("catch NoSuchFieldException")
i use this code to find static or dhcp connection:
public void getWifiDhcpStatic(){
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
for (WifiConfiguration conf : configuredNetworks){
if (conf.networkId == connectionInfo.getNetworkId()){
if (conf.toString().toLowerCase().indexOf("DHCP".toLowerCase())>-1){
Log.i("myLogDHCPorSTATIC","DHCP ");
}else if(conf.toString().toLowerCase().indexOf("STATIC".toLowerCase())>-1){
Log.i("myLogDHCPorSTATIC","STATIC ");
}
break;
}
}
}
Do not forget to add in manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />