Enable mobile data (Lte/3g/gprs) with intent - android

In my app i want to navigate user to settings where he/she able to activate device mobile data.
I want to use intent to solve this but my problem is that mobile data option is in different pages in device settings for Exmaple below code work fine in Sony Xperia Z2 device (with android 5.1.1)
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
But in some other device such as sony experia SP (android 4.3) and samsung S4 (android 5.0.1) user must choose one more step and go to mobile network page.
I can resolve this problem with this code : (Going straight to mobile network)
Intent intent=new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS);
ComponentName cn = new ComponentName("com.android.phone","com.android.phone.Settings");
intent.setComponent(cn);
startActivity(intent);
But user with z2 must return one step back !
How can i resolve this ? choose which way ? (I hope explain problem clear )

try this way:
Also add the permission
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
method to enable mobile/3g data:
private void setMobileDataEnabled(Context context, boolean enabled) {
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);
}
For lollipop and above:
The setMobileDataEnabled method is no longer callable as of Android L and later

Related

Turning ethernet on and off on android

Is there a way to turn ethernet on and off programatically, similarly to how WiFi can be turned on and off through the WiFiManager class? I believe ifconfig down/up will not work as it would require root. I treid doing ifconfig wlan0 down in a terminal emulator, which gave me permission denied.
I'm on a non-rooted device.
firstly, you should know, since android Q, WifiManager class is not worked.
This method was deprecated in API level 29.
Starting with Build.VERSION_CODES#Q, applications are not allowed to enable/disable Wi-Fi. Compatibility Note: For applications targeting Build.VERSION_CODES.Q or above, this API will always return false and will have no effect. If apps are targeting an older SDK ( Build.VERSION_CODES.P or below), they can continue to use this API.
Both for the network and wifi, I suggest you show a permission dialog, let the user open it, it matches the android permission manager.
you can use the following code to open the setting
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.android.settings",
"com.android.settings.Settings$DataUsageSummaryActivity"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
if the target SDK below Q, you can try to use the reflect way.
private void setMobileDataEnabled(Context context, boolean enabled) throws Exception{
final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Class conmanClass = null;
try {
conmanClass = Class.forName(conman.getClass().getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
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);
}

Get WIFI ID from last connected WIFI

I'm writing an Android application which should react if the phone connects or disconnects to a WIFI network. I registered a BroadcastReceiver for this and it works great. Now with this code I'm able to get the current WIFI ID if the phone is connected to a WIFI:
WifiManager mainWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo currentWifi = mainWifi.getConnectionInfo();
int id = currentWifi.getNetworkId();
But what if the WIFI disconnects and I want to get the WIFI ID of the last connected WIFI? My problem is that all this is in an BroadcastReceiver. This is allways new created if a new Broadcast comes in so I can not really save some data there. Is there a method or something else with which I can get the last connected WIFI ID?
Forgive me if I'm missing something. You could getSharedPreferences to have a context to access from Broadcast receiver.
This BroadcastReceiver intercepts the android.net.ConnectivityManager.CONNECTIVITY_ACTION, which indicates a connection change. It checks whether the type is TYPE_WIFI. If it is, it checks whether Wi-Fi is connected and sets the wifiConnected flag in the main activity accordingly.
public class NetworkReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connMgr =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// Checks the user prefs and the network connection. Based on the result, decides
// whether
// to refresh the display or keep the current display.
// If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
if (WIFI.equals(sPref) && networkInfo != null
&& networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
// If device has its Wi-Fi connection, sets refreshDisplay
// to true. This causes the display to be refreshed when the user
// returns to the app.
You can find here the sample app.

Android L (5.x) Turn ON/OFF "Mobile Data" programmatically

I need to Turn ON/OFF Mobile data programmatically. Below code is not working for 5.x. Can you please help me. Thanks in advance.
private 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); }
03-30 12:42:29.466: W/System.err(5966):
java.lang.NoSuchMethodException: setMobileDataEnabled [boolean] 03-30
12:42:29.466: W/System.err(5966): at
java.lang.Class.getMethod(Class.java:664) 03-30 12:42:29.466:
W/System.err(5966): at
java.lang.Class.getDeclaredMethod(Class.java:626)
java.lang.NoSuchMethodException: setMobileDataEnabled [boolean] # below line.
final Method setMobileDataEnabledMethod =
connectivityManagerClass.getDeclaredMethod("setMobileDataEnabled",
Boolean.TYPE);
It seems like the setMobileDataEnabled method no longer exists in
ConnectivityManager and this functionality was moved to
TelephonyManager with two methods getDataEnabled and setDataEnabled.
public void setMobileDataState(boolean mobileDataEnabled)
{
try
{
TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("setDataEnabled", boolean.class);
if (null != setMobileDataEnabledMethod)
{
setMobileDataEnabledMethod.invoke(telephonyService, mobileDataEnabled);
}
}
catch (Exception ex)
{
Log.e(TAG, "Error setting mobile data state", ex);
}
}
public boolean getMobileDataState()
{
try
{
TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method getMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("getDataEnabled");
if (null != getMobileDataEnabledMethod)
{
boolean mobileDataEnabled = (Boolean) getMobileDataEnabledMethod.invoke(telephonyService);
return mobileDataEnabled;
}
}
catch (Exception ex)
{
Log.e(TAG, "Error getting mobile data state", ex);
}
return false;
}
When executing the code you get a SecurityException stating that Neither user 10089 nor current process has android.permission.MODIFY_PHONE_STATE.
A permission MODIFY_PHONE_STATE should be added
I got this from Answer
Thank you Muzikant
In Android L 5.xx the hidden API setMobileDataEnabled method is removed and it can no longer be used. You can verify this in android lolipop source code under /frameworks/base/core/java/android/net/ConnectivityManager.java.
If you still insist to perform it, you can use code snippet answered by Kushal but getDataEnabled is a system api, which normal user applications cant access. There is also one more system api available setDataEnabled under TelephonyManager. (/frameworks/base/telephony/java/android/telephony/TelephonyManager.java)
/** #hide */
#SystemApi
public void setDataEnabled(boolean enable) {
setDataEnabled(SubscriptionManager.getDefaultDataSubId(), enable);
}
It also needs the permission "android.permission.MODIFY_PHONE_STATE" which will work only on rooted devices.
Quick response, it is not possible to enable/disable mobile data by programming as it is possible with bluetooth.
Starting from version 23 of android, data protection begins to be highly valued and also the protection that an application activates or disables something on the phone, for this reason the permissions are implemented, taking this into account
Starting from this, google proposes that you encourage the user to do this action, giving him context and why he needs to have it activated.
Redirect the user to activate the data
Intent intent = new Intent(Settings.ACTION_DATA_USAGE_SETTINGS);
startActivity(intent);
Redirect the user to activate gps
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Request enable Bluetooth
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);

