Android how to obtain signal strength [duplicate] - android

I am trying to write a very simple Android application that checks the signal strength of the current cell. So far, I have only found something called getNeighboringCellInfo(), but I'm not really sure if that includes the current cell.
How do I get the CURRENT cell signal strength in Android?
Does getNeighborCellInfo() get the current cell? It doesn't seem like it based on the results that I have been able to get with it. Here's my current code:
List<NeighboringCellInfo> n = tm.getNeighboringCellInfo();
//Construct the string
String s = "";
int rss = 0;
int cid = 0;
for (NeighboringCellInfo nci : n)
{
cid = nci.getCid();
rss = -113 + 2*nci.getRssi();
s += "Cell ID: " + Integer.toString(cid) + " Signal Power (dBm): " +
Integer.toString(rss) + "\n";
}
mainText.setText(s);

create a PhoneStateListener and handle the onSignalStrengthChanged callback. When your app is initialized, it should give you an initial notification. This is in 1.x. in 2.x, there's an open issue about this.

This code may help:
PhoneStateListener phoneStateListener = new PhoneStateListener() {
public void onCallForwardingIndicatorChanged(boolean cfi) {}
public void onCallStateChanged(int state, String incomingNumber) {}
public void onCellLocationChanged(CellLocation location) {}
public void onDataActivity(int direction) {}
public void onDataConnectionStateChanged(int state) {}
public void onMessageWaitingIndicatorChanged(boolean mwi) {}
public void onServiceStateChanged(ServiceState serviceState) {}
public void onSignalStrengthChanged(int asu) {}
};
Once you’ve created your own Phone State Listener, register it with the Telephony Manager using a bitmask to indicate the events you want to listen for, as shown in the following code snippet:
TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
PhoneStateListener.LISTEN_CALL_STATE |
PhoneStateListener.LISTEN_CELL_LOCATION |
PhoneStateListener.LISTEN_DATA_ACTIVITY |
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
PhoneStateListener.LISTEN_SERVICE_STATE |
PhoneStateListener.LISTEN_SIGNAL_STRENGTH);
Also, need to add these to AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Below code will create effect like picture (Android system Cell Info)
Inside your running activity/fragment, create a sub class like this
TextView txtSignalMobile1 = findViewById...;
class myPhoneStateListener extends PhoneStateListener {
public int signalStrengthValue;
public int signalLevel;
#RequiresApi(api = Build.VERSION_CODES.Q)
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
if (signalStrength.isGsm()) {
if (signalStrength.getGsmSignalStrength() != 99)
signalStrengthValue = signalStrength.getGsmSignalStrength() * 2 - 113;
else{
signalStrengthValue = signalStrength.getCellSignalStrengths().get(0).getDbm();
signalLevel =signalStrength.getCellSignalStrengths().get(0).getAsuLevel();
}
} else {
signalStrengthValue = signalStrength.getCdmaDbm();
}
txtSignalMobile1.setText(signalStrengthValue + "dbm, " + signalLevel + "asu");
}
}
Call somewhere else maybe onCreate or after a button... (used thread to update continnously value changed)
Thread splashThread2 = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
requireActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// update TextView here!
int signal2 = NetworkUtils.GetWifiSignal(requireContext());
txtSignalWifi.setText(signal2 + "/100");
}
});
}
} catch (Exception ignore) {
// when user exit suddenly
}
}
};
splashThread2.start();

Related

Android - Navigating through USSD menu using pre-determined inputs sent via requests

