I've got an app which connect itself programatically to a wifi connection. My problem is, I want to handle the case, that the password is wrong. I want to detect that the password is not correct in runtime. To be precise I've got a progressdialog running while the connection is established, so if the password is wrong the progressdialog is just shown all the time and can't be skipped. A further note: I handled a password which is less than 8 characters by using this code:
if(!m_wifiManager.enableNetwork(netId, true)) {
progressDialogConnecting.dismiss();
createInfoMessageDialog(CONST.WIFI_CON_FAILED_TITLE, CONST.WIFI_CON_FAILED_MSG_CONFAILURE);
m_wifiManager.reconnect();
return;
}
If the key for the wifi connection is less than 8 characters, this if-case gets triggered. But if it is longer than 8 characters and wrong I get an endless state of showing the progress dialog.
What I exactly want to ask: how do I handle 1. wrong password 2. connection states (just like Android system showing me the toasts "Connected to Wifi xyz") ? AND is it even possible to handel the first one (wrong password)?
Here is the code, that did not work for handling connection established event (this is just the wifirecevier, I also registered it in the activity):
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)){
if(wrongNetworkConnected)
progressDialogConnecting.dismiss();
}
}
} else {
}
}
}
}
Edit: What I am currently doing, is that I have a Handler which tells me to whom I am connected. That's useful because I can say that after the reconnect() I am reconnected to the old network (current network) and not the new one - so apparently the password could be wrong (or something else), because I could not connect to the new network.
The problem about this method is that first of all it takes too much time and secondly it is not reliable. I can lie and say that if you will get reconnected to your current network it is the fault of a wrong password, but actually it is not 100% sure that you cannot reconnect because of this - it may also have other reasons. So I am still searching for a simple feedback/handle from the suplicant that the password is wrong, just like the android api does in the wifi settings of each android device...
My problem is, I want to handle the case, that the password is wrong.
After some research I found this post which is not marked as answered but it still worked for me very well.
Here is the if-case in which the program jumps (already tested several times by me) if there is an authentication error --> e.g. wrong password:
int supl_error=intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if(supl_error==WifiManager.ERROR_AUTHENTICATING){
// DO SOMETHING
}
NOTE: As seen in the linked post above this if-case should appear in a BroadcastReceiver adding the intent WifiManager.SUPPLICANT_STATE_CHANGED_ACTIONto the receiver-registration in your activity-class.
Related
For the past few days i've been trying to show the online/offline status of a user.. For this i have a register activity where they register and their info gets saved in firebase and if they exit an activity i have overriden its onstop method and made the value to set to offline... but if the user suddenly loses internet connection it still shows online.. i cant change it to offline because internet is needed to make a change in the database and the use doesn't have internet... SO how do i set the database value to offline... i googled quite some stuff about this but didnt find anything... Can anyone please help me out please
My code
#Override
protected void onStart() {
super.onStart();
fetchData();
// mDatabaseReference.child("UserData").child(UID).child("Online").setValue("True");
}
#Override
protected void onStop() {
super.onStop();
fetchData();
// mDatabaseReference.child("UserData").child(UID).child("Online").setValue(false);
}
What you're trying to do is known as a presence system. The Firebase Database has a special API to allow this: onDisconnect(). When you attach a handler to onDisconnect(), the write operation you specify will be executed on the server when that server detects that the client has disconnected.
From the documentation on managing presence:
Here is a simple example of writing data upon disconnection by using the onDisconnect primitive:
DatabaseRef presenceRef = FirebaseDatabase.getInstance().getReference("disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnect().setValue("I disconnected!");
In your case this could be as simple as:
protected void onStart() {
super.onStart();
fetchData();
DatabaseReference onlineRef = mDatabaseReference.child("UserData").child(UID).child("Online");
onlineRef.setValue("True");
onlineRef.onDisconnect().setValue("False");
}
Note that this will work in simple cases, but will start to have problems for example when your connection toggles rapidly. In that case it may take the server longer to detect that the client disappears (since this may depends on the socket timing out) than it takes the client to reconnect, resulting in an invalid False.
To handle these situations better, check out the sample presence system in the documentation, which has more elaborate handling of edge cases.
DEFINITION:
My non-android device (NAD) is a Bluetooth device who loops its name from 60 to 0 and resets in an infinite fashion.
OBJECTIVE:
What I'm trying is to do is to have my android device as closely as possible detect that countdown and initiate an alarm as close to that of the NAD counter as possible.
I'm doing this by getting the native BluetoothAdapter of my device to startDiscovery() manually by tying the function to onscreen buttons and keeping an eye on the toasts I set through my BroadcastReceiver, which updates onscreen Textviews Which enables me to monitor what my device is receiving in real-time
REQUIREMENT:
System & resource efficiency is not a concern in this context.
PROBLEM:(Keep an eye out for PART 1 and PART 2 in the code)
I'm not sure how using fetchUuidsWithSdp() is helping me since the TextView it's updating remains empty and the Textview getting populated by the EXTRA_NAME extra from intent returning action ACTION_NAME_CHANGED is the cached, initial discovery name (ie. my application is not reading a name after initial discovery).
my code can be found below
Sorry for any newbie mistakes,I'm trying my best :)
public class BTBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//pulling the action name from the broadcasted intent
String action = intent.getAction();
if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
sToaster("StartedD");//show toast that Discovery has started
}
else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
sToaster("EndedD");//show toast signifying end of discovery
/*
if(notfound){
mBTAdapter.startDiscovery();
}*/
}
else if(BluetoothDevice.ACTION_FOUND.equals(action)){
//when a device is found
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//make sure it's indeed my NAD device by checking MAC address
if(device.getAddress().equals(MACAddress)){
if(notfound){
//show device name on screen
sToaster("FOUND DEvice");
notfound = false;
NAD = device;
NameShower.setText(device.getName());
}
else{
//do nothing if it's the second time the device is found
}
}
}
else if(BluetoothDevice.ACTION_NAME_CHANGED.equals(action)){
//name changed
BluetoothDevice foundDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//make sure it's indeed my NAD device
if(foundDevice.equals(NAD)){
sToaster("Name Change!"); //show on screen that the name change intent has been caught
//PART1
//to prevent caching of the old device name StackOverflow article
//advised using this function i don't totally understand yet
//NAD.fetchUuidsWithSdp();
//either commented or not commented the outcome is the same (no refresh of the name)
//PART2
//tried showing the new name two different ways below, neither of which are effective
//by inspecting the TextViews on-screen
NameShower.setText(foundDevice.getName());
EventView.setText(intent.getStringExtra(BluetoothDevice.EXTRA_NAME));
}
}
}
};
I have worked on a bluetooth project and what I perceived was that the discovery process should be in an Intent which can be left registered in the background. And to discover the devices in range, you just need to invoke the BTDevice.startDiscovery() to search them.
Generally the startDiscovery() drains battery if enabled continuously.
If you want, I can edit this post to share a snipet that I used to scan for devices.
Hope this helps !
whenever we get a call, we do see missed call notification. Is there a way to remove the missed call notification in android programatically?
We see missed calls numbers & its count. Can we remove them via code?
The only "legal" but extremely ugly and usually useless way to achieve what you want is to show Call Log to user. And I mean literally show (becomes visual, gets focus). In case you want to do this, here's how:
public static boolean showCallLog(Context context)
{
try
{
Intent showCallLog = new Intent();
showCallLog.setAction(Intent.ACTION_VIEW);
showCallLog.setType(android.provider.CallLog.Calls.CONTENT_TYPE);
context.startActivity(showCallLog);
return true;
}
catch (Exception e)
{
Log.d("Couldn't show call log.", e.getMessage());
}
return false;
}
The reason behind this mess is the fact that apps authoritatively responsible for call logging and notifying users about missed calls (stock phone apps) use cached values. Why? Because of overall performance. You need to somehow notify those apps that Call Log has changed (seen means changed, as well) and that it should update it. It would be nice if all such apps on all devices would receive a broadcast in order to refresh, but as far as I know, it's not the case.
I hope someone will find a better way to force refresh on stock phone apps.
I know most people check ConnectivityManager.CONNECTIVITY_ACTION for receiving broadcast when connectivity is changed. However, in some cases, you may only want to get notified when wireless connection is establish successfully.
Personally, my case is that I need to post a login request when user has connected to certain wirless network. After some Googling, I got to WifiManager.NETWORK_STATE_CHANGED_ACTION, but it is poorly ducumented thus its reliability is doubted. So I need to confirm whether this intent is always fired after wireless configuration has completed successfully.
Anyway, here is the code I use in my BroadcastReceiver:
public class StateChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (!networkInfo.isConnected()) {
return;
}
WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (!wifiInfo.getSSID().equals(THE_SSID_YOU_ARE_LOOKING_FOR)) {
return;
}
// Do something
}
}
EDIT:
When testing with my Samsung S4 (I959) device, my broadcast receiver failed to receive the broadcast. Common approach using ConnectivityManager.CONNECTIVITY_ACTION seems more reliable across different manufacturers. so you may want to use it instead.
Below is my previous investigation on this broadcast.
Here is what I got from 4.4.4_r1 source.
From WifiStateMachine source, the first thing to see is the states of the state machine, which is inside its constructor. Note that the latter is the parent state of the former.
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mVerifyingLinkState, mL2ConnectedState);
addState(mCaptivePortalCheckState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mUntetheringState, mSoftApStartedState);
Thankfully the names are almost self-explanatory. You can easily notice the states we are interested in. To see what really happens, we can search the source for these states.
The first method we investigate would be sendNetworkStateChangeBroadcast. Its invocation can be identified inside VerifyingLinkState and CaptivePortalCheckState, and some others you may find out for yourself.
Inside CaptivePortalCheckState, when processing CMD_CAPTIVE_CHECK_COMPLETE, you can finally confirm that when the checking is finished and network is fully configured, we will receive the state change intent in our app with CONNECTED state in NetworkInfo extra along with a WifiInfo.
Last but not least, we look back into the history. Personally I'm interested in 4.x platforms, so I turned to the source of 4.0.1_r1. It is a bit surprising that this version seems to be more readable than the latter one. You can find that sendNetworkStateChangeBroadcast is fired inside handleSuccessfulIpConfiguration (and other methods), which is fired in ConnectingState.processMessage() and ConnectedState.processMessage() when ip has been configured successfully.
So we finally arrive at the conclusion, using WifiManager.NETWORK_STATE_CHANGED_ACTION to track successful wireless connection, is safe and appropriate.
If you have any other questions related to WifiManager broadcasts, you can also refer to the source code mentioned above and find it out for yourself :)
Just a quick background I'm Running CM7 on a rooted Nexus one.
I am trying to detect when an outgoing call is actually connected: has stopped ringing and the person you are calling has answered. Looking through the forums this seems to be a tough and perhaps unanswered question. I'd really appreciate any insight into this.
In my searching the best I could find was in:
Android : How to get a state that the outgoing call has been answered?
#PattabiRaman said: "instead of detecting the outgoing call connection state, it is easy to get the duration of the last dialed call."
Does he mean that one should get the duration of the last dialed call as the call is in progress? And when that duration goes over 0 then you know?
The class com.android.internal.telephony.CallManager should have information about when the call actually is answered. It has a public static method getInstance() which returns the CallManager instance, and a public method getActiveFgCallState() which returns the current call state as a Call.State enum.
So in theory something like this might work:
Method getFgState = null;
Object cm = null;
try {
Class cmDesc = Class.forName("com.android.internal.telephony.CallManager");
Method getCM = cmDesc.getMethod("getInstance");
getFgState = cmDesc.getMethod("getActiveFgCallState");
cm = getCM.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
And then repeatedly poll the state:
Object state = getFgState.invoke(cm);
if (state.toString().equals("IDLE")) {
...
} else if (state.toString().equals("ACTIVE")) {
// If the previous state wasn't "ACTIVE" then the
// call has been established.
}
I haven't verified that this actually works. And even if it does you'll have to keep in mind that the API could change, since this isn't something that app developers are supposed to rely on.
I have looked into the code.
It will always give null unless you instantiate a Phone object and set it as default Phone.
But instantiating it needs some System permissions allowed only to system aps.
By using this method:
com.android.internal.telephony.PhoneFactory# public static void makeDefaultPhones(Context context) {
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.4_r1.2/com/android/internal/telephony/PhoneFactory.java