Android 6.0.1 couldn't enable wifi hotspot programmatically - android

When I tried to enable wifi tethering from the following code it throws the exception
java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at com.....
.... not granted this permission: android.permission.WRITE_SETTINGS
But this works fine in android 6.0 and below versions. And also tried with giving android.permission.WRITE_SETTINGS too.
Is there any limitation in accessing wifiAP in android 6.1?
Follow I attached the code sample that I used to enable hotspot.
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = ssId;
netConfig.preSharedKey = passkey;
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
try {
boolean apstatus = (Boolean) method.invoke(wifiManager, netConfig, true);
for (Method isWifiApEnabledmethod : wmMethods) {
if (isWifiApEnabledmethod.getName().equals("isWifiApEnabled")) {
while (!(Boolean) isWifiApEnabledmethod.invoke(wifiManager)) {}
for (Method method1 : wmMethods) {
if (method1.getName().equals("getWifiApState")) {
int apstate;
apstate = (Integer) method1.invoke(wifiManager);
Log.i(TAG, "Apstate ::: " + apstate);
}
}
}
}
if (apstatus) {
Log.d(TAG, "Access Point created");
} else {
Log.d(TAG, "Access Point creation failed");
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

I think Android M don't support to create hotspot programmatically . You can take your Marshmallow user to settings page to create hotspot by himself. below code will help yo to go setting page.
startActivity(
new Intent(Settings.ACTION_SETTINGS));

This is not the correct way.But this fixed the issue.
Changed the target sdk version to 21. Then hotspot will start programmatically even in android 6.0.1. Think there should be a proper way to do this for android 6 and later versions. I think requesting runtime permissions needs to execute those kind of processess.
This talks about the android permission requesting in runtime

Set target SDK version 21 and ask for write_settings permission in your activity. Also add android.permission.WRITE_SETTINGS permission in manifest.
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_SETTINGS)){
}else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_SETTINGS},
121);
}
For more details please visit http://developer.android.com/training/permissions/requesting.html

Guys I tried everything and I wasn't able to start the hotspot in Android 6.0.
You can just check if Api is >= 23, and if so just take the user to settings page to create hotspot by himself.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
final ComponentName cn = new ComponentName(
"com.android.settings",
"com.android.settings.TetherSettings");
intent.setComponent(cn);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity( intent);
}else{
createhotSpot();
}

Permission is not your problem. You need something like this code :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.System.canWrite(getApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 200); //You need a callback for activity result so that check if user enabled this feature, go for starting hotspot (google for it)
} else {
// Do your stuff about starting hotspot (in network thread)
}
}

Related

get the ssid and the password of the hotspot android 8.0 and higher

hello i try to get the ssid and the password of the hotspot. i use in the method below and its work for android below to 8.
but in android 8.0 its throw exption , i read that i need to get some premisiion
permission:android.permission.OVERRIDE_WIFI_CONFIG.
but we cant get this premission
Method[] methods = m_wifiManager.getClass().getDeclaredMethods();
for (Method m : methods) {
if (m.getName().equals("getWifiApConfiguration")) {
try {
m_wifiConf = (WifiConfiguration) m.invoke(m_wifiManager);
message = m_wifiConf.SSID + '/' + m_wifiConf.preSharedKey + '/';
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
Not sure if this relates to your approach with reflection, but as of Android 8.1 you need to have at least ACCESS_COARSE_LOCATION permission and location services enabled in order to use getConnectionInfo() (see getScanResults()).
Anyway, that won't get you access to the wifi password.
As for the OVERRIDE_WIFI_CONFIG permission, it is defined as
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
android:protectionLevel="signature|privileged" />
This means that your app has to be signed by a platform key or to be added to the privileged whitelist in order to use this permission.

How to get Permission for read "Service SMS" in MIUI 8+ (programmatically)

How to get Permission for read "Service SMS" in MIUI 8+ (programmatically).
This will launch the intent for service sms. Once user will allow the access for service sms you will able to read the notification sms.
if (isMIUI()) {
//this will launch the auto start screen where user can enable the permission for your app
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", getActivity().getPackageName());
startActivity(localIntent);
}
public static boolean isMIUI() {
String device = Build.MANUFACTURER;
if (device.equals("Xiaomi")) {
try {
Properties prop = new Properties();
prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
return prop.getProperty("ro.miui.ui.version.code", null) != null
|| prop.getProperty("ro.miui.ui.version.name", null) != null
|| prop.getProperty("ro.miui.internal.storage", null) != null;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
Note: you can not take the permission programmatically it's only allowed for whitelisted app from MIUI. for example- facebook messenger, whatsapp, flipkart etc have autostart option by default.

Connect to wifi without internet programmatically

I'm using the following code to connect to a WiFi network without internet connection, because it hosts its own web-server where I want to connect even if there is no internet connection available.
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = String.format("\"%s\"", scanResult.SSID);
wifiConfiguration.preSharedKey = String.format("\"%s\"", "secret");
int netId = wifiManager.addNetwork(wifiConfiguration)
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
This works fine on every device below Android Marshmallow (I'm using CM13, so is it maybe related to CyanogenMod?): When I use this code to connect, Android still uses the mobile connection and mark the WiFi symbol with an exclamation mark. Seconds later it shows a notification with the question if I want to stay connected, because the network has no internet connection.
Problem: My app tries to connect automatically to my web-server which fail, because there is obviously no internet connection. Of course it would be possible to wait until I can reach my web-server, but it should work without user interaction.
How does ChromeCast or any other IoT device solve this? I never saw a notification like this when I was setting up my ChromeCast device.
I solved this by binding (connectivityManager.bindProcessToNetwork(network);) the current process to the connected network. This prevents the "keep using this network" Dialog and allows you to communicate with the device over wifi.
NetworkRequest.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
if (!Settings.System.canWrite(mActivity)) {
Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + mActivity.getPackageName()));
mActivity.startActivity(goToSettings);
}
}
connectivityManager.bindProcessToNetwork(null);
if (mSsid.contains("my_iot_device-xxxxxxxxx")) {
connectivityManager.bindProcessToNetwork(network);
} else {
}
} else {
//This method was deprecated in API level 23
ConnectivityManager.setProcessDefaultNetwork(null);
if (mSsid.contains("my_iot_device-xxxxxxxxx")) {
ConnectivityManager.setProcessDefaultNetwork(network);
} else {
}
}
try {
//do a callback or something else to alert your code that it's ok to send the message through socket now
} catch (Exception e) {
Crashlytics.logException(e);
e.printStackTrace();
}
connectivityManager.unregisterNetworkCallback(this);
}
});
}

