I want to make some scan of the Access Points, but the method wifiManager.startScan() doesn't work in my code :
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.buttonMeasure:
wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
registerReceiver(broadcastReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
wifiManager.setWifiEnabled(true); //Edit
timer2 = new Timer(WifiActivity.this);
while(broadcastReceiver.getMeasureFinished()<=49){
Log.d("info7","mesure" + broadcastReceiver.getMeasureFinished());
success = false;
while(success==false){
success=wifiManager.startScan();
Log.d("info2","startScan : " + success);
}
}
case R.id.buttonLocate:
//localization.
}
}
Eclipse is well enter in the loop, but doesn't want to read wifiManager.startScan();, what is the cause? Thanks!
Related
So my aim main is to make an app that can send messages from one phone to another without any internet connectivity. So as a first step I tried to create an app to switch wifi On/Off and show the available wifi devices. The app seems to work fine on emulator but does not work on the phone. Even the basic toggling of wifi didn't work on the phone. I've attached my MainActivity.java file. Kindly help.
MainActivity.java:-
public class MainActivity extends AppCompatActivity {
WifiManager wifiManager;
TextView wifiStatusTextView;
TextView wifiListView;
Switch wifiSwitch;
List<ScanResult> wifiList;
StringBuilder sb = new StringBuilder();
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Defining Variables
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiStatusTextView = (TextView) findViewById(R.id.wifi_status_text_view);
wifiListView = (TextView) findViewById(R.id.wifi_list);
wifiSwitch = (Switch) findViewById(R.id.wifi_switch);
registerReceiver(mWifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
wifiManager.startScan();
/* Checking wifi state.
* If wifi is enabled, display "wifi is on" and set toggle button to on position.
* If Wifi is disabled, display "wifi is off" and set toggle button to off position.
*/
if (wifiManager.isWifiEnabled()) {
wifiStatusTextView.setText("Wifi is currently ON");
wifiSwitch.setChecked(true);
} else {
wifiStatusTextView.setText("Wifi is currently OFF");
wifiSwitch.setChecked(false);
}
/* adds listener to toggle button
* If toggle is checked, wifi is enabled and "Wifi is on" is displayed.
* If toggle is unchecked, wifi is enabled and "Wifi is off" is displayed.
*/
wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
wifiManager.setWifiEnabled(true);
wifiStatusTextView.setText("Wifi is currently ON");
Toast.makeText(MainActivity.this, "Wifi may take a moment to turn on", Toast.LENGTH_LONG).show();
} else {
wifiManager.setWifiEnabled(false);
wifiStatusTextView.setText("Wifi is currently OFF");
}
}
});
}
#Override
public void onResume()
{
super.onResume();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 87);
}
}
}
private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
List<ScanResult> mScanResults = wifiManager.getScanResults();
sb = new StringBuilder();
wifiList = wifiManager.getScanResults();
for (int i = 0; i < wifiList.size(); i++){
sb.append(new Integer(i+1).toString() + ".");
sb.append((wifiList.get(i)).SSID);
sb.append("\n");
}
wifiListView.setText(sb);
}
}
};
}
I'm currently working on a wifi scanner project on an Android API 19
My problem is when the screen is off, after about 10 minutes it stops scanning the wifi
and when I turn on my device the scan starts again correctly.
I can not remove deep sleep :/
how to do a persistent wifi scan properly ??
someone has a suggestion ??
Thanks for your help
I am root on my device, this is my service background scan wifi
AndroidManifest :
<service android:name=".wifi" android:process=":my_service" android:enabled="true" android:priority="999" android:exported="true" android:label="Preferences"/>
service WIFI
class scanner_wifi extends Service implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
public void onCreate() {
tts = new TextToSpeech(this, this);
final WifiManager mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
if(mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
registerReceiver(new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
Log.e("WIFI_SCAN","NEW SCAN WIFI");
tts.speak("WIFI", TextToSpeech.QUEUE_FLUSH, null);
List<ScanResult> results = mWifiManager.getScanResults();
final int N = results.size();
for(int i=0; i < N; ++i) {
Log.e("WIFI_SCAN", " BSSID =" + results.get(i).BSSID);
Log.e("WIFI_SCAN", " SSID =" + results.get(i).SSID);
Log.e("WIFI_SCAN", " Capabilities=" + results.get(i).capabilities);
Log.e("WIFI_SCAN", " Frequency =" + results.get(i).frequency);
Log.e("WIFI_SCAN", " Level =" + results.get(i).level);
Log.e("WIFI_SCAN", "---------------");
}
}
}, filter);
mWifiManager.startScan();
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.FRENCH);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("WIFI_SCAN", "This Language is not supported");
}
} else {
Log.e("WIFI_SCAN", "Initilization Failed!");
}
}
public void onDestroy(){
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
my code works well but after x minutes of screen off , the device close my apps :/
Thanks for your help
I enable wi-fi tethering through my application in my android device. How do I get notification in my application when someone connects to the Wi-Fi network tethered by my application? Do I need to register for some specific broadcast receivers?
I have pasted below the application source code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((ToggleButton) findViewById(R.id.toggle_tethering)).setOnCheckedChangeListener(this);
}
#Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
Boolean result = false;
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Tab3OpenWifi";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
String setWifiApConfigurationMethodName = "setWifiApConfiguration";
Method setWifiApConfigurationMethod = wifiManager.getClass().getMethod(setWifiApConfigurationMethodName, WifiConfiguration.class);
result = (Boolean) setWifiApConfigurationMethod.invoke(wifiManager, config);
if (result) {
String setWifiApEnableMethodName = "setWifiApEnabled";
Method setWifiApEnableMethod = wifiManager.getClass().getMethod(setWifiApEnableMethodName, WifiConfiguration.class, boolean.class);
String message;
if (isChecked) {
result = (Boolean) setWifiApEnableMethod.invoke(wifiManager, null, true);
if (result) {
message = "Enabling tethering successfully";
} else {
message = "Enabling tethering failed";
}
} else {
result = (Boolean) setWifiApEnableMethod.invoke(wifiManager, null, false);
if (result) {
message = "Disabling tethering successfully";
} else {
message = "Disabling tethering failed";
}
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Failed to update Wifi Tethering config.", Toast.LENGTH_SHORT).show();
}
}
I used below broadcast receiver to get the AP state.
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"mReceiver.onReceive>>");
String action = intent.getAction();
if (WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
Log.d(TAG,"WIFI_AP_STATE_CHANGED_ACTION");
} else if (ACTION_TETHER_STATE_CHANGED.equals(action)) {
ArrayList<String> available = intent.getStringArrayListExtra(
EXTRA_AVAILABLE_TETHER);
ArrayList<String> active = intent.getStringArrayListExtra(
EXTRA_ACTIVE_TETHER);
ArrayList<String> errored = intent.getStringArrayListExtra(
EXTRA_ERRORED_TETHER);
Log.d(TAG,"==Available==");
for(String str : available)
Log.d(TAG, ""+str);
Log.d(TAG,"==Active==");
for(String str : active)
Log.d(TAG, ""+active);
Log.d(TAG,"==Error==");
for(String str : errored)
Log.d(TAG, ""+str);
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
}
Log.d(TAG,"mReceiver.onReceive<<");
}
};
I don't think there is an API for that, nor any broadcast event which you can listen to.
The only option that I can think of is operating at a lower level, i.e. the kernel level. I am no expert, but I used to monitor the /proc/net/tcp file to look for open connections. That may be a starting point for you.
I also wrote a simple library, if you want to get a glimpse of how I did it. You can find it here: https://github.com/dextorer/AndroidTCPSourceApp
Friends, I want to find all available WiFi networks and display them in a list I have tried as below. But it's not working. I have edited my code, and now I got the result but with all the result that I don't need. I only need names of wifi network in my list.
public class MainActivity extends Activity {
TextView mainText;
WifiManager mainWifi;
WifiReceiver receiverWifi;
List<ScanResult> wifiList;
StringBuilder sb = new StringBuilder();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainText = (TextView) findViewById(R.id.tv1);
mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (mainWifi.isWifiEnabled() == false)
{
// If wifi disabled then enable it
Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled",
Toast.LENGTH_LONG).show();
mainWifi.setWifiEnabled(true);
}
receiverWifi = new WifiReceiver();
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mainWifi.startScan();
mainText.setText("Starting Scan...");
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Refresh");
return super.onCreateOptionsMenu(menu);
}
public boolean onMenuItemSelected(int featureId, MenuItem item) {
mainWifi.startScan();
mainText.setText("Starting Scan");
return super.onMenuItemSelected(featureId, item);
}
protected void onPause() {
unregisterReceiver(receiverWifi);
super.onPause();
}
protected void onResume() {
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
super.onResume();
}
// Broadcast receiver class called its receive method
// when number of wifi connections changed
class WifiReceiver extends BroadcastReceiver {
// This method call when number of wifi connections changed
public void onReceive(Context c, Intent intent) {
sb = new StringBuilder();
wifiList = mainWifi.getScanResults();
sb.append("\n Number Of Wifi connections :"+wifiList.size()+"\n\n");
for(int i = 0; i < wifiList.size(); i++){
sb.append(new Integer(i+1).toString() + ". ");
sb.append((wifiList.get(i)).toString());
sb.append("\n\n");
}
mainText.setText(sb);
}
}
}
You need to create a BroadcastReceiver to listen for Wifi scan results:
private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
List<ScanResult> mScanResults = mWifiManager.getScanResults();
// add your logic here
}
}
}
In onCreate() you would assign mWifiManager and initiate a scan:
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
registerReceiver(mWifiScanReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
getScanResults() will return data only if you have appropriate permissions. For this, add one of the following two lines to your AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Also note that in API 23+, permissions must be requested at runtime. (For a lab environment, you can also grant permissions manually in Settings instead—less coding required, but not recommended for an end-user app.)
Note that the code which handles your scan results would run every time a new scan result is available, updating the result.
After Android 6.0
If your Android OS version is 6.0 or above then your application must ask for the following permission at runtime(Either of the following).
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
How to ask the permission at runtime
Just add this code in the onResume method of your activity
#Override
public void onResume()
{
super.onResume();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 87);
}
}
}
What will happen if you don't have the above permission at Runtime?
Wifi.getScanResults() will return 0 results.
Many people including me have faced this problem in Nexus 5 phones and referred to it as a "bug".
How to scan and read wifi networks? (Deeper Understanding)
Scanning can be requested by
wifiManager.startScan();
boolean startScan() returns
true or false immediately based on the fact whether the scan has started
successfully or not.
However it starts an asynchronous event which
sends an intent (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) when
the scan completes. Since the scan results (asynchronous event result) will not be available immediately, you will have to register your activity with a BroadcastReceiver.
Here is the code snippet to read those results(asynchronously) using BroadcastReceiver.
public class WifiScanReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION))
{
List<ScanResult> scanResults = wifimanager.getScanResults();
// Write your logic to show in the list
}
}
}
You can see this demo on BroadcastReceiver
Relevant links
Scan result returns an empty list in Android 6.0
class WifiReceiver extends BroadcastReceiver {
public void onReceive(Context c, Intent intent) {
sb = new StringBuilder();
wifiList = mainWifi.getScanResults();
for (int i = 0; i < wifiList.size(); i++){
sb.append(new Integer(i+1).toString() + ".");
sb.append((wifiList.get(i)).SSID);
sb.append("\n");
}
mainText.setText(sb);
}
}
I have a Wifi class that has a couple of broadcast receivers that listen out for changes in Wifi connection state, Wifi Rssi levels etc...
I want to be able to pass this data to another "Engine" Object and still keep the data changing dynamically.
I currently create a Wifi object within the "Engine" class and run its methods, the data is then dynamically displayed fine in Log statements in the log cat.
My problem is trying to get the dynamically changing data to the Engine, when I try to get data over it gets the first value and leaves it at that without ever updating.
So I was wondering what my options are on how to do this?
Below is my current code setup if that is any help:
Wifi Class
public Wifi(Context context){
mainWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
public int getCurrentWifiState() {
return currentWifiState;
}
public void setCurrentWifiState(int currentWifiState) {
this.currentWifiState = currentWifiState;
}
public String getConnectedSSID() {
return connectedSSID;
}
public void setConnectedSSID(String connectedSSID) {
this.connectedSSID = connectedSSID;
}
public int getConnectedLevel() {
return connectedLevel;
}
public void setConnectedLevel(int connectedLevel) {
this.connectedLevel = connectedLevel;
}
//method to do a scan and receive info about all access points available
public List<ScanResult> scan(final Context context){
receiverWifi = new WifiReceiver();
mainWifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
context.registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mainWifi.startScan();
Log.d("WIFI DEBUG","\nStarting Scan...\n");
wifiList = mainWifi.getScanResults();
return wifiList;
}
class WifiReceiver extends BroadcastReceiver {
public void onReceive(Context c, Intent intent) {
sb = new StringBuilder();
wifiList = mainWifi.getScanResults();
ListIterator<ScanResult> results = wifiList.listIterator();
while (results.hasNext()) {
ScanResult info = results.next();
String wifiInfo = "Name: " + info.SSID + "; capabilities = " + info.capabilities + "; sig str = " + info.level + "dBm";
Log.v("WiFi", wifiInfo);
Log.d("Signal Level", "Signal Level : " + mainWifi.calculateSignalLevel(info.level, 5));
}
}
}
//method to listen for changes in the level of the wifi connection
public void initializeWiFiListener(Context context){
Log.d("WIFI", "executing initializeWiFiListener");
String connectivity_context = Context.WIFI_SERVICE;
final WifiManager wifi = (WifiManager)context.getSystemService(connectivity_context);
if(!wifi.isWifiEnabled()){
if(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLING){
//wifi.setWifiEnabled(true);
}
}
rssiListener = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(WifiManager.RSSI_CHANGED_ACTION.equals(action)){
WifiInfo data = mainWifi.getConnectionInfo();
Log.d("WIFI", "RSSI has changed");
if(mainWifi.getConnectionInfo()!=null){
setConnectedSSID(data.getSSID());
setConnectedLevel(data.getRssi());
Log.d("WIFI", "new RSSI = " + data.getSSID()+ " " + data.getRssi() + "dBm");
}
}
}
};
//leak here - need to de reg receiver
context.registerReceiver(rssiListener, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
}
//method to listen for changes in the connection to a wifi access point
public void changeWiFiListener(Context context){
Log.d("WIFI", "executing initializeWiFiListener");
String connectivity_context = Context.WIFI_SERVICE;
final WifiManager wifi = (WifiManager)context.getSystemService(connectivity_context);
if(!wifi.isWifiEnabled()){
if(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLING){
//wifi.setWifiEnabled(true);
}
}
wifiChangeListener = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){
Log.d("WIFI", "WIFI has changed");
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1);
Log.d("WIFI", "WIFI State = " + wifiState);
setCurrentWifiState(wifiState);
}
}
};
//Leak here - not unregistering receiver
context.registerReceiver(wifiChangeListener, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
}
public WifiReceiver getReceiverWifi() {
return receiverWifi;
}
public void setReceiverWifi(WifiReceiver receiverWifi) {
this.receiverWifi = receiverWifi;
And my Engine Code:
public Engine(Context aContext){
context = aContext;
cm = new CallManager(aContext);
wifiManager = new Wifi(context);
wifiManager.initializeWiFiListener(context);
wifiManager.changeWiFiListener(context);
clc = new CallLogController();
}
public void controlCalls(){
int currentWifiState = wifiManager.getCurrentWifiState();
cm.monitorOutgoingCalls(context, currentWifiState, clc);
}
public void unRegAllRecievers(){
wifiManager.unregRegisters(context);
cm.unRegReciever(context);
}
public void doWifiScan(){
scanTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
wifiManager.scan(context);
Log.d("TIMER", "Timer set off");
}
});
}};
t.schedule(scanTask, 300, 30000);
}
public void stopScan(){
scanTask.cancel();
t.cancel();
//boolean tf = scanTask.cancel();
//Log.d("TIMER", "Timer True or False? : " + tf);
}
}
So I'm just wondering what would be the best solution to make sure the data from the Wifi class is constantly updated in the engine when it receives changes from the broadcast receiver?
depends if your class, the one that should be notified of the latest state.
If it's a class that is not created in an Activity and is static (singletone or Application based) then you should probably have the Reciver update the singletone class.
If it's Activity based, you need stick Broadcasts, and once the broadcast is recieved remove the sticky broadcast.