终端接入到专网APN,要求增加网络检测,一旦检测到公网连接,需要断开网络。
1、增加网络检测工具类PolicyManagerUtilsl,将工具类加入到一个系统服务,并放在
/frameworks/base/services/core/java/com/android/server/相应的系统服务目录。
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class PolicyManagerUtils {
public static void monitorInternet(PolicyManagerService policyManagerService,Context context){
NetworkStatusCallback listener = new NetworkStatusCallback(policyManagerService,context);
ConnectivityManager connMgr=null;
connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connMgr != null) {//
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
connMgr.registerNetworkCallback(nr, listener);
}
}
private static class NetworkStatusCallback extends ConnectivityManager.NetworkCallback {
private static final String TAG = "NetworkStatusCallback";
private Context context;
private ConnectivityManager manager;
private PolicyManagerService policyManagerService;
public NetworkStatusCallback(PolicyManagerService policyManagerService,Context context) {
this.context = context;
this.policyManagerService=policyManagerService;
this.manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
isNetworkEnable();
}
@Override
public void onLosing(Network network, int maxMsToLive) {
super.onLosing(network, maxMsToLive);
}
@Override
public void onLost(Network network) {
super.onLost(network);
isNetworkEnable();
}
@Override
public void onUnavailable() {
super.onUnavailable();
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
}
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
super.onLinkPropertiesChanged(network, linkProperties);
}
private void isNetworkEnable() {
NetworkInfo active = manager.getActiveNetworkInfo();
boolean result = null != active &&
active.getState() == NetworkInfo.State.CONNECTED;
if(result){
new Thread(){
@Override
public void run() {
boolean isAccessInternet=false;
isAccessInternet=isDomainAccessible();
if(!isAccessInternet){
isAccessInternet=httpnet();
}
if(isAccessInternet){
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(telephonyManager!=null) {
if(telephonyManager.isDataEnabled()) {
Log.e(TAG,"disable Telephony network");
telephonyManager.setDataEnabled(false);
}
}
android.net.wifi.WifiManager wifiManager = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if(wifiManager!=null) {
if(wifiManager.isWifiEnabled()) {
Log.e(TAG,"disable wifi network");
wifiManager.setWifiEnabled(false);
}
}
NetWaringBroadcast(context);
}
}
}.start();
}
}
private static final String SETTINGS_PKG="com.android.settings";
private static final String SETTINGS_NETWARNING_RECEIVER_PATH="com.android.settings.PublicNetworkWarningReceiver";
public static void NetWaringBroadcast(Context context){
Intent intent = new Intent();
intent.setAction("network.warning.receiver");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.putExtra("MSG","监测到互联网连接,关闭连接");
intent.setComponent(new ComponentName(SETTINGS_PKG, SETTINGS_NETWARNING_RECEIVER_PATH));
context.sendBroadcast(intent);
}
private boolean httpnet(){
URL url = null;
boolean isHttpget=false;
try {
//url = new URL("https://www.baidu.com");
url = new URL("https://m.baidu.com");
HttpURLConnection connection =(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
Log.e(TAG,String.valueOf(responseCode));
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
inputStream.close();
isHttpget= true;
} else {
System.out.println("Response Code: " + responseCode);
isHttpget=false;
}
//
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return isHttpget;
}
private boolean isDomainAccessible() {
try {
InetAddress inetAddress = InetAddress.getByName("m.baidu.com");
if(inetAddress.isLoopbackAddress()) {
Log.d(TAG, "DNS,IP Address,isLoopbackAddress: " + inetAddress.getHostAddress()+"skip,retrurn false");
return false;
}else {
Log.e(TAG, "DNS,IP Address,is not a LoopbackAddress: " + inetAddress.getHostAddress() + "skip,retrurn true");
return true;
}
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
}
}
}
}
在系统服务里面调用:
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET,"YourManagerService");
PolicyManagerUtils.monitorInternet(PolicyManagerService.this,mContext);
原理是一旦网络可用,先ping下百度,如果不通,再http get下百度,两项不通过,认为是没有连接到互联网。
isDomainAccessible()是检测本地网络环回,有可能访问的m.baidu.com是127.0.0.1,这样本地能ping通。
2、打开/packages/apps/Settings/AndroidManifest.xml,在xml的最后增加一个广播接收PublicNetworkWarningReceiver。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settings"
coreApp="true"
android:sharedUserId="android.uid.system">
<original-package android:name="com.android.settings"/>
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
...................................................
<receiver android:name=".PublicNetworkWarningReceiver"
android:exported="true" >
<intent-filter>
<action android:name="network.warning.receiver" />
</intent-filter>
</receiver>
</application>
</manifest>
3、在/packages/apps/Settings/src/com/android/settings/下创建广播接收PublicNetworkWarningReceiver.java。
package com.android.settings;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class PublicNetworkWarningReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("NetworkWarning","NetworkWarning received");
String msg=intent.getStringExtra("MSG");
if(msg!=null&&msg.length()!=0) {
Log.e("NetworkWarning","NetworkWarning toast");
new Handler(context.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
});
}
}
}
最后编译系统。