Odczytywanie stanu połączenia z siecią GSM (telefonia) ------------------------------------------------------- Kontynuujemy rozwój projektu 'StanUrzadzenia' 0. Niezbędne uprawnienie READ_PHONE_STATE W pliku manifestu Properties\AndroidManifest.xml, w obrębie elementu manifest: W VS/Xamarin można to też ustawić z menu Project/StanUrządzenia Properties/Android Manifest: READ_PHONE_STATE 1. W Android >=6 należy zdobyć te uprawnienia dla procesu: private const int requestReadPhoneState = 0; static private bool zdobądźUprawnieniaDoOdczytaniaWłasnościGSM(Activity activity) { Permission permissionCheck = ContextCompat.CheckSelfPermission(activity, Manifest.Permission.ReadPhoneState); if (permissionCheck != Permission.Granted) { ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.ReadPhoneState }, requestReadPhoneState); return false; } else { //Toast.makeText(activity.getApplicationContext(), "Aplikacja posiada już uprawnienia do odczytania stanu telefonu", Toast.LENGTH_LONG).show(); return true; } } Po przydzieleniu uprawnień (okno dialogowe) wywołana zostanie metoda: //tylko informacja dla użytkownika public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { switch (requestCode) { case requestReadPhoneState: if ((grantResults.Length > 0) && (grantResults[0] == Permission.Granted)) { Toast.MakeText(ApplicationContext, "Udzielono uprawnienia do odczytania stanu telefonu", ToastLength.Long).Show(); odswiezListe(); } break; default: break; } } 2. Odczytanie stanu sieci: static private UrządzenieInfo odczytajSiećTelefoniczną(Activity activity, SignalStrength signalStrength) { UrządzenieInfo gsmInfo = new UrządzenieInfo(); gsmInfo.typInformacji = TypInformacji.Inne; gsmInfo.nazwa = "Sieć GSM"; TelephonyManager tm = (TelephonyManager)activity.GetSystemService(TelephonyService); //menadzer gsm //Android.Telephony.Gsm.GsmCellLocation loc = (Android.Telephony.Gsm.GsmCellLocation)tm.CellLocation; //lokalizacja telefonu przez gsm, przestarzałe! if (tm != null) { //przy braku uprawnień tu będzie wyjątek Java.Lang.SecurityException -> warto try..catch gsmInfo.opis = "IMEI: " + tm.Imei; //gsmInfo.opis = "\nID: "+loc.Cid; gsmInfo.opis += "\nOperator: " + tm.NetworkOperatorName; string typSieciTelefonicznej = ""; switch (tm.NetworkType) { case NetworkType.OneXrtt: typSieciTelefonicznej = "1xRTT"; break; case NetworkType.Cdma: typSieciTelefonicznej = "CDMA"; break; case NetworkType.Edge: typSieciTelefonicznej = "EDGE"; break; case NetworkType.Ehrpd: typSieciTelefonicznej = "eHRPD"; break; case NetworkType.Evdo0: typSieciTelefonicznej = "EVDO rev. 0"; break; case NetworkType.EvdoA: typSieciTelefonicznej = "EVDO rev. A"; break; case NetworkType.EvdoB: typSieciTelefonicznej = "EVDO rev. B"; break; case NetworkType.Gprs: typSieciTelefonicznej = "GPRS"; break; case NetworkType.Hsdpa: typSieciTelefonicznej = "HSDPA"; break; case NetworkType.Hspa: typSieciTelefonicznej = "HSPA"; break; case NetworkType.Hspap: typSieciTelefonicznej = "HSPA+"; break; case NetworkType.Hsupa: typSieciTelefonicznej = "HSUPA"; break; case NetworkType.Iden: typSieciTelefonicznej = "iDen"; break; case NetworkType.Lte: typSieciTelefonicznej = "LTE"; break; case NetworkType.Umts: typSieciTelefonicznej = "UMTS"; break; case NetworkType.Unknown: typSieciTelefonicznej = "Nieznany"; break; default: typSieciTelefonicznej = "Inny"; break; //sic! } gsmInfo.opis += "\nTyp sieci: " + typSieciTelefonicznej; gsmInfo.opis += "\nNumer telefonu: " + tm.Line1Number; string stanPołączenia = ""; switch (tm.CallState) { case CallState.Ringing: stanPołączenia = "Dzwonienie"; break; case CallState.Offhook: stanPołączenia = "Trwa rozmowa"; //zajęty break; case CallState.Idle: stanPołączenia = "Nieaktywny"; //wolny break; } gsmInfo.opis += "\nStan połączenia: " + stanPołączenia; if (signalStrength != null) gsmInfo.polozeniePaska = signalStrength.Level * 25; //0-4, wymaga API 22 -> trzeba zwiększyć else gsmInfo.polozeniePaska = -1; } else { //brak zasięgu gsmInfo.polozeniePaska = -1; } return gsmInfo; } 3. Uruchomienie w metodzie odświeżListe: if (zdobądźUprawnieniaDoOdczytaniaWłasnościGSM(this)) { listaUrządzeń.Add(odczytajSiećTelefoniczną(this, null)); //na razie bez siły sygnału } 4. Nasłuchiwacz do monitorowania siły sygnału: _PhoneStateListener phoneStateListener = null; SignalStrength signalStrength = null; class _PhoneStateListener : PhoneStateListener { private MainActivity activity; public _PhoneStateListener(MainActivity activity) { this.activity = activity; } public override void OnSignalStrengthsChanged(SignalStrength signalStrength) { activity.signalStrength = signalStrength; //activity.odswiezListe(); //odświeżanie stąd jest zbyt częste } } Rozwinięcie kodu z metody odswiezListe if (zdobądźUprawnieniaDoOdczytaniaWłasnościGSM(this)) { if (phoneStateListener == null) phoneStateListener = new _PhoneStateListener(this); TelephonyManager tm = (TelephonyManager)this.GetSystemService(TelephonyService); tm.Listen(phoneStateListener, PhoneStateListenerFlags.SignalStrengths); listaUrządzeń.Add(odczytajSiećTelefoniczną(this, signalStrength)); //teraz przekazywanie siły sygnału } ------------------------------------------------------ Odczytywanie stanu sieci radiowej WiFi Uprawnienia: Zdobywanie uprawnień przez proces: private const int requestAccessWifiState = 1; //!!! w intencjach była ogólniejsza metoda - warto użyć jej tutaj !!! static private bool zdobądźUprawnieniaDoOdczytaniaWłasnościWiFi(Activity activity) { Permission permissionCheck = ContextCompat.CheckSelfPermission(activity, Manifest.Permission.AccessWifiState); if (permissionCheck != Permission.Granted) { ActivityCompat.RequestPermissions(activity, new String[] { Manifest.Permission.AccessWifiState }, requestAccessWifiState); return false; } else { //Toast.MakeText(activity.ApplicationContext, "Aplikacja posiada już uprawnienia do odczytania stanu telefonu", ToastLength.Long).Show(); return true; } } Zmiana w istniejącej metodzie: public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { switch (requestCode) { case requestReadPhoneState: if ((grantResults.Length > 0) && (grantResults[0] == Permission.Granted)) { Toast.MakeText(ApplicationContext, "Udzielono uprawnienia do odczytania stanu telefonu", ToastLength.Long).Show(); odswiezListe(); } break; case requestAccessWifiState: if ((grantResults.Length > 0) && (grantResults[0] == Permission.Granted)) { Toast.MakeText(ApplicationContext, "Udzielono uprawnienia do odczytania stanu sieci WiFi", ToastLength.Long).Show(); odswiezListe(); } break; default: break; } } Odczytywanie informacji o sieci WiFi: static private UrządzenieInfo odczytajSiećWiFi(Activity activity) { UrządzenieInfo wifiInfo = new UrządzenieInfo(); wifiInfo.typInformacji = TypInformacji.Inne; wifiInfo.nazwa = "Sieć WiFi"; WifiManager wm = (WifiManager)activity.ApplicationContext.GetSystemService(WifiService); if (wm != null) { WifiInfo wi = wm.ConnectionInfo; if (wi != null) { wifiInfo.opis = "SSID: " + wi.SSID; wifiInfo.opis += "\nIP: " + wi.IpAddress; wifiInfo.opis += "\nMAC: " + wi.MacAddress; int rssi = wi.Rssi; wifiInfo.polozeniePaska = WifiManager.CalculateSignalLevel(rssi, 100); } else wifiInfo.polozeniePaska = -1; wifiInfo.opis += "\nZapisane sieci: "; IList _wis = wm.ConfiguredNetworks; if (_wis != null) { foreach(WifiConfiguration _wi in _wis) { wifiInfo.opis += "\n\t" + _wi.Ssid; } } else wifiInfo.opis += "brak zapamiętanych sieci"; } else { //brak sieci wifiInfo.polozeniePaska = -1; } return wifiInfo; } Wywołanie tej metody należy dodać do odwiezListe. if(zdobądźUprawnieniaDoOdczytaniaWłasnościWiFi(this)) { listaUrządzeń.Add(odczytajSiećWiFi(this)); } Jeżeli chcemy być powiadamiani o zmianach w sieci WiFi (UWAGA! Bardzo częste powiadomienia), należy ustalić BroadcastReceiver: class WifiReceiver : BroadcastReceiver { private readonly TimeSpan czasMiędzyOdświeżeniamiWiFi = TimeSpan.FromMilliseconds(10000); DateTime? czasOstatniegoOdświeżeniaWiFi = null; MainActivity activity; public WifiReceiver(MainActivity activity) { this.activity = activity; } public override void OnReceive(Context context, Intent intent) { //UWAGA! To jest wywoływane bardzo często -> filtrowanie if (intent.Action == WifiManager.WifiStateChangedAction) { DateTime bieżącyCzas = DateTime.Now; if (czasOstatniegoOdświeżeniaWiFi == null || (bieżącyCzas - czasOstatniegoOdświeżeniaWiFi > czasMiędzyOdświeżeniamiWiFi)) { czasOstatniegoOdświeżeniaWiFi = bieżącyCzas; Toast.MakeText(context, "Zmiana stanu WiFi", ToastLength.Long).Show(); //activity.odswiezListe(); } } } } BroadcastReceiver wifiReceiver = null; W metodzie odswiezListe: if (zdobądźUprawnieniaDoOdczytaniaWłasnościWiFi(this)) { listaUrządzeń.Add(odczytajSiećWiFi(this)); if (wifiReceiver == null) wifiReceiver = new WifiReceiver(this); IntentFilter _intentFilter = new IntentFilter(WifiManager.WifiStateChangedAction); Intent _intent = ApplicationContext.RegisterReceiver(wifiReceiver, _intentFilter); }