How does MoreLocale work?

I downloaded source code, and seems that there is something connected with Android Settings. I want to implement some it's features in my application. How it works?
Finally I found a way to set Android system locale:
public void changeLanguage() {
IActivityManager am = ActivityManagerNative.getDefault();
Configuration config;
try {
config = am.getConfiguration();
config.locale = Locale.US; // Change it to your locale
config.userSetLocale = true;
am.updateConfiguration(config);
BackupManager.dataChanged("com.android.providers.settings");
} catch (RemoteException e) {
e.printStackTrace();
}
}
It also requires CHANGE_CONFIGURATION permission:
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
NOTE: In Android 4.2 or newer, permission policy has been changed, and 3rd party application can't get this permission. If you have root access, execute pm grant command:
String.format("pm grant $1%s android.permission.CHANGE_CONFIGURATION", new Object[]{getPackageName()})

Enabling USB tethering programmatically - there is an app that did it for 2.3

I've read many questions here on SO that ask how to enable USB tethering programmatically.
The answer is always the same, ordinary applications can't do it, only system apps.
Yet for 2.3 you could download an app in the market that would do it for you.
https://play.google.com/store/apps/details?id=org.tdtran.autousbtethering
On ICS (Android 4.0.3) it no longer works.
How did they do it for 2.3? Is it possible also for 4.0?
using the following code you can enable USB tethering. i didt test in 4.0.
public void switchOnTethering() {
Object obj = getSystemService(Context.CONNECTIVITY_SERVICE);
for (Method m : obj.getClass().getDeclaredMethods()) {
if (m.getName().equals("tether")) {
try {
m.invoke(obj, "usb0");
} 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();
}
}
}
}
ICS and above: To execute the reflection method, the application would require the WRITE_SECURE_SETTINGS permission.
This is not available unless the phone is rooted.
since this is one of the most popular pages in the Google results for this topic I'd like to contribute my code which is checking the available interfaces. It does work on a Gingerbread phone I have, but not my Galaxy S3.
// DETECT INTERFACE NAME
Log.i("UsbTethering","Detecting tetherable usb interface.");
String[] available = null;
ConnectivityManager connMgr = (ConnectivityManager)connectivityServiceObject;
Method[] wmMethods = connMgr.getClass().getDeclaredMethods();
for(Method getMethod: wmMethods)
{
if(getMethod.getName().equals("getTetherableUsbRegexs"))
{
try
{
available = (String[]) getMethod.invoke(connMgr);
break;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
// DETECT INTERFACE NAME
if(available.length > 0)
{
for(String interfaceName : available)
{
Log.i("UsbTethering", "Detected " + String.valueOf(available.length) + " tetherable usb interfaces.");
Log.i("UsbTethering", "Trying to " + desiredString + " UsbTethering on interface " + interfaceName + "...");
Integer returnCode = (Integer)method.invoke(connectivityServiceObject, interfaceName);
if(returnCode == 0)
{
Log.i("UsbTethering", "UsbTethering " + desiredString + "d.");
return true;
}
else
{
Log.w("UsbTethering", "Failed to " + desiredString + "Usb Tethering. ReturnCode of method " + method.getName() + ": " + String.valueOf(returnCode));
}
}
}
On Samsumg Galaxy Tab 2 10.1 the interface isn't called "usb0" but "rndis0". Maybe that's the same for Galaxy SII
The port "rndis0" is enabled dynamically not availble in the the Tetherable interfaces list.
It gets added when the user selects the USB Tethering option in the menu.
The function ConnectivityManager::setUsbTethering(bool) is called when the option is selected. And this function call is allowed only for System applications.
I know its an old thread but i hope this could help some other people in the future ,
That code worked for me in Android 4.4(with root privilege)
code:
the trick is to use reflection , the method which changes the usb tethring is called "setUsbTethering"
I wont write the entire class but here is what you need:
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Method usbTethering = connectivityManager.getClass().getMethod('setUsbTethering')
int returnCode = (Integer)usbTethering.invoke(connectivityManager, true);
0 = success
you can print the entire class methods using the following code
private static void printClassMethod(#NonNull Class aClazz) {
Method[] wmMethods = aClazz.getDeclaredMethods();
for (Method method : wmMethods) {
Log.i('anytag', method.getName());
}
}
then call printClassMethod(ConnectivityManager.class)
More Over, you can go onto the class itself and check the methods and arguments needed.
to get things work:
you must set your app as System app,
Declare in manifest : android:sharedUserId="android.uid.system"
add writing secure permission<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
Sign the apk using google certificate key(apk-with-system-privileges) and push it to /system/app
Mind, that usbTethering is turned on while USB is attached, so a nicer solution will be to register to both USB_STATE and USB_ATTACH and enable/disable it correspondingly in onReceive Method. (USB tethering is turned off automatically when USB is de-attached)

Categories

Resources