Определить USB-модем на Android
Есть ли какой-нибудь способ (программно) узнать в вашей Активности / Приложении, что пользователь включил USB-модем на своем телефоне?
6 ответов
Просматривая документацию Settings.System, вы обнаружите, что ответ "нет" сделать это невозможно.
Вы также можете использовать отражение для доступа к скрытой функции для настройки USB-модема. Вот мой код
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
Log.d(TAG,"test enable usb tethering");
String[] available = null;
int code=-1;
Method[] wmMethods = cm.getClass().getDeclaredMethods();
for(Method method: wmMethods){
if(method.getName().equals("getTetherableIfaces")){
try {
available = (String[]) method.invoke(cm);
break;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
}
}
for(Method method: wmMethods){
if(method.getName().equals("tether")){
try {
code = (Integer) method.invoke(cm, available[0]);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
break;
}
}
if (code==0)
Log.d(TAG,"Enable usb tethering successfully!");
else
Log.d(TAG,"Enable usb tethering failed!");
Чтобы отключить usb-модем, вам просто нужно изменить имя метода отражения "getTetherableIfaces" на "getTetherIfaces", изменить "tether" на "untether".
Пожалуйста, проверьте.
Это должно работать на всех телефонах, подтверждено на некоторых устройствах Android 7,6 и 5;
Метод: интерфейс rndisX (обычно rndis0) отображается только при включенном usb-модеме.
Пример кода:
private static boolean isTetheringActive(Context context){
try{
for(Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();){
NetworkInterface intf=en.nextElement();
for(Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();){
InetAddress inetAddress=enumIpAddr.nextElement();
if(!intf.isLoopback()){
if(intf.getName().contains("rndis")){
return true;
}
}
}
}
}catch(Exception e){e.printStackTrace();}
return false;
}
Вот решение для прослушивания изменений состояния привязки:
Для начала вам необходимо ознакомиться с BroadcastReceiver. Вы можете найти много учебников (Google: как прослушать изменения подключения...)
Чтобы получить обновление состояния привязки, вам нужно использовать скрытое действие фильтра Android (см. ConnectivityManager)
и в вашем классе BroadcastReceiver:
IntentFilter filter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED");
затем зарегистрируйте фильтр в BroadcastReceiver:
myApplicationContext.registerReceiver(this, filter);
в вашем методе onReceive (конечный контекст, конечное намерение) информация Intent.extras содержит 3 массива, заполненных соответствующим привязанным сетевым интерфейсом: erroredArray / availableArray / activeArray
Это немного сложно, но вы можете получить информацию о состоянии привязки.
Кроме того, вы можете отразить скрытые функции кода Android:
Ищи getTetherableIfaces()
в диспетчере подключений.
Вы можете получить сетевые интерфейсы и проверить, что активно, следующим образом:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
NetworkInterface rndis = null;
NetworkInterface wlan = null;
while(interfaces.hasMoreElements()) {
NetworkInterface nif = interfaces.nextElement();
if(hasIP4Address(nif)) {
if(nif.getDisplayName().startsWith("rndis"))
rndis = nif;
else if (nif.getDisplayName().startsWith("wlan"))
wlan = nif;
}
}
// Let the user choose Wi-Fi or rndis connect
if (rndis != null) {
socket.setNetworkInterface(rndis);
Log.i(TAG, "Subscribe: with interface rndis");
} else if(wlan != null) {
socket.setNetworkInterface(wlan);
Log.i(TAG, "Subscribe: with interface wlan");
}
Я обнаружил, что если я проверяю сетевой интерфейс usb0, он имеет IP-адрес только после того, как модем настроен.
public static String getIPAddressUsb(final boolean useIPv4) {
try {
final List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (final NetworkInterface intf : interfaces) {
if (intf.getDisplayName().startsWith("usb")) {
final List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
for (final InetAddress addr : addrs) {
final String sAddr = addr.getHostAddress().toUpperCase();
final boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
if (useIPv4) {
if (isIPv4) { return sAddr; }
} else {
if (!isIPv4) {
final int delim = sAddr.indexOf('%');
return delim < 0 ? sAddr : sAddr.substring(0, delim);
}
}
}
}
}
} catch (final Exception ex) {
// for now eat exceptions
}
return "";
}
boolean isUsbTethered(){
String ipAddr = MipnAndroidApplication.getIPAddressUsb(true);
if (ipAddr.length() == 0) {
Log.i(LOG_TAG, "tethering not enabled");
return false;
} else {
Log.i(LOG_TAG, "tethering enabled :)");
return true;
}
}