您的位置:首页 > 理论基础 > 计算机网络

通过广播方式获取当前网络类型,如果是Wifi,获取对应的信息(附加有root之后可实现保存的无线网名称及密码获取)

2018-01-12 22:12 1126 查看
设备当前网络状态的获取有很多的方式,今天说一下自定义广播的方式,同时实现网络数据回传显示的效果;实现原理和上一篇一样,面向接口的广播接收者开发;具体看下面代码实现

1,布局文件和上一篇一样,由于篇幅所以写成两篇,activity_main.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="pay.com.huaya.broadcastrecevierup.MainActivity">

<TextView
android:id="@+id/tv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="8" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click1"
android:text="发送自定义广播" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click2"
android:text="发送带权限广播" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click3"
android:text="当前机器状态" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click4"
android:text="当前网络状态" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click5"
android:text="当前电量" />
</LinearLayout>
</ScrollView>
</LinearLayout>

2,广播接收者InternetStateReceiver的代码如下:

package pay.com.huaya.broadcastrecevierup.MyBroadcastReceiverPackage;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

import pay.com.huaya.broadcastrecevierup.InfoProvider;
import pay.com.huaya.broadcastrecevierup.Utils.NetWorkUtils;

/**
* author:why
* created on: 2018/1/10 10:21
* description:
*/
public class InternetStateReceiver extends BroadcastReceiver {
private NetWorkUtils netWorkUtils;
private ConnectivityManager myConnectivityManager;
private InfoProvider infoProvider;
@Override
public void onReceive(Context context, Intent intent) {
//调用网络工具类获取网络信息
netWorkUtils=new NetWorkUtils();
String status =NetWorkUtils.getNetworkState(context);
infoProvider.getConnectInfo(""+status);
}

//设置infoProvider成员,实现activity中对成员变量初始化
public void setInfoProvider(InfoProvider infoProvider) {
this.infoProvider = infoProvider;
}
}


3,这里我就把接口InfoProvider独立出来了,其代码如下:

package pay.com.huaya.broadcastrecevierup;

/**
* author:why
* created on: 2018/1/11 11:32
* description:
*/
public interface InfoProvider {

//获取网络连接状态信息

public void getConnectInfo(String connectInfo);

}

4,MainActivity代码:

package pay.com.huaya.broadcastrecevierup;

import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import pay.com.huaya.broadcastrecevierup.MyBroadcastReceiverPackage.InternetStateReceiver;
import pay.com.huaya.broadcastrecevierup.Utils.NetWorkUtils;

public class MainActivity extends AppCompatActivity implements InfoProvider {

public InternetStateReceiver internetStateReceiver;
public TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化界面
initUI();

//网络状态广播接收者动态注册
internetStateReceiver = new InternetStateReceiver();
IntentFilter internetIntentfilter = new    IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
internetStateReceiver.setInfoProvider(this);
registerReceiver(internetStateReceiver, intentFilter);
}

private void initUI() {
textView = findViewById(R.id.tv_1);
}

//获取网络状态
public void click4(View view) {
String status = NetWorkUtils.getNetworkState(this);
textView.setText("当前网络:"+status);
}

//重写接口方法

@Override
public void getConnectInfo(String connectInfo) {

textView.setText("回调回来的信息:" + connectInfo);
}

}

5,因为这里有一些网络权限相关的东西,所以给出AndroidManifest.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pay.com.huaya.broadcastrecevierup">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!--网络状态-->
<receiver android:name=".MyBroadcastReceiverPackage.InternetStateReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</receiver>
</application>
<!--额外的权限-->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>

</manifest>

6,在广播接收者中使用了一个获取网络信息的工具类NetWorkUtils代码如下:

package pay.com.huaya.broadcastrecevierup.Utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;

import static android.content.Context.WIFI_SERVICE;

