最近到處在跑著找工作,難免在面試過程中遇到這樣那樣的問題,記得最清楚一次在面試過程中被問到,當手機處於弱網狀態下,如何處理,如何監聽網路訊號強度變化。但是真是蒙了,回答的亂七八糟,思路一點都不明確。今天小編在這裡帶領大家瞭解下關於手機訊號強度的相關幾個概念。
Android手機訊號強度介紹
android定義了2種訊號單位:dBm和asu。它們之間的關係是:dBm =-113+2asu,這是google給android手機定義的特有訊號單位。例如,我的訊號強度為-53dBm,則對應30asu,因為-53 = -113 + (230) 。
詳細介紹兩者:
asu:alone signal unit 獨立訊號單元,是一種類比訊號。ASU僅僅代表手機將它的位置傳遞給附近的訊號塔的速率。它和dBm測量的是一樣的東西,但是是以一種更加線性方式來表示。
dBm:是一個表示功率絕對值的值(也可以認為是以1mW功率為基準的一個比值),計算公式為:10log(功率值/1mw)。
[例] 如果功率P為1mw,折算為dBm後為0dBm。
[例] 對於0.01mW的功率,按dBm單位進行折算後的值應為: 10log(0.01/1)=-20dBm。
這個數值越大,表明訊號越好。由於手機訊號強度一般較小,折算成為dBm一般都是負數。
中國移動的規範規定,手機接收電平>=(城市取-90dBm;鄉村取-94dBm) 時,則滿足覆蓋要求,
也就是說此處無線訊號強度滿足覆蓋要求.-67dBm要比-90dBm訊號要強20多個dB,
那麼它在打電話接通成功率和通話過程中的話音品質都會好的多。再引入一個相關概念dB。
dB:是一個表徵相對值的值,純粹的比值,只表示兩個量的相對大小關係,沒有單位,當考慮甲的功率相比於乙功率大或小多少個dB時,按下面的計算公式:10log(甲功率/乙功率),如果採用兩者的電壓 比計算,要用20log(甲電壓/乙電壓)。
[例] 甲功率比乙功率大一倍,那麼10lg(甲功率/乙功率)=10lg2=3dB,即甲的功率比乙的功率大3 dB。反之,如果甲的功率是乙的功率的一半,則甲的功率比乙的功率小3 dB。
總結:dBm是負數,越接近0訊號強度越高,訊號越好,但不可能為0。asu為正數,值越大訊號越好。dB是兩個量之間的比值,表示兩個量間的相對大小,而dBm則是表示功率絕對大小的值。
關於對數運算,不記得的自行複習一下了。
下面再來瞭解一下網路類型吧,還是很多的,不過在國內只要瞭解國內三大電訊廠商的網路類型大概就可以了。
電信
2G CDMA
3G CDMA2000
4G TD-LTE,FDD-LTE
移動
2G GSM
3G TD-SCDMA
4G TD-LTE,FDD-LTE
聯通
2G GSM
3G WCDMA
4G TD-LTE,FDD-LTE
而GoogleAPI給我們提供的有19種類型,在TelephonyManager類中定義,具體如下
/** Network type is unknown */public static final int NETWORK_TYPE_UNKNOWN = 0;/** Current network is GPRS */public static final int NETWORK_TYPE_GPRS = 1;/** Current network is EDGE */public static final int NETWORK_TYPE_EDGE = 2;/** Current network is UMTS */public static final int NETWORK_TYPE_UMTS = 3;/** Current network is CDMA: Either IS95A or IS95B*/public static final int NETWORK_TYPE_CDMA = 4;/** Current network is EVDO revision 0*/public static final int NETWORK_TYPE_EVDO_0 = 5;/** Current network is EVDO revision A*/public static final int NETWORK_TYPE_EVDO_A = 6;/** Current network is 1xRTT*/public static final int NETWORK_TYPE_1xRTT = 7;/** Current network is HSDPA */public static final int NETWORK_TYPE_HSDPA = 8;/** Current network is HSUPA */public static final int NETWORK_TYPE_HSUPA = 9;/** Current network is HSPA */public static final int NETWORK_TYPE_HSPA = 10;/** Current network is iDen */public static final int NETWORK_TYPE_IDEN = 11;/** Current network is EVDO revision B*/public static final int NETWORK_TYPE_EVDO_B = 12;/** Current network is LTE */public static final int NETWORK_TYPE_LTE = 13;/** Current network is eHRPD */public static final int NETWORK_TYPE_EHRPD = 14;/** Current network is HSPA+ */public static final int NETWORK_TYPE_HSPAP = 15;/** Current network is GSM {@hide} */public static final int NETWORK_TYPE_GSM = 16;/** Current network is TD_SCDMA {@hide} */public static final int NETWORK_TYPE_TD_SCDMA = 17;/** Current network is IWLAN {@hide} */public static final int NETWORK_TYPE_IWLAN = 18;
下面通過一些執行個體來測試一下吧
首先記得加許可權
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
執行個體代碼
public class MainActivity extends AppCompatActivity {private static final int NETWORKTYPE_WIFI = 0;private static final int NETWORKTYPE_4G = 1;private static final int NETWORKTYPE_2G = 2;private static final int NETWORKTYPE_NONE = 3;public TextView mTextView;public TelephonyManager mTelephonyManager;public PhoneStatListener mListener;/*** 網路訊號強度監聽** @param savedInstanceState*/@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextView = (TextView) findViewById(R.id.textview);//擷取telephonyManagermTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);//開始監聽mListener = new PhoneStatListener();//監聽訊號強度mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);}@Overrideprotected void onResume() {super.onResume();mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);}@Overrideprotected void onPause() {super.onPause();//使用者不在當前頁面時,停止監聽mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_NONE);}private class PhoneStatListener extends PhoneStateListener {//擷取訊號強度@Overridepublic void onSignalStrengthsChanged(SignalStrength signalStrength) {super.onSignalStrengthsChanged(signalStrength);//擷取網路訊號強度//擷取0-4的5種訊號層級,越大訊號越好,但是api23開始才能用// int level = signalStrength.getLevel();int gsmSignalStrength = signalStrength.getGsmSignalStrength();//擷取網路類型int netWorkType = getNetWorkType(MainActivity.this);switch (netWorkType) {case NETWORKTYPE_WIFI:mTextView.setText("當前網路為wifi,訊號強度為:" + gsmSignalStrength);break;case NETWORKTYPE_2G:mTextView.setText("當前網路為2G移動網路,訊號強度為:" + gsmSignalStrength);break;case NETWORKTYPE_4G:mTextView.setText("當前網路為4G移動網路,訊號強度為:" + gsmSignalStrength);break;case NETWORKTYPE_NONE:mTextView.setText("當前沒有網路,訊號強度為:" + gsmSignalStrength);break;case -1:mTextView.setText("當前網路錯誤,訊號強度為:" + gsmSignalStrength);break;}}}public static int getNetWorkType(Context context) {int mNetWorkType = -1;ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo networkInfo = manager.getActiveNetworkInfo();if (networkInfo != null && networkInfo.isConnected()) {String type = networkInfo.getTypeName();if (type.equalsIgnoreCase("WIFI")) {mNetWorkType = NETWORKTYPE_WIFI;} else if (type.equalsIgnoreCase("MOBILE")) {return isFastMobileNetwork(context) ? NETWORKTYPE_4G : NETWORKTYPE_2G;}} else {mNetWorkType = NETWORKTYPE_NONE;//沒有網路}return mNetWorkType;}/**判斷網路類型*/private static boolean isFastMobileNetwork(Context context) {TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {//這裡只簡單區分兩種類型網路,認為4G網路為快速,但最終還需要參考訊號值return true;}return false;}}
關於訊號擷取流程,這個還需深入研究,目前只在應用程式層簡單擷取了網路訊號。
以上所述是小編給大家介紹的Android手機訊號強度檢測詳細介紹,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!