Android - Correct way to detect disconnecting from a particular wifi ssid?

I've seen a couple of BroadcastReciever examples to detect wifi disconnects but none of them seem to work correctly (triggering twice for each disconnect for example) and none mention checking against an ssid, is this even possible?
So just to clarify, I want to detect disconnection from a particular ssid. An actual disconnect and not wifi being disabled on the device.
Thanks
EDIT: Re-opening as nothing works on both the devices we have to test.
NETWORK_STATE_CHANGED_ACTION was the answer in the end. The device having the problem registering this event started working when another app (which would also be listening for similar events) was uninstalled! No idea how or why an app could block events registering with another app. The final solution ended up being;
String action = intent.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION))
{
WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
NetworkInfo.State state = networkInfo.getState();
if(state == NetworkInfo.State.CONNECTED)
{
String connectingToSsid = manager.getConnectionInfo().getSSID().replace("\"", "");
WifiStateHistory.recordConnectedSsid(connectingToSsid);
//connected
}
if(state == NetworkInfo.State.DISCONNECTED)
{
if(manager.isWifiEnabled())
{
String disconnectedFromSsid = WifiStateHistory.getLastConnectedSsid();
//disconnected
}
}
}
Are you sure there are twice notification for same state? There are always two phase of disconnection:
WifiManager.WIFI_STATE_DISABLING
WifiManager.WIFI_STATE_DISABLED
My code to detect (and rebroadcast) connections and disconnects (not by disabling wifi) and including the SSID as an extra is as follows. Most of what I've read suggested using SUPPLICANT_CONNECTION_CHANGE_ACTION but this just did not work correctly, it would seemingly only fire when disabling/enabling wifi on my device (Nexus 4) and not during connections. The only problem is on first run of the app as it won't record the current ssid so doesn't know what the ssid of the network that has just been connected. Any ideas around this?
public class EventMapper extends BroadcastReceiver
{
private static String lastConnectedSsid = "";
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION))
{
SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
if(state == SupplicantState.COMPLETED)
{
WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
lastConnectedSsid = manager.getConnectionInfo().getSSID().replace("\"", "");
Intent newIntent = new Intent();
newIntent.setAction(Event.App_Event_WifiConnected.name());
newIntent.putExtra("App_Events_SSID", lastConnectedSsid);
context.sendBroadcast(newIntent);
}
if(state == SupplicantState.DISCONNECTED)
{
boolean wifiEnabled = ((WifiManager)context.getSystemService(Context.WIFI_SERVICE)).isWifiEnabled();
if(wifiEnabled)
{
Intent newIntent = new Intent();
newIntent.setAction(Event.App_Event_WifiDisconnected.name());
newIntent.putExtra("App_Events_SSID", lastConnectedSsid);
context.sendBroadcast(newIntent);
}
}
}
}
}
I got the same problem in some custom roms. I used "android.net.wifi.STATE_CHANGE" to listen the network change. In the receiver, I used "(NetworkInfo)intent.getParcelableExtra("networkInfo")).getState()" to get the network state. There are three states: DISCONNECTED, CONNECTING, CONNECTED. You can use DISCONNECTED to detect if the network is disconnected.
Please let me know if it works in your situation(HTC One X (4.1)).

