I am working on a little app to check the signal strength of various network operators in my area. My current operators signal is quite unstable and I want to look into the
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 issueabout this.
private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onCallForwardingIndicatorChanged(boolean cfi) {
super.onCallForwardingIndicatorChanged(cfi);
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//checkInternetConnection();
String callState = "UNKNOWN";
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
callState = "IDLE";
break;
case TelephonyManager.CALL_STATE_RINGING:
callState = "Ringing (" + incomingNumber + ")";
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callState = "Offhook";
break;
}
Log.i("Phone Stats", "onCallStateChanged " + callState);
super.onCallStateChanged(state, incomingNumber);
}
@Override
public void onCellLocationChanged(CellLocation location) {
String cellLocationString = location.toString();
super.onCellLocationChanged(location);
}
@Override
public void onDataActivity(int direction) {
String directionString = "none";
switch (direction) {
case TelephonyManager.DATA_ACTIVITY_IN:
directionString = "IN";
break;
case TelephonyManager.DATA_ACTIVITY_OUT:
directionString = "OUT";
break;
case TelephonyManager.DATA_ACTIVITY_INOUT:
directionString = "INOUT";
break;
case TelephonyManager.DATA_ACTIVITY_NONE:
directionString = "NONE";
break;
default:
directionString = "UNKNOWN: " + direction;
break;
}
Log.i("Phone Stats", "onDataActivity " + directionString);
super.onDataActivity(direction);
}
@Override
public void onDataConnectionStateChanged(int state,int networktype) {
String connectionState = "Unknown";
switch (state ) {
case TelephonyManager.DATA_CONNECTED :
connectionState = "Connected";
break;
case TelephonyManager.DATA_CONNECTING:
connectionState = "Connecting";
break;
case TelephonyManager.DATA_DISCONNECTED:
connectionState = "Disconnected";
break;
case TelephonyManager.DATA_SUSPENDED:
connectionState = "Suspended";
break;
default:
connectionState = "Unknown: " + state;
break;
}
super.onDataConnectionStateChanged(state);
Log.i("Phone Stats", "onDataConnectionStateChanged "
+ connectionState);
}
@Override
public void onMessageWaitingIndicatorChanged(boolean mwi) {
super.onMessageWaitingIndicatorChanged(mwi);
}
@Override
public void onServiceStateChanged(ServiceState serviceState) {
String serviceStateString = "UNKNOWN";
switch (serviceState.getState()) {
case ServiceState.STATE_IN_SERVICE:
serviceStateString = "IN SERVICE";
break;
case ServiceState.STATE_EMERGENCY_ONLY:
serviceStateString = "EMERGENCY ONLY";
break;
case ServiceState.STATE_OUT_OF_SERVICE:
serviceStateString = "OUT OF SERVICE";
break;
case ServiceState.STATE_POWER_OFF:
serviceStateString = "POWER OFF";
break;
default:
serviceStateString = "UNKNOWN";
break;
}
Log.i("Phone Stats", "onServiceStateChanged " + serviceStateString);
super.onServiceStateChanged(serviceState);
}
@Override
public void onSignalStrengthChanged(int asu) {
Log.i("Phone Stats", "onSignalStrengthChanged " + asu);
setSignalLevel( asu);
super.onSignalStrengthChanged(asu);
}
private void setSignalLevel(int level) {
int sLevel = (int) ((level / 31.0) * 100);
Log.i("signalLevel ", "" + sLevel);
}
};
As I have no 50 reputation points, here is the result of my searches about the subject :
The solution of Alejandro Colorado seems to be the good one. But the problem is that the classes used to achieve it are reserved for android system applications, i.e. apps which are signed with the same signature key as the system.
How could it be possible? I found two way to achieve this.
The first one is to ask a job at any manufacturer compagny, and sign their NDA, but eh, that's not a really good solution. Especially as the app implemented and signed with this key will only work on devices from the compagny...
The second one, much more enjoyable, but i warn you, it's not gonna be easy, is to make your own ROM. You'll have to create your application, insert it in the /system/app/ directory of your ROM and recompile it to flash your device with your new system. But there's a question i've not answered yet, is the problem of unrecognised ROM signature. I think the best way to avoid this problem is to add your ROM signing key in the Recovery you'll be using.
That's where i am at this point, maybe you could find these research usefull, i hope so! I'll come back later if i find some more informations for you guys. Bye.
Maybe these quotes and links can help you code your own solution:
1.- To get a list of available network providers (quoting How to get a list of available network providers? in full):
Since Android is open source I had a look at the sources and finally found something called INetworkQueryService. I guess you can do the same as the android settings implementation and interact with this service. Some guidance through NetworkSettings.java:
- onCreate starts the NetworkQueryService and binds it.
- loadNetworksList() tells the service to query for network operators.
- INetworkQueryServiceCallback is evaluated and if the event "EVENT_NETWORK_SCAN_COMPLETED" was raised, networksListLoaded will be called to iterate over the available Networks.
2.- Even a quick read to NetworkSetting.java and INetworkQueryService interface, gives us an idea to achieve your goal.
/** * Service connection code for the NetworkQueryService. * Handles the work of binding to a local object so that we can make * the appropriate service calls. */ /** Local service interface */ private INetworkQueryService mNetworkQueryService = null; /** Service connection */ private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() { /** Handle the task of binding the local object to the service */ public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("connection created, binding local service."); mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService(); // as soon as it is bound, run a query. loadNetworksList(); } /** Handle the task of cleaning up the local binding */ public void onServiceDisconnected(ComponentName className) { if (DBG) log("connection disconnected, cleaning local binding."); mNetworkQueryService = null; } };
Intent intent = new Intent(this, NetworkQueryService.class); ... startService (intent); bindService (new Intent(this, NetworkQueryService.class), mNetworkQueryServiceConnection, Context.BIND_AUTO_CREATE);
private void loadNetworksList() { ... // delegate query request to the service. try { mNetworkQueryService.startNetworkQuery(mCallback); } catch (RemoteException e) { } displayEmptyNetworkList(false); }
/** * This implementation of INetworkQueryServiceCallback is used to receive * callback notifications from the network query service. */ private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() { /** place the message on the looper queue upon query completion. */ public void onQueryComplete(List<OperatorInfo> networkInfoArray, int status) { if (DBG) log("notifying message loop of query completion."); Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED, status, 0, networkInfoArray); msg.sendToTarget(); } };
private void networksListLoaded(List<OperatorInfo> result, int status) { ... if (status != NetworkQueryService.QUERY_OK) { ... displayNetworkQueryFailed(status); displayEmptyNetworkList(true); } else { if (result != null){ displayEmptyNetworkList(false); ... } else { displayEmptyNetworkList(true); } } }
I hope it helps. I think it's an interesting challenge so maybe I'll give it a try next time I have some spare time. Good luck!