/**
* author:why
* created on: 2018/1/12 13:37
* description:
*/
public class NetWorkUtils {

//获取网络状态类型
public static String getNetworkState(Context context) {
//获取系统的网络服务
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

//如果当前没有网络
if (null == connManager)
return null;

//获取当前网络类型,如果为空,返回无网络
NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
return "NO Network";
}

// 判断连接的是不是wifi
NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (null != wifiInfo) {
NetworkInfo.State state = wifiInfo.getState();
if (null != state)
if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {

//获取无线网描述
WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
WifiInfo wifiName = wifiManager.getConnectionInfo();
return "已连接WIFI"+"  无线网描述:"+wifiName;
//                    try {
/**
*  测试机root之后可以获取无线网密码,本工具类获取的一组的无线网数据(之前保存过)
*  然后将单个wifi信息保存在一个WifiData对象中,然后放在ArraylList中存储,想要获取或者展示
*  从列表中获取;你可以丰富工具类,添加带有参数的方法,实现对wifi信息的过滤提取等
*/
//                        return new WiFiUtils().Read();
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
}
}

// 如果不是wifi,则判断当前连接的是运营商的哪种网络2g、3g、4g等
NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

if (null != networkInfo) {
NetworkInfo.State state = networkInfo.getState();
String strSubTypeName = networkInfo.getSubtypeName();
if (null != state)
if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
switch (activeNetInfo.getSubtype()) {
//2G网络,还可以区分联通,电信,移动,这里不细分,
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
return "2G NetWork";
//3G网络,还可以区分联通,电信,移动,这里不细分,
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
return "3G Network";
//如果是4g类型
case TelephonyManager.NETWORK_TYPE_LTE:
return "4G Network";
default:
//中国移动 联通 电信 三种3G制式
if (strSubTypeName.equalsIgnoreCase("TD-SCDMA") || strSubTypeName.equalsIgnoreCase("WCDMA") || strSubTypeName.equalsIgnoreCase("CDMA2000")) {
return "3G Network";
} else {
return "NETWORN_MOBILE";
}
}
}
}
return "No NetWork";
}
}

注意上面的工具类中,假如当前网络是Wifi我们做了一个特殊的处理,返回当前连接wife的信息(包括速度,名称等等);在回传数据方法的下面有一段注释的代码,需要在设备root之后才可以使用,就是不仅能够获取无线网的描述信息,还可以获取之前保存过的无线网的密码,里面涉及到另一个工具类WiFiUtils,我在这里也给出源码(后续会修改);

package pay.com.huaya.broadcastrecevierup.Utils;

//import android.net.wifi.WifiInfo;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* author:why
* created on: 2018/1/12 15:16
* description:
*/
public class WiFiUtils {
public String Read() throws Exception {
List<WifiData> wifiInfos = new ArrayList<WifiData>();
Process process = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
StringBuffer wifiConf = new StringBuffer();
try {
process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
dataInputStream = new DataInputStream(process.getInputStream());
dataOutputStream
.writeBytes("cat /data/misc/wifi/*.conf\n");
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
InputStreamReader inputStreamReader = new InputStreamReader(
dataInputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
wifiConf.append(line);
}
bufferedReader.close();
inputStreamReader.close();
process.waitFor();
} catch (Exception e) {
throw e;
} finally {
try {
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (dataInputStream != null) {
dataInputStream.close();
}
process.destroy();
} catch (Exception e) {
throw e;
}
}

Pattern network = Pattern.compile("network=\\{([^\\}]+)\\}", Pattern.DOTALL);
Matcher networkMatcher = network.matcher(wifiConf.toString());
while (networkMatcher.find()) {
String networkBlock = networkMatcher.group();
Pattern ssid = Pattern.compile("ssid=\"([^\"]+)\"");
Matcher ssidMatcher = ssid.matcher(networkBlock);

if (ssidMatcher.find()) {
WifiData wifiInfo = new WifiData();
wifiInfo.Ssid = ssidMatcher.group(1);
Pattern psk = Pattern.compile("psk=\"([^\"]+)\"");
Matcher pskMatcher = psk.matcher(networkBlock);
if (pskMatcher.find()) {
wifiInfo.Password = pskMatcher.group(1);
} else {
wifiInfo.Password = "无密码";
}
wifiInfos.add(wifiInfo);
}
}
return "name:"+wifiInfos.get(0).Ssid+"  password:"+wifiInfos.get(0).Password;
}
}

注意事项:

网络状态属于系统广播,可以静态注册,很容易实现当网络变化的时候广播发送,但是我这里想自己随时随地获取并显示网络信息,所以写了一个自定义广播并动态注册了
网络我没有细分联通,移动和电信等,但是是可以实现的
获取wifi的名称很简单,但是无线网的密码的有管理员权限才可以,所以的先root设备(如果想要获取并显示)
我这里把以前保存过得无线网名称和密码都保存在一个集合中,元素是一个自定义类(实体),其中只有两个成员无线网名称和密码,如下:


package pay.com.huaya.broadcastrecevierup.Utils;

/**
* author:why
* created on: 2018/1/12 15:34
* description:
*/
public class WifiData {
public String Ssid="";
public String Password="";
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