ANDROID: if WiFi is enabled AND active, launch an intent

This is what I would like to do :
=> IF WiFi is enabled AND active, launch an intent (in fact it's a WebView that gets its content=>the instructions of my app on the web)
=> IF NOT, then I would launch another intent so that I don't show a WebView with "Web page not available ... The Web page at http://www.mywebsite.com might be temporarily down or it may have moved ..."
I tought initially to use
if(wifi.isWifiEnabled())
but that does not say if the Wifi connection is ACTIVE or not. It says only that the user has turned the switch on. The device may or may not be connected... Is this correct ?
Then I tried to use :
if (wifi.getConnectionInfo().getSSID()!= null)
but I noticed that it returns a string even if the connection has been lost or has been disabled ... ?
How should I do then ?
wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
Intent intent_instructions;
if (wifi.getConnectionInfo().getSSID()!= null){
Log.i("Hub", "WiFi is enabled AND active !");
Log.i("Hub", "SSID = "+wifi.getConnectionInfo().getSSID());
intent_instructions = new Intent(this, Instructions.class);
}else{
Log.i("Hub", "NO WiFi");
intent_instructions = new Intent(this, Instructions_No_WiFi.class);
}
this.startActivity(intent_instructions);
Is there a more general way to test if the device has the connectivity to the internet just before launching an intent ? be it through Wifi, 3G, etc ...
Thanks in advance for your help.
You can use the following code to check for connectivity:
private static boolean isConnected(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = null;
if (connectivityManager != null) {
networkInfo =
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
}
return networkInfo == null ? false : networkInfo.isConnected();
}
Please make sure that you've registered the android.net.conn.CONNECTIVITY_CHANGE intent in your Manifest, or else, you'll never receive a notification that you're online.
I've been struggling with this issue for the last couple of days and I just now realized that I needed to register CONNECTIVITY_CHANGE and not only WIFI_STATE_CHANGED.
Try android.net.ConnectivityManager.getActiveNetworkInfo(): if it returns null you have no connection; if it returns a NetworkInfo object, you can check the connection's state with NetworkInfo.getState(), and if it's NetworkInfo.State.CONNECTED then you're connected, else you're not.
You can do it as follows:
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){
Log.d("WIFI", "WIFI has changed");
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1);
Log.d("WIFI", "WIFI State = " + wifiState);
setCurrentWifiState(wifiState);
}
You will get 0,1,2,3 depending on which state the Wifi is in, so for example 2 is connecting, you can check the rest in the documents
In your BroadcastReceiver class:
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)){
boolean connected = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
if (connected){
// start your service here
}
}
}
And in your AndroidManifest.xml make sure you register for the android.net.wifi.supplicant.CONNECTION_CHANGE broadcast intent.
<intent-filter >
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
</intent-filter>
isConnected() doesnt work fully ok, research something else
final ConnectivityManager connMgr = (ConnectivityManager)
this.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi =
connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile =
connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if( wifi.isAvailable() && wifi.getDetailedState() == DetailedState.CONNECTED){
Toast.makeText(this, "Wifi" , Toast.LENGTH_LONG).show();
}
else if( mobile.isAvailable() && mobile.getDetailedState() == DetailedState.CONNECTED ){
Toast.makeText(this, "Mobile 3G " , Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(this, "No Network " , Toast.LENGTH_LONG).show();
}
this code check if you are with wifi or 3g or nothing , in the case of wifi on but not connected to a net or 3g have signal problem it detect this details, with DetailedStates

Categories

Resources