I am planning to create an Android App that will automate sending a users response to a USSD Menu. At a click of a button, the app will send the initial code, followed by the rest of the menu inputs.
For example, the initial number is *143#, followed by 1, 1, 1, and a user PIN. I'd like to be able to automate that sequence of inputs so that the user won't have to input it on their own.
I know that in Android Oreo, they implemented a USSD Callback using the TelephonyManager, where the Android App can send a USSD Request, and then read the response given.
I am currently exploring that option and this is what I've tried so far. Heavily lifted from this StackOverflow Question.
interface UssdResultNotifiable {
void notifyUssdResult(String request, String returnMessage, int resultCode);
}
public class MainActivity extends Activity implements UssdResultNotifiable {
USSDSessionHandler hdl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onUssdSend(View view) {
hdl = new USSDSessionHandler(MainActivity.this, MainActivity.this);
hdl.doSession(((EditText) this.findViewById(R.id.ussdText)).getText().toString());
}
#Override
public void notifyUssdResult(final String request, final String returnMessage, final int resultCode) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Request was " + request + "\n response is "
+ returnMessage + "\n result code is " + resultCode, Toast.LENGTH_LONG).show();
Log.e(TAG, "ussd result hit! Response is = " + returnMessage);
hdl.doSession("1");
}
});
}
}
class USSDSessionHandler {
TelephonyManager tm;
private UssdResultNotifiable client;
private Method handleUssdRequest;
private Object iTelephony;
USSDSessionHandler(Context parent, UssdResultNotifiable client) {
this.client = client;
this.tm = (TelephonyManager) parent.getSystemService(Context.TELEPHONY_SERVICE);
try {
this.getUssdRequestMethod();
} catch (Exception ex) {
//log
}
}
private void getUssdRequestMethod() throws ClassNotFoundException, NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
if (tm != null) {
Class telephonyManagerClass = Class.forName(tm.getClass().getName());
if (telephonyManagerClass != null) {
Method getITelephony = telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
this.iTelephony = getITelephony.invoke(tm); // Get the internal ITelephony object
Method[] methodList = iTelephony.getClass().getMethods();
this.handleUssdRequest = null;
for (Method _m : methodList)
if (_m.getName().equals("handleUssdRequest")) {
handleUssdRequest = _m;
break;
}
}
}
}
#android.support.annotation.RequiresApi(api = Build.VERSION_CODES.N)
public void doSession(String ussdRequest) {
try {
if (handleUssdRequest != null) {
handleUssdRequest.setAccessible(true);
handleUssdRequest.invoke(iTelephony, SubscriptionManager.getDefaultSubscriptionId(), ussdRequest, new ResultReceiver(new Handler()) {
#Override
protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
Object p = ussdResponse.getParcelable("USSD_RESPONSE");
if (p != null) {
Method[] methodList = p.getClass().getMethods();
for(Method m : methodList){
Log.e(TAG, "onReceiveResult: " + m.getName());
}
try {
CharSequence returnMessage = (CharSequence) p.getClass().getMethod("getReturnMessage").invoke(p);
CharSequence request = (CharSequence) p.getClass().getMethod("getUssdRequest").invoke(p);
USSDSessionHandler.this.client.notifyUssdResult("" + request, "" + returnMessage, resultCode); //they could be null
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
});
}
} catch (IllegalAccessException | InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
What you get is an app that would ask for a USSD Input for the user, and once the "Send" button is hit, the USSD Response is displayed via a Toast on the notifyUssdResult function. In that same function, I send the next input in my sequence which is "1". Am I able to once again send a reply to the USSD, and the USSD takes it as the input and goes to the next menu.
However, as soon as I send the reply, the USSD menu shows up in my device and I'm unable to proceed further. I am unable to navigate the USSD Menu purely through my app, as the USSD Menu interferes with the screen and doesn't go away.
Is there any samples I can follow?
FOR EXAMPLE YOU WANT TO RUN *123# 1 then 1 then 1 then 2
so you can directly write this in string here is the code hope it helps
String s= "*123*1*1*2#"
//screen from which can get the number
if((s.startsWith("*"))&&(s.endsWith("#"))){
//if true then it is a USSD call----
callstring=s.substring(0, s.length()-1);
callstring=callstring+ Uri.encode("#");
Log.d("CALL TYPE---------->", "USSD CALL");
}else{
callstring=s;
Log.d("CALL TYPE---------->", "Not a USSD CALL");
}
Intent i=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+callstring));
startActivity(i);

Force stop android applications

After opening application details settings using
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS), how can I force stop application programmatically?
You can use Accessibility to achieve that (but it needs Accessibility for your app turned on by user)
public class MyAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
//TYPE_WINDOW_STATE_CHANGED == 32
if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event
.getEventType()) {
AccessibilityNodeInfo nodeInfo = event.getSource();
if (nodeInfo == null) {
return;
}
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByViewId("com.android.settings:id/left_button");
//We can find button using button name or button id
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
list = nodeInfo
.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
#Override
public void onInterrupt() {
// TODO Auto-generated method stub
}
}
You can check it out in this example:
AccessibilityTestService.java
You have two ways, a more rude one and a better one
The good practice
If you have only one activity running
the this.finish(); method will be enough
If you have multiple activities running
You gotta call the this.finishAffinity(); method. This is the best practice in general cases, where you can have both a single or multiple activities
The rude way
System.Exit(0);
I added this only for info, but this might not work with multiple activities and this is not a good way for closing apps. It's mostly like the "Hold power button until the pc shuts down".
Clicking an element of another application on runtime is something that will be considered as a security threat. You would need a hack to go past this hurdle.
There is one hack that I recently found out, you can probably make use of it. You can find the source code here: https://github.com/tfKamran/android-ui-automator
You can add the code in here as a module in your app and invoke a service with action com.tf.uiautomator.ACTION_CLICK_ITEM and send the text of the element you want to click on as an extra with key itemText.
You can test it using adb like:
adb shell am startservice -a com.tf.uiautomator.ACTION_CLICK_ITEM -e itemText "OK"
I found one solution for force stop. After force stop how can i go back to my activity page ?
public class DeviceAccessibilityService extends AccessibilityService {
private static final String TAG = "litan";
private boolean isKilled = false;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isKilled = false;
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
AccessibilityNodeInfo nodeInfo = event.getSource();
Log.i(TAG, "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo);
if (nodeInfo == null) {
return;
}
List<AccessibilityNodeInfo> list = new ArrayList<>();
if ("com.android.settings.applications.InstalledAppDetailsTop".equals(event.getClassName())) {
if (Build.VERSION.SDK_INT >= 18) {
list = nodeInfo.findAccessibilityNodeInfosByViewId("com.android.settings:id/right_button");
} else if (Build.VERSION.SDK_INT >= 14) {
list = nodeInfo.findAccessibilityNodeInfosByText("com.android.settings:id/right_button");
}
for (AccessibilityNodeInfo node : list) {
Log.i(TAG, "ACC::onAccessibilityEvent: left_button " + node);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
} else if ("android.app.AlertDialog".equals(event.getClassName())) {
list = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 18) {
list = nodeInfo.findAccessibilityNodeInfosByViewId("android:id/button1");
} else if (Build.VERSION.SDK_INT >= 14) {
list = nodeInfo.findAccessibilityNodeInfosByText("android:id/button1");
}
for (final AccessibilityNodeInfo node : list) {
Log.i(TAG, "ACC::onAccessibilityEvent: button1 " + node);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
return;
}
}
#Override
public void onInterrupt() {
// TODO Auto-generated method stub
Log.i("Interrupt", "Interrupt");
}
#Override
protected void onServiceConnected() {
AccessibilityServiceInfo info = getServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.flags = AccessibilityServiceInfo.DEFAULT;
info.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
info.flags = AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY;
info.flags = AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
// We are keeping the timeout to 0 as we don’t need any delay or to pause our accessibility events
info.feedbackType = AccessibilityEvent.TYPES_ALL_MASK;
info.notificationTimeout = 100;
this.setServiceInfo(info);
// Toast.makeText(getApplicationContext(), "onServiceConnected", Toast.LENGTH_SHORT).show();
}
private static void logd(String msg) {
Log.d(TAG, msg);
}
private static void logw(String msg) {
Log.w(TAG, msg);
}
private static void logi(String msg) {
Log.i(TAG, msg);
}
}

get EXTRA_CALL_DISCONNECT_CAUSE after call ended

I'm making an Android app which need to monitor when the call is disconnected and get the disconnect cause to do some more things. I'm using a broadcast receiver to know when the call is disconnected but I'm stuck at getting the disconnect cause.
Below is my brief code:
final BroadcastReceiver phoneStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
String cause = null;
if (intent.hasExtra(TelecomManager.EXTRA_CALL_DISCONNECT_CAUSE)) {
cause = intent.getExtras().getString(TelecomManager.EXTRA_CALL_DISCONNECT_CAUSE);
}
TextView callState = (TextView) findViewById(R.id.callState);
callState.setText("Call State is: " + state + " " + number + " " + cause);
}
};
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
registerReceiver(phoneStateReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
btnStop.setEnabled(true);
btnStart.setEnabled(false);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
unregisterReceiver(phoneStateReceiver);
btnStart.setEnabled(true);
btnStop.setEnabled(false);
}
});
Please, somebody helps me at this point?
Many thanks.!!!
From API-21 documentation, EXTRA_CALL_DISCONNECT_CAUSE & EXTRA_CALL_DISCONNECT_MESSAGE are optional extras for TelecomManager.ACTION_PHONE_STATE_CHANGED. Looks like they do not have any data in them in AOSP code and as observed on Nexus 5 (L & M releases). It has been left for OEMs to implement and report any data in those extras. I am looking for any devices that use these extras. It would be great to know of any devices which do report call disconnect cause / message.

