Android M: 无法以编程方式删除 WIFI AP
Android M: Unable to remove WIFI AP programmatically
In Android M: 我正在使用下面的代码删除当前连接的 WIFI AP。
void RemoveConnectedNetwork(){
int ID=_wifiManager.getConnectionInfo().getNetworkId();
Log.d("test", "network id = ["+ID+"]");
boolen ret =_wifiManager.removeNetwork(ID);
Log.d("test", "removeNetwork return ="+ret);
_wifiManager.saveConfiguration();
}
但 RemoveConnectedNetwork()
总是 returns false。
虽然这个 API 在以前的版本中运行良好。
使用 Android M 中的任何其他 API 可以解决这个问题吗?
谢谢。
Android 6.0 中的 Wifi 管理器有一些变化。
如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 非零。
用户仍然可以创建和修改自己的 Wi-Fi 配置。
活跃的设备所有者有权编辑或删除任何 Wi-Fi 配置,包括那些不是他们创建的。
请参阅此link了解更多详情:
https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html
自 Android 起,不允许 M 个应用修改非其创建的网络。任何网络都可以从应用程序中删除,如果它是由该应用程序本身配置的。
调用removeNetwork(int)后查看"WifiConfigManager"的log,会报错this UID (app UID) does not have permission to delete configuration ("wifi SSID"capabilities)
这有很多原因,请参阅以下代码和link了解更多详细信息。
https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiConfigManager.java
/**
* Checks if |uid| has permission to modify the provided configuration.
*
* @param config WifiConfiguration object corresponding to the network to be modified.
* @param uid UID of the app requesting the modification.
* @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts.
*/
private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) {
// System internals can always update networks; they're typically only
// making meteredHint or meteredOverride changes
if (uid == Process.SYSTEM_UID) {
return true;
}
// Passpoint configurations are generated and managed by PasspointManager. They can be
// added by either PasspointNetworkEvaluator (for auto connection) or Settings app
// (for manual connection), and need to be removed once the connection is completed.
// Since it is "owned" by us, so always allow us to modify them.
if (config.isPasspoint() && uid == Process.WIFI_UID) {
return true;
}
// EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided
// by authenticator back to the WifiConfiguration object.
// Since it is "owned" by us, so always allow us to modify them.
if (config.enterpriseConfig != null
&& uid == Process.WIFI_UID
&& TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) {
return true;
}
final DevicePolicyManagerInternal dpmi = LocalServices.getService(
DevicePolicyManagerInternal.class);
final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
// If |uid| corresponds to the device owner, allow all modifications.
if (isUidDeviceOwner) {
return true;
}
final boolean isCreator = (config.creatorUid == uid);
// Check if the |uid| holds the |NETWORK_SETTINGS| permission if the caller asks us to
// bypass the lockdown checks.
if (ignoreLockdown) {
return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}
// Check if device has DPM capability. If it has and |dpmi| is still null, then we
// treat this case with suspicion and bail out.
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
&& dpmi == null) {
Log.w(TAG, "Error retrieving DPMI service.");
return false;
}
// WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner.
final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!isConfigEligibleForLockdown) {
return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}
final ContentResolver resolver = mContext.getContentResolver();
final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
return !isLockdownFeatureEnabled
&& mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}
In Android M: 我正在使用下面的代码删除当前连接的 WIFI AP。
void RemoveConnectedNetwork(){
int ID=_wifiManager.getConnectionInfo().getNetworkId();
Log.d("test", "network id = ["+ID+"]");
boolen ret =_wifiManager.removeNetwork(ID);
Log.d("test", "removeNetwork return ="+ret);
_wifiManager.saveConfiguration();
}
但 RemoveConnectedNetwork()
总是 returns false。
虽然这个 API 在以前的版本中运行良好。
使用 Android M 中的任何其他 API 可以解决这个问题吗?
谢谢。
Android 6.0 中的 Wifi 管理器有一些变化。
如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 非零。
用户仍然可以创建和修改自己的 Wi-Fi 配置。
活跃的设备所有者有权编辑或删除任何 Wi-Fi 配置,包括那些不是他们创建的。
请参阅此link了解更多详情: https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html
自 Android 起,不允许 M 个应用修改非其创建的网络。任何网络都可以从应用程序中删除,如果它是由该应用程序本身配置的。 调用removeNetwork(int)后查看"WifiConfigManager"的log,会报错this UID (app UID) does not have permission to delete configuration ("wifi SSID"capabilities)
这有很多原因,请参阅以下代码和link了解更多详细信息。 https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/master/service/java/com/android/server/wifi/WifiConfigManager.java
/**
* Checks if |uid| has permission to modify the provided configuration.
*
* @param config WifiConfiguration object corresponding to the network to be modified.
* @param uid UID of the app requesting the modification.
* @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts.
*/
private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) {
// System internals can always update networks; they're typically only
// making meteredHint or meteredOverride changes
if (uid == Process.SYSTEM_UID) {
return true;
}
// Passpoint configurations are generated and managed by PasspointManager. They can be
// added by either PasspointNetworkEvaluator (for auto connection) or Settings app
// (for manual connection), and need to be removed once the connection is completed.
// Since it is "owned" by us, so always allow us to modify them.
if (config.isPasspoint() && uid == Process.WIFI_UID) {
return true;
}
// EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided
// by authenticator back to the WifiConfiguration object.
// Since it is "owned" by us, so always allow us to modify them.
if (config.enterpriseConfig != null
&& uid == Process.WIFI_UID
&& TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) {
return true;
}
final DevicePolicyManagerInternal dpmi = LocalServices.getService(
DevicePolicyManagerInternal.class);
final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
// If |uid| corresponds to the device owner, allow all modifications.
if (isUidDeviceOwner) {
return true;
}
final boolean isCreator = (config.creatorUid == uid);
// Check if the |uid| holds the |NETWORK_SETTINGS| permission if the caller asks us to
// bypass the lockdown checks.
if (ignoreLockdown) {
return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}
// Check if device has DPM capability. If it has and |dpmi| is still null, then we
// treat this case with suspicion and bail out.
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
&& dpmi == null) {
Log.w(TAG, "Error retrieving DPMI service.");
return false;
}
// WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner.
final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!isConfigEligibleForLockdown) {
return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}
final ContentResolver resolver = mContext.getContentResolver();
final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
return !isLockdownFeatureEnabled
&& mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
}