I'm trying to enable/disable data mobile in specific moments. I've tried it on MotoG 4.4.2 (Rooted) with it I had no problem to do this, but when I've tried it on Samsung Galaxy Grand Prime 4.4.4 (No Root) it doesn't work, also I've tried it on Samsung Galaxy S3 4.3 (No Root) but it worked.
MotoG Worked -- WHY? -- ROOT Acces
Samsung Galaxy Grand Prime didn't work -- WHY? -- I think it doesn't work because when I try to do it manually I've to accept a dialog that I want to lose data connectivity, and I think this is the problem because it doesn't work.
Samsung Galaxy S3 worked -- WHY? -- I think it worked because the user put "Don't show me again" and user accepted it before.
The code that I'm trying is :
public void GetDataConnectionAPI() {
this.context.getApplicationContext();
TelephonyManager telephonyManager =
(TelephonyManager) this.context.getApplicationContext().
getSystemService(Context.TELEPHONY_SERVICE);
try {
telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);
ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());
dataConnSwitchmethod_OFF =
ITelephonyClass.getDeclaredMethod("disableDataConnectivity");
dataConnSwitchmethod_ON = ITelephonyClass.getDeclaredMethod("enableDataConnectivity");
} catch (Exception e) {
e.printStackTrace();
}
}
And then I enable/disable the data with this method :
public void setMobileDataEnabled(Context context, boolean enabled) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field connectivityManagerField = conmanClass.getDeclaredField("mService");
connectivityManagerField.setAccessible(true);
final Object connectivityManager = connectivityManagerField.get(conman);
final Class connectivityManagerClass = Class.forName(connectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod = connectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(connectivityManager, enabled);
}
When I want to Enable I call this method :
public void EnableMobileData(){
try {
setMobileDataEnabled(context, true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
On my Manifest I put
<!-- 3g uses-permisions-->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
I wonder if it's any possibility to avoid this dialog or just accept it programmatically..
I've read Bojan Kogoj answer that sais that I've to :
Pre-installed into a system folder on the ROM
Compiled by a manufacturer using their security certificate
But I'm wondering if is any other way to do this.
The MODIFY_PHONE_STATE permission is not guaranteed to work in all cases. By default it is a system-level permission, so it will only work on devices whose manufacturers have enabled it.
Similarly, methods like getITelephony() are device/manufacturer-specific, and there is no way to get the name of the methods for doing so on every device.
Unfortunately there is no guaranteed way to do this.
Related
Kindly give answer,i have trouble to refresh mobile network,I don't want system app,I need only for android Mobile apps,I need to refresh my mobile data network pro grammatically in current version like marshmallow and nougat,I already put permissions for this,i attached following my codes
private static boolean setMobileConnectionEnabled(Context context, boolean enabled) {
try {
// Requires: android.permission.CHANGE_NETWORK_STATE
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
Log.i("if", "" + Build.VERSION.SDK_INT);
// pre-Gingerbread sucks!
final TelephonyManager telMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final Method getITelephony = telMgr.getClass().getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
final Object objITelephony = getITelephony.invoke(telMgr);
final Method toggleDataConnectivity = objITelephony.getClass()
.getDeclaredMethod(enabled ? "enableDataConnectivity" : "disableDataConnectivity");
toggleDataConnectivity.setAccessible(true);
toggleDataConnectivity.invoke(objITelephony);
}
// Requires: android.permission.CHANGE_NETWORK_STATE
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Log.i("else", "" + Build.VERSION.SDK_INT);
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Gingerbread to KitKat inclusive
final Field serviceField = connMgr.getClass().getDeclaredField("mService");
serviceField.setAccessible(true);
final Object connService = serviceField.get(connMgr);
try {
final Method setMobileDataEnabled = connService.getClass()
.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
Log.i("try", "" + setMobileDataEnabled);
setMobileDataEnabled.setAccessible(true);
setMobileDataEnabled.invoke(connService, Boolean.valueOf(enabled));
} catch (NoSuchMethodException e) {
// Support for CyanogenMod 11+
final Method setMobileDataEnabled = connService.getClass()
.getDeclaredMethod("setMobileDataEnabled", String.class, Boolean.TYPE);
setMobileDataEnabled.setAccessible(true);
Log.i("catch", "" + setMobileDataEnabled);
Log.i("errr", "" + e.getMessage());
try {
setMobileDataEnabled.invoke(connService, context.getPackageName(), Boolean.valueOf(enabled));
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
// Requires: android.permission.MODIFY_PHONE_STATE (System only, here for completions sake)
else {
// Lollipop and into the Future!
final TelephonyManager telMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Log.i("telMgr",""+telMgr);
final Method setDataEnabled = telMgr.getClass().getDeclaredMethod("setDataEnabled", Boolean.TYPE);
Log.i("telMgdfgsdgr",""+setDataEnabled);
setDataEnabled.setAccessible(true);
setDataEnabled.invoke(telMgr, Boolean.valueOf(enabled));
}
return true;
} catch (NoSuchFieldException e) {
Log.e("", "setMobileConnectionEnabled", e);
} catch (IllegalAccessException e) {
Log.e("gsdjkghskd", "setMobileConnectionEnabled", e);
} catch (IllegalArgumentException e) {
Log.e("lllll", "setMobileConnectionEnabled", e);
} catch (NoSuchMethodException e) {
Log.e("nooooo", "setMobileConnectionEnabled", e);
} catch (InvocationTargetException e) {
Log.e("innnnnn", "setMobileConnectionEnabled", e);
}
return false;
}
My Manifest file
<permission
android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.MODIFY_PHONE_STATE"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.CHANGE_NETWORK_STATE"
android:maxSdkVersion="24" />
Kindly give some suggestions please
I can't comment so I'll put my answer here, but it might disappoint you.
There's currently no way to do that in Android >= 5.
You can do that only on rooted phone or system app. It was possible through reflection but since it was #Hide annotated Google removed it and had every right to do so.
If you're looking for disabling only (or disabling the the possibility to change cellular data state) you can use your device provider's api (like Samsung). Samsung allows to disable the possibility to change the cell data state, but... you cannot force the state back to on, after the possibility to change was turned off.
Google repeatedly ignores tickets from the community to bring back this option to SDK.
Please downvote this answer only if you have a solution how to do that without rooted phone or system app.
I'm having android(OS_VERSION 4.0) device. I would like to share the files to another android device through the wifi networks. I know, This can be done through wifi p2p(WifiDirect) in android 4.0 above. But this is not possible in android 2.3.3 devices(Prior to Android 4.0). I found the Superbeam application does the file sharing through shared networks in android 2.3.3.This application create the wifi tethering without sharing the internet connection of the device. The created tethering is only used for sharing the files not for sharing the internet. How to achieve this concept. Can anyone help me?
This answer may help to someone having the same question. The simple logic i implemented is,
1.Create the wifi tethering(Hotspot)
2.Disable the mobile data connection
Code is,
//To enable the wifi hotspot
setWifiTetheringEnabled(true);
//To disable the mobile data cnnection
setMobileDataEnabled(false);
private void setWifiTetheringEnabled(boolean enable) {
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
Method[] methods = wifiManager.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("setWifiApEnabled")) {
try {
method.invoke(wifiManager, null, enable);
} catch (Exception ex) {
}
break;
}
}
}
private void setMobileDataEnabled(Context context, boolean enabled) {
try {
final ConnectivityManager conman = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class
.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass
.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField
.get(conman);
final Class iConnectivityManagerClass = Class
.forName(iConnectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod = iConnectivityManagerClass
.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled);
} catch (ClassNotFoundException | NoSuchFieldException
| IllegalAccessException | IllegalArgumentException
| NoSuchMethodException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am writing a little app that only I will use and I want to pragmatically enable / disable my mobile data on a rooted android 4.5 device (I am running a custom Android L for Nexus 4).
I have looked for a while and I found the methods with reflection that worked until android 4.3.
I have also seen the method from this post Toggle mobile data programmatically on Android 4.4.2 but this requires cyanogenmod.
From what I can find on the internet this is impossible for non-root apps but my question is:
is there something I can do with my root privileges to accomplish this?
I've created this method looking around on internet; it works fine on rooted android 5.0.1
Basically you have to pass true if you want the connection to be enabled, false otherwise, and the context of your application.
private final static String COMMAND_L_ON = "svc data enable\n ";
private final static String COMMAND_L_OFF = "svc data disable\n ";
private final static String COMMAND_SU = "su";
public static void setConnection(boolean enable,Context context){
String command;
if(enable)
command = COMMAND_L_ON;
else
command = COMMAND_L_OFF;
try{
Process su = Runtime.getRuntime().exec(COMMAND_SU);
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes(command);
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
outputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
Please report if this has problems on some device.
EDIT: Now also compatible with android 5.1 Credit
Use this
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Method methodSet = tm.class.getDeclaredMethod( "setDataEnabled", boolean.class);
methodSet.invoke(tm, true);
Edit:
This requires permission MODIFY_PHONE_STATE, this is System or signature level permission.
Ideally you could create a runnable jar file with this code and execute it using
export CLASSPATH=<jar path>
exec app_process <jar-dir-path> your.package.name.classname "$#"
from su shell.
I noticed that the service call method does not work consistently on all devices. The number to be used in it varied from device to device.
I have found the following solution which works without any issue across all ROOTED devices.
Simply execute the following via su
To enable mobile data
svc data enable
To disable mobile data
svc data disable
It's as simple as that.
void turnData(boolean ON) throws Exception
{
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if(currentapiVersion == Build.VERSION_CODES.FROYO)
{
Log.i("version:", "Found Froyo");
try{
Method dataConnSwitchmethod;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;
TelephonyManager telephonyManager = (TelephonyManager) cx.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);
ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());
if (ON) {
dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("enableDataConnectivity");
} else {
dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("disableDataConnectivity");
}
dataConnSwitchmethod.setAccessible(true);
dataConnSwitchmethod.invoke(ITelephonyStub);
}catch(Exception e){
Log.e("Error:",e.toString());
}
}
else
{
Log.i("version:", "Found Gingerbread+");
final ConnectivityManager conman = (ConnectivityManager) cx.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(conman);
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, ON);
}
}
I have a small issue regarding Ethernet.
My three questions are:
Can we programmatically Turn-On/Off Ethernet?
Can we programmatically Enable/Disable Ethernet?
Can we programmatically Connect Ethernet?
The above Questions are done with the Wifi. Like
We can programmatically Turn-On/Off Wifi.
We can programmatically Enable/Disable Wifi.
We can programmatically Connect Wifi using WifiManager.
Does android provides any EthernetManager like as WifiManager to handle Ethernet?
Or, if this doesn't seem feasible, then my original requirement is:
The first thing I am going to clear is "DEVICE IS ROOTED" .
Can I manipulate the Settings (Default)? Like I don't want any other option in the Settings.apk other than WIFI and Ethernet. It should show only Wifi and Ethernet. That's it. Can I disable all the options from the Settings or Can I remove all the other options from the Settings?
The solution I will present here is a hack using reflection and does only work on a rooted android system.
Your device might have the popular android.net.ethernet package. In an Activity, try
Object emInstance = getSystemService("ethernet");
It returns an valid instance of the EthernetManager or null. Null means you are out of luck.
An additional requirement might be depending on your device: Ethernet and Wifi might only work exclusively. You might need to disable Wifi to enable Ethernet and vice versa.
To enable Ethernet by reflection use your instance of the EthernetManager.
The method you want to invoke is setEthEnabled(boolean enabled)
Class<?> emClass = null;
try {
emClass = Class.forName("android.net.ethernet.EthernetManager");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object emInstance = getSystemService("ethernet");
Method methodSetEthEnabled = null;
try {
methodSetEthEnabled = emClass.getMethod("setEthEnabled", Boolean.TYPE);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
methodSetEthEnabled.setAccessible(true);
try {
// new Boolean(true) to enable, new Boolean(false) to disable
methodSetEthEnabled.invoke(emInstance, new Boolean(false));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Your application manifest needs these permissions
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
The permission WRITE_SECURE_SETTINGS can only be acquired by system apps. The app does not need to be signed by a system key. It can be any valid sign (like the regular Android App Export function). Use busybox to remount the system partition for write access and move your apk into the /system/app folder. Reboot the device and it should work.
Can we programmatically Connect Ethernet ?
There is no Access Point to connect you like with Wifi. You either configure it for DHCP or provide static values. This can of course also be done via reflection.
You will need the class EthernetDevInfo for that.
The actual implementation of the EthernetManager and EthernetDevInfo might slightly differ between Android versions and devices as it doesn't have to conform to a public api (yet) and might even be a custom version.
To get a list of getters and setters you can use a Introspector or reflection in general.
Ok here are some methods i made for manipulating with the ETHERNET INTERFACE (eth0).
1) A method for checking if an ethernet interface exists
public static boolean doesEthExist() {
List<String> list = getListOfNetworkInterfaces();
return list.contains("eth0");
}
public static List<String> getListOfNetworkInterfaces() {
List<String> list = new ArrayList<String>();
Enumeration<NetworkInterface> nets;
try {
nets = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
return null;
}
for (NetworkInterface netint : Collections.list(nets)) {
list.add(netint.getName());
}
return list;
}
2) A method for checking if the ETHERNET is enabled or ON
public static boolean isEthOn() {
try {
String line;
boolean r = false;
Process p = Runtime.getRuntime().exec("netcfg");
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
if(line.contains("eth0")){
if(line.contains("UP")){
r=true;
}
else{
r=false;
}
}
}
input.close();
Log.e("OLE","isEthOn: "+r);
return r;
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
return false;
}
}
3) A method for enabling or disabling the Ethernet depending on the state in which it is
public static void turnEthOnOrOff() {
try {
if(isEthOn()){
Runtime.getRuntime().exec("ifconfig eth0 down");
}
else{
Runtime.getRuntime().exec("ifconfig eth0 up");
}
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
}
}
4) A method for connecting via ethernet depending on the chosen type (dhcp/static)
private boolean connectToStaticSettingsViaIfconfig(StaticConnectionSettings scs) {
try {
if(typeChosen.equalsIgnoreCase("dhcp")){
Runtime.getRuntime().exec("ifconfig eth0 dhcp start");
}
else{
Runtime.getRuntime().exec("ifconfig eth0 "+scs.getIp()+" netmask "+scs.getNetmask()+" gw "+scs.getGateway());
}
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
return false;
}
return true;
}
There is one more class which i created for storing all the eth values needed. This class is than initialized with the values the user inserts.
public class StaticConnectionSettings {
private String ip, netmask, dns, mac, gateway, type;
//Getters and Setters
}
This is it ... I will test it shortly... This code lacks a test phase (ping). And maybe it needs setting of DNS. But this can be done easily. I have not included it because i think on our device it will work also without the DNS setting.
It works for Android 6.0.1
Class<?> ethernetManagerClass = Class.forName("android.net.ethernet.EthernetManager");
Method methodGetInstance = ethernetManagerClass.getMethod("getInstance");
Object ethernetManagerObject = methodGetInstance.invoke(ethernetManagerClass);
Method methodSetEthEnabled = ethernetManagerClass.getMethod("setEthernetEnabled", Boolean.TYPE);
methodSetEthEnabled.invoke(ethernetManagerObject, isEnabled);
Three Answeres to your above questions:
Yes. You could try using ifconfig eth0 down ; ifconfig eth0 up. But i have not tested it by myself yet.
Yes, but you do not have to. Android does the switching for you. If you connect to WiFi, Ethernet disables. If you are already connected to WiFi and you plug your ethernet cable into the device; you need only to disable WiFi (which you know how to) and android switches automatically to ethernet.
Not so easy as you may think. I have the same problem and until now i have found only one solution which i have not yet tested. Since android runs on the linux kernel, we can use ifconfig in order to manipulate the ethernet connection.
An explanation is hidden here:
http://elinux.org/images/9/98/Dive_Into_Android_Networking-_Adding_Ethernet_Connectivity.pdf
And the youtube video of this lecture
http://www.youtube.com/watch?v=LwI2NBq7BWM
And a reference on how to use ifconfig for android
Android ethernet configure IP using dhcp
So if you come to a possible solution, please share it!! If i will do it before you i will certenly.
I want to know how to detect state of WiFi tethering. I've seen an article: Android 2.3 wifi hotspot API But it doesn't work! It returns always WIFI_AP_STATE_DISABLED = 1. It doesn't depend on real state of WiFi tethering.
Using reflection:
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Method[] wmMethods = wifi.getClass().getDeclaredMethods();
for (Method method: wmMethods) {
if (method.getName().equals("isWifiApEnabled")) {
try {
boolean isWifiAPenabled = method.invoke(wifi);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
As you can see here
In addition to the reflexion, to get the Wifi tethering status update, you can listen to this broadcast Action :
IntentFilter filter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED");
To get all tethering option update :
IntentFilter filter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED");
Those actions are hidden inside the Android source code
First, you need to get WifiManager:
Context context = ...
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Then:
public static boolean isSharingWiFi(final WifiManager manager)
{
try
{
final Method method = manager.getClass().getDeclaredMethod("isWifiApEnabled");
method.setAccessible(true); //in the case of visibility change in future APIs
return (Boolean) method.invoke(manager);
}
catch (final Throwable ignored)
{
}
return false;
}
Also you need to request a permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Here is the Xamarin C# version if anyone is looking:
static Method isWifiApEnabledMethod;
public static bool IsWifiApEnabled ()
{
var wifiManager = WifiManager.FromContext (Application.Context);
if (isWifiApEnabledMethod == null)
{
try
{
isWifiApEnabledMethod = wifiManager.Class.GetDeclaredMethod ("isWifiApEnabled");
isWifiApEnabledMethod.Accessible = true; //in the case of visibility change in future APIs
}
catch (NoSuchMethodException e)
{
Debug.WriteLine ("Can't get method by reflection" + e);
}
catch (System.Exception ex)
{
Debug.WriteLine ("Can't get method by reflection" + ex);
}
}
if (isWifiApEnabledMethod != null)
{
try
{
return (bool)isWifiApEnabledMethod.Invoke (wifiManager);
}
catch (System.Exception ex)
{
Debug.WriteLine ("Can't invoke by reflection" + ex);
}
}
return false;
}
(without using reflection since they say google is restricting it)
I'm writting this answer 10 years later. also I don't know if this can be considered a good aproach or not but I first get the Wlan network interface IPs
and if there is no address I assume that it tethering isn't enabled. if there is an address, I check using the connectivity manger whether WI-FI is connected to a network or not. if there is an IP for the Wlan network interface but it isn't connected to a network, I assume tethering is enabled.
you probably would need to add this line to your manifest file
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
code to get the ip of an inteface (this only gets the IPv4, you can modify it to get the IPv6 or both if you want)
// method used to retrieve Wlan ip addresses IPv4 of the device.
public static String IpAddresses() throws NoAddressFoundException, SocketException {
Enumeration<NetworkInterface> Nics = NetworkInterface.getNetworkInterfaces();
while (Nics.hasMoreElements()) {
NetworkInterface NIC = Nics.nextElement();
if (NIC.isUp() && !NIC.isLoopback() && NIC.getName().contains("wlan")) {
Enumeration<InetAddress> Addresses = NIC.getInetAddresses();
while (Addresses.hasMoreElements()) {
InetAddress WlanAddress = Addresses.nextElement();
if (WlanAddress instanceof Inet4Address)
return WlanAddress.getHostAddress();
}
}
}
throw new NoAddressFoundException("No suitable wifi address found");
}
then if there is an address i check if wifi is connected by this method:
//method to check if the device is connected to a Wi-Fi network; it doesn't matter if network has access to internet
public static boolean isWifiConnected(Context context) {
ConnectivityManager ConMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo WifiInfo = ConMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return WifiInfo.isConnected();
}
NOTE: the "NoAddressFoundException" is a custom exception in my app if anyone is wondering. it won't exist in your case.
Reflection is a poor way to achieve this.
We can inspect the DhcpInfo to determine if the device is allocating addresses (mobile hotspot) or is being allocated by another DHCP server.
Here is a kotlin function that will determine if a device is a mobile hotspot, it has not been widely tested so YMMV.
fun isMobileHotspot(manager: WifiManager): Boolean {
val info = manager.dhcpInfo
return (
info.ipAddress == 0
&& info.netmask == 0
&& info.gateway == 0
&& info.serverAddress == 16885952) // 192.168.1.1
}