How to modify Wi-Fi p2p frequency for non-rooted android?

I'm working on an Android Wi-Fi P2p project (also called WiFi direct).
This is how I try to create the group:
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
private WifiP2pManager mManager;
private Channel mChannel;
private MainActivity mActivity;
public WiFiDirectBroadcastReceiver(WifiP2pManager p2pManager,
Channel channel, MainActivity mainActivity) {
super();
this.mManager = p2pManager;
this.mChannel = channel;
this.mActivity = mainActivity;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
String state = MainActivity.wifiP2PStateMap.get(intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1));
if (state.equalsIgnoreCase("ENABLED")) {
Log.d(MainActivity.TAG, "P2P state changed to ENABLED ");
mManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.d(MainActivity.TAG, "Group created ");
}
#Override
public void onFailure(int reason) {
Log.d(MainActivity.TAG, "Failed to create Group " + MainActivity.failureMap.get(reason));
}
});
}
}else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)){
//STUB
}else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)){
//STUB
}else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
//STUB
}else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
//STUB
}
}
}
When I scan the available wifi groups using wifi-analyzer I see that my group was created on channel 1, and it is always on channel 1.
Since this channel might be over crowded with other Access points I want to use a different channel.
The problem is that Android's API does not have a visible method to change the channel.
Here I found these questions: Q1, Q2, but they suggest rooting the device which is not an option for me.
When I looked into Android's sources I found that there is a hidden method:
/** #hide */
public void setWifiP2pChannels(Channel c, int lc, int oc, ActionListener listener) {
checkChannel(c);
Bundle p2pChannels = new Bundle();
p2pChannels.putInt("lc", lc);
p2pChannels.putInt("oc", oc);
c.mAsyncChannel.sendMessage(SET_CHANNEL, 0, c.putListener(listener), p2pChannels);
}
Using reflection I tried the following:
Method setWifiP2pChannels = p2pManager.getClass().getMethod("setWifiP2pChannels", WifiP2pManager.Channel.class, int.class, int.class, WifiP2pManager.ActionListener.class);
setWifiP2pChannels.invoke(p2pManager, channel, 0, channel_to_set, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.d(MainActivity.TAG, "Changed channel (" + channel_to_set + ") succeeded");
}
#Override
public void onFailure(int reason) {
Log.d(MainActivity.TAG, "Changed channel (" + channel_to_set + ") failed");
}
});
When channel_to_set was 0 or 1 the actual channel did not change. When channel_to_set to something higher, creating a group returned an error.
Any idea how to solve this?
Thanks

Get Signal Strength in Android

I want to get the Signal Strength of the Device at the point I hit the API call. I have searched on all the related threads and I am not successful yet.
So I would like to get the signal strength like
SignalStrength ss = null ; // some initialization
int n = ss.getGsmSignalStrength();
But while using this, it is obvious that I will get null pointer exception since I have initialised SignalStrength as null. But I don't know how to initialise this.
Also that I don't want to use PhoneStateListener because it is triggered only if the signal changes.
I am getting the Signal Strength using the below code
TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
CellInfoGsm cellinfogsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0);
CellSignalStrengthGsm cellSignalStrengthGsm = cellinfogsm.getCellSignalStrength();
cellSignalStrengthGsm.getDbm();
But I don't want to use CellSignalStrength because it is only added in API Level 17 and will not work under 17. I want the code to work on API Level 7+.
Or is there any other method, so that I could get the signal strength at the point of hitting the API call?
Define Variables:
TelephonyManager mTelephonyManager;
MyPhoneStateListener mPhoneStatelistener;
int mSignalStrength = 0;
Then add this class to your code:
class MyPhoneStateListener extends PhoneStateListener {
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
mSignalStrength = signalStrength.getGsmSignalStrength();
mSignalStrength = (2 * mSignalStrength) - 113; // -> dBm
}
}
and in your onCreate method use:
mPhoneStatelistener = new MyPhoneStateListener();
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneStatelistener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
Global Define :
TelephonyManager telephonyManager;
myPhoneStateListener psListener;
TextView txtSignalStr;
onCreate Method :
#Override
protected void onCreate(final Bundle savedInstanceState) {
txtSignalStr = (TextView)findViewById(R.id.signalStrength);
psListener = new myPhoneStateListener();
telephonyManager = (TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(psListener,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
Create myPhoneStateListener Class :
public class myPhoneStateListener extends PhoneStateListener {
public int signalStrengthValue;
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
if (signalStrength.isGsm()) {
if (signalStrength.getGsmSignalStrength() != 99)
signalStrengthValue = signalStrength.getGsmSignalStrength() * 2 - 113;
else
signalStrengthValue = signalStrength.getGsmSignalStrength();
} else {
signalStrengthValue = signalStrength.getCdmaDbm();
}
txtSignalStr.setText("Signal Strength : " + signalStrengthValue);
}
}
public class PhoneCustomStateListener extends PhoneStateListener {
public int signalSupport = 0;
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
signalSupport = signalStrength.getGsmSignalStrength();
Log.d(getClass().getCanonicalName(), "------ gsm signal --> " + signalSupport);
if (signalSupport > 30) {
Log.d(getClass().getCanonicalName(), "Signal GSM : Good");
} else if (signalSupport > 20 && signalSupport < 30) {
Log.d(getClass().getCanonicalName(), "Signal GSM : Avarage");
} else if (signalSupport < 20 && signalSupport > 3) {
Log.d(getClass().getCanonicalName(), "Signal GSM : Weak");
} else if (signalSupport < 3) {
Log.d(getClass().getCanonicalName(), "Signal GSM : Very weak");
}
}
}
We should not initialize signalstrength, instead of that use phonelistener and override the method onSignalStrengthsChanged(SignalStrength signalStrength).
For eg., have a look at following code snippet
class SamplePhoneStateListener extends PhoneStateListener {
int signalStrength = 0;
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
signalStrength = signalStrength.getGsmSignalStrength();
//You can check the signal strength value here..
}
}
using TelephonyManager object you can listen to the above class like
TelephonyManagerObject.listen(myListener,
PhoneStateListener.LISTEN_SIGNAL_STRENGTHS)
This worked for me:
Which services are needed:
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
How to gather the metrics:
public void startGatherMetrics() {
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null) {
networkInfoStr = connectivityManager.getActiveNetworkInfo().toString();
// gather Network Capabilities
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network network = connectivityManager.getActiveNetwork();
networkInfoStr += "; " + connectivityManager.getNetworkCapabilities(network).toString();
}
}
Log.d("A_NETWORK_INFO", networkInfoStr);
new Thread(new Runnable() {
#Override
public void run() {
quitLooper = false;
Looper.prepare();
telephonyManager.listen(new PhoneStateListener() {
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
Log.d("A_NETWORK_METRICS",
"Signal Strength (0-4 / dBm):" + getLevel(signalStrength) + " / "
+ getDbm(signalStrength));
if (quitLooper)
Looper.myLooper().quit();
}
}, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
Looper.loop();
}
}).start();
}
public void stop() {
quitLooper = true;
}
The "getLevel(signalStrength)" and "getDbm(signalStrength)" can be found here.
You don't instantiate SignalStrength (and possibly you cannot). from application code.
You must use a PhoneStateListener (subclass), and implement onSignalStrengthsChanged:
http://developer.android.com/reference/android/telephony/PhoneStateListener.html#onSignalStrengthsChanged(android.telephony.SignalStrength)
A SignalStrength will be created for you and passed into your override.
The PhoneStateListener object should be instantiated in a looper thread. So, if you are using worker thread (non - GUI thread) the following can be used;
private HandlerThread handlerThreadCellularSignal = null;
public void startListen() {
handlerThreadCellularSignal = new HandlerThread("CELLULAR_INFO_THREAD");
handlerThreadCellularSignal.start();
Looper looper = handlerThreadCellularSignal.getLooper();
Handler handler = new Handler(looper);
handler.post(new Runnable() {
#Override
public void run() {
phoneStatelistener = new PhoneStateListenerEx();
TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(phoneStatelistener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
});
}
private void stopListen() {
handlerThreadCellularSignal.quit();
}
public class PhoneStateListenerEx extends PhoneStateListener {
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
int signalStrengthdBm = (2 * signalStrength.getGsmSignalStrength()) - 113; // -> dBm
Log.d("Cellular Signal Strength | " + String.valueOf(signalStrengthdBm));
}
}
public class myPhoneStateListener extends PhoneStateListener {
public int signalStrengthValue;
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
if (signalStrength.isGsm()) {
if (signalStrength.getGsmSignalStrength() != 99)
signalStrengthValue = signalStrength.getGsmSignalStrength() * 2 - 113;
else
signalStrengthValue = signalStrength.getGsmSignalStrength();
} else {
signalStrengthValue = signalStrength.getCdmaDbm();
}
txtSignalStr.setText("Signal Strength : " + signalStrengthValue);
}
}
Kotlin Version :
class myPhoneStateListener : PhoneStateListener() {
var signalStrengthValue = 0
override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
super.onSignalStrengthsChanged(signalStrength)
signalStrengthValue = if (signalStrength.isGsm) {
if (signalStrength.gsmSignalStrength != 99) signalStrength.gsmSignalStrength * 2 - 113 else signalStrength.gsmSignalStrength
} else {
signalStrength.cdmaDbm
}
txtSignalStr.setText("Signal Strength : $signalStrengthValue")
}
}

Categories

Resources