问题
I am trying to make wifi scanner for my project which does 20 scan when I hit the scan button. When I run the code its scans but I dont know it scans for 20 times or not and the RSSI value/wifi level keeps changing. In log it also says that you need to unregisterReciever.
My MainActivity.java
package com.example.scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
WifiManager wifi;
WifiScanReceiver wifireciever;
WifiInfo info;
Button scan, save;
List<ScanResult> wifilist;
ListView list;
String wifis[];
String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
list=(ListView)findViewById(R.id.listView1);
scan=(Button)findViewById(R.id.button1);
save=(Button)findViewById(R.id.button2);
scan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
wifi=(WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()==false){
wifi.setWifiEnabled(true);
}
wifireciever = new WifiScanReceiver();
registerReceiver(wifireciever, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
});
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
savedata();
}
});
}
protected void savedata() {
// TODO Auto-generated method stub
try {
File sdcard = Environment.getExternalStorageDirectory();
File directory = new File(sdcard.getAbsolutePath() + "/WIFI_RESULT");
directory.mkdirs();
name = new SimpleDateFormat("yyyy-MM-dd HH mm ss").format(new Date());
File file = new File(directory,name + "wifi_data.txt");
FileOutputStream fou = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fou);
try {
for (int i =0; i < list.getCount(); i++){
osw.append(list.getItemAtPosition(i).toString());
}
osw.flush();
osw.close();
Toast.makeText(getBaseContext(), "Saved", Toast.LENGTH_LONG).show();
} catch (IOException e){
e.printStackTrace();
}
} catch (FileNotFoundException e){
e.printStackTrace();
}
}
public class scan_data {
String ssid;
String bssid;
int lvl;
int count = 0;
}
class WifiScanReceiver extends BroadcastReceiver {
@SuppressLint("UseValueOf")
public void onReceive(Context c, Intent intent) {
scan_data[] data = new scan_data[100];
for (int i=0;i<100;i++){
scan_data sdata = new scan_data();
data[i]=sdata;
}
int a =0;
for (int i=0;i<20;i++){
wifi.startScan();
List<ScanResult> wifilist = wifi.getScanResults();
if (a<wifilist.size()){
a=wifilist.size();
}
if (i==0){
for(int j=0;j<wifilist.size();j++){
data[j].ssid=wifilist.get(j).SSID.toString();
data[j].bssid=wifilist.get(j).BSSID.toString();
data[j].lvl=wifilist.get(j).level;
data[j].count++;
}
}
else if (i==19){
for (int j=0;j<wifilist.size();j++){
if(data[j].bssid.equals(wifilist.get(j).BSSID)){
data[j].lvl=data[j].lvl + wifilist.get(j).level;
data[j].count++;
}
data[j].lvl=data[j].lvl/data[j].count;
}
}
else {
for (int j=0;j<wifilist.size();j++){
if(data[j].bssid.equals(wifilist.get(j).BSSID)){
data[j].lvl=data[j].lvl + wifilist.get(j).level;
data[j].count++;
}
}
}
}
wifis = new String[a];
for (int i =0; i<a; i++){
wifis[i] = ("\n" + data[i].ssid + "\n AP Address" + data[i].bssid + "\n Signal Strength:" + data[i].lvl).toString();
}
list.setAdapter(new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,wifis));
}
}
protected void onPause() {
unregisterReceiver(wifireciever);
super.onPause();
}
protected void onResume() {
registerReceiver(wifireciever, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
and the log cat is :
06-05 17:42:43.262: D/dalvikvm(32156): GC_FOR_ALLOC freed 117K, 11% free 6899K/7687K, paused 35ms, total 35ms
06-05 17:42:43.312: I/dalvikvm-heap(32156): Grow heap (frag case) to 13.478MB for 6400016-byte allocation
06-05 17:42:43.412: D/dalvikvm(32156): GC_CONCURRENT freed 1K, 6% free 13148K/13959K, paused 33ms+2ms, total 103ms
06-05 17:42:43.412: D/dalvikvm(32156): WAIT_FOR_CONCURRENT_GC blocked 8ms
06-05 17:42:43.532: D/AbsListView(32156): Get MotionRecognitionManager
06-05 17:42:43.642: D/libEGL(32156): loaded /system/lib/egl/libGLES_rhea.so
06-05 17:42:43.662: D/BRCM_EGL(32156): eglCreateContext() config: 19 context: 0x4a12ca38, VC context 1, Thread 32156
06-05 17:42:43.662: D/BRCM_EGL(32156): eglCreateWindowSurface() surface: 0x4a240960, VC surface: 1, Thread: 32156
06-05 17:42:43.662: D/BRCM_EGL(32156): eglMakeCurrent(0x4a12ca38, 0x4a240960, 0x4a240960) Thread: 32156
06-05 17:42:43.672: D/OpenGLRenderer(32156): Enabling debug mode 0
06-05 17:43:39.937: D/BRCM_EGL(32156): eglMakeCurrent(NULL) Thread: 32156
06-05 17:43:39.937: D/BRCM_EGL(32156): eglDestroySurface() surface: 0x4a240960, android window 0x4908d370, Thread: 32156
06-05 17:43:40.457: D/BRCM_EGL(32156): eglMakeCurrent(0x4a12ca38, 0x4a2cbf60, 0x4a2cbf60) Thread: 32156
06-05 17:43:40.478: D/BRCM_EGL(32156): eglMakeCurrent(NULL) Thread: 32156
06-05 17:43:40.488: D/BRCM_EGL(32156): eglMakeCurrent(0x4a12ca38, 0x4a2cbf60, 0x4a2cbf60) Thread: 32156
06-05 17:43:40.488: D/BRCM_EGL(32156): eglMakeCurrent(NULL) Thread: 32156
06-05 17:43:40.508: E/ActivityThread(32156): Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41640c78 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.508: E/ActivityThread(32156): android.app.IntentReceiverLeaked: Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41640c78 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:793)
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1314)
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1301)
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1295)
06-05 17:43:40.508: E/ActivityThread(32156): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:394)
06-05 17:43:40.508: E/ActivityThread(32156): at com.example.scanner.MainActivity$1.onClick(MainActivity.java:64)
06-05 17:43:40.508: E/ActivityThread(32156): at android.view.View.performClick(View.java:4262)
06-05 17:43:40.508: E/ActivityThread(32156): at android.view.View$PerformClick.run(View.java:17421)
06-05 17:43:40.508: E/ActivityThread(32156): at android.os.Handler.handleCallback(Handler.java:615)
06-05 17:43:40.508: E/ActivityThread(32156): at android.os.Handler.dispatchMessage(Handler.java:92)
06-05 17:43:40.508: E/ActivityThread(32156): at android.os.Looper.loop(Looper.java:137)
06-05 17:43:40.508: E/ActivityThread(32156): at android.app.ActivityThread.main(ActivityThread.java:4947)
06-05 17:43:40.508: E/ActivityThread(32156): at java.lang.reflect.Method.invokeNative(Native Method)
06-05 17:43:40.508: E/ActivityThread(32156): at java.lang.reflect.Method.invoke(Method.java:511)
06-05 17:43:40.508: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
06-05 17:43:40.508: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
06-05 17:43:40.508: E/ActivityThread(32156): at dalvik.system.NativeStart.main(Native Method)
06-05 17:43:40.518: E/ActivityThread(32156): Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@4167dca8 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.518: E/ActivityThread(32156): android.app.IntentReceiverLeaked: Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@4167dca8 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:793)
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1314)
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1301)
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1295)
06-05 17:43:40.518: E/ActivityThread(32156): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:394)
06-05 17:43:40.518: E/ActivityThread(32156): at com.example.scanner.MainActivity$1.onClick(MainActivity.java:64)
06-05 17:43:40.518: E/ActivityThread(32156): at android.view.View.performClick(View.java:4262)
06-05 17:43:40.518: E/ActivityThread(32156): at android.view.View$PerformClick.run(View.java:17421)
06-05 17:43:40.518: E/ActivityThread(32156): at android.os.Handler.handleCallback(Handler.java:615)
06-05 17:43:40.518: E/ActivityThread(32156): at android.os.Handler.dispatchMessage(Handler.java:92)
06-05 17:43:40.518: E/ActivityThread(32156): at android.os.Looper.loop(Looper.java:137)
06-05 17:43:40.518: E/ActivityThread(32156): at android.app.ActivityThread.main(ActivityThread.java:4947)
06-05 17:43:40.518: E/ActivityThread(32156): at java.lang.reflect.Method.invokeNative(Native Method)
06-05 17:43:40.518: E/ActivityThread(32156): at java.lang.reflect.Method.invoke(Method.java:511)
06-05 17:43:40.518: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
06-05 17:43:40.518: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
06-05 17:43:40.518: E/ActivityThread(32156): at dalvik.system.NativeStart.main(Native Method)
06-05 17:43:40.528: E/ActivityThread(32156): Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@416416e0 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.528: E/ActivityThread(32156): android.app.IntentReceiverLeaked: Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@416416e0 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:793)
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1314)
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1301)
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1295)
06-05 17:43:40.528: E/ActivityThread(32156): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:394)
06-05 17:43:40.528: E/ActivityThread(32156): at com.example.scanner.MainActivity$1.onClick(MainActivity.java:64)
06-05 17:43:40.528: E/ActivityThread(32156): at android.view.View.performClick(View.java:4262)
06-05 17:43:40.528: E/ActivityThread(32156): at android.view.View$PerformClick.run(View.java:17421)
06-05 17:43:40.528: E/ActivityThread(32156): at android.os.Handler.handleCallback(Handler.java:615)
06-05 17:43:40.528: E/ActivityThread(32156): at android.os.Handler.dispatchMessage(Handler.java:92)
06-05 17:43:40.528: E/ActivityThread(32156): at android.os.Looper.loop(Looper.java:137)
06-05 17:43:40.528: E/ActivityThread(32156): at android.app.ActivityThread.main(ActivityThread.java:4947)
06-05 17:43:40.528: E/ActivityThread(32156): at java.lang.reflect.Method.invokeNative(Native Method)
06-05 17:43:40.528: E/ActivityThread(32156): at java.lang.reflect.Method.invoke(Method.java:511)
06-05 17:43:40.528: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
06-05 17:43:40.528: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
06-05 17:43:40.528: E/ActivityThread(32156): at dalvik.system.NativeStart.main(Native Method)
06-05 17:43:40.538: E/ActivityThread(32156): Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41641368 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.538: E/ActivityThread(32156): android.app.IntentReceiverLeaked: Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41641368 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:793)
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1314)
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1301)
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1295)
06-05 17:43:40.538: E/ActivityThread(32156): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:394)
06-05 17:43:40.538: E/ActivityThread(32156): at com.example.scanner.MainActivity$1.onClick(MainActivity.java:64)
06-05 17:43:40.538: E/ActivityThread(32156): at android.view.View.performClick(View.java:4262)
06-05 17:43:40.538: E/ActivityThread(32156): at android.view.View$PerformClick.run(View.java:17421)
06-05 17:43:40.538: E/ActivityThread(32156): at android.os.Handler.handleCallback(Handler.java:615)
06-05 17:43:40.538: E/ActivityThread(32156): at android.os.Handler.dispatchMessage(Handler.java:92)
06-05 17:43:40.538: E/ActivityThread(32156): at android.os.Looper.loop(Looper.java:137)
06-05 17:43:40.538: E/ActivityThread(32156): at android.app.ActivityThread.main(ActivityThread.java:4947)
06-05 17:43:40.538: E/ActivityThread(32156): at java.lang.reflect.Method.invokeNative(Native Method)
06-05 17:43:40.538: E/ActivityThread(32156): at java.lang.reflect.Method.invoke(Method.java:511)
06-05 17:43:40.538: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
06-05 17:43:40.538: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
06-05 17:43:40.538: E/ActivityThread(32156): at dalvik.system.NativeStart.main(Native Method)
06-05 17:43:40.548: E/ActivityThread(32156): Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41640ff0 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.548: E/ActivityThread(32156): android.app.IntentReceiverLeaked: Activity com.example.scanner.MainActivity has leaked IntentReceiver com.example.scanner.MainActivity$WifiScanReceiver@41640ff0 that was originally registered here. Are you missing a call to unregisterReceiver()?
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:793)
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1314)
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1301)
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1295)
06-05 17:43:40.548: E/ActivityThread(32156): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:394)
06-05 17:43:40.548: E/ActivityThread(32156): at com.example.scanner.MainActivity$1.onClick(MainActivity.java:64)
06-05 17:43:40.548: E/ActivityThread(32156): at android.view.View.performClick(View.java:4262)
06-05 17:43:40.548: E/ActivityThread(32156): at android.view.View$PerformClick.run(View.java:17421)
06-05 17:43:40.548: E/ActivityThread(32156): at android.os.Handler.handleCallback(Handler.java:615)
06-05 17:43:40.548: E/ActivityThread(32156): at android.os.Handler.dispatchMessage(Handler.java:92)
06-05 17:43:40.548: E/ActivityThread(32156): at android.os.Looper.loop(Looper.java:137)
06-05 17:43:40.548: E/ActivityThread(32156): at android.app.ActivityThread.main(ActivityThread.java:4947)
06-05 17:43:40.548: E/ActivityThread(32156): at java.lang.reflect.Method.invokeNative(Native Method)
06-05 17:43:40.548: E/ActivityThread(32156): at java.lang.reflect.Method.invoke(Method.java:511)
06-05 17:43:40.548: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
06-05 17:43:40.548: E/ActivityThread(32156): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
06-05 17:43:40.548: E/ActivityThread(32156): at dalvik.system.NativeStart.main(Native Method)
I know I m missing the unregistorReciever thing but where should I add
回答1:
your wifi scans 20 times, apparently because of this
for (int i=0;i<20;i++){
wifi.startScan();
your are starting scan 20 times inside the for loop, why?
and regarding unregister the receiver,
it can be placed at onDestroy()
one more note, the line
wifi.startScan();
should not be placed inside the onReceive()
it should be placed at onClick() of scan buttom
and onReceive()
will be called so you can get data and save it
so if you call startScan it will trigger scan again
and you are using too many hardcoded sizes , 100 and 20 what are these suppose to be?
Edit:
scan_data[] data = null;
int TOTAL_SCANS = 0;
class WifiScanReceiver extends BroadcastReceiver {
@SuppressLint("UseValueOf")
public void onReceive(Context c, Intent intent) {
List<ScanResult> wifilist = wifi.getScanResults();
data = new scan_data[wifilist .size()];
int a =0;
// for (int i=0;i<20;i++){ //DELETE THE LOOP
if (a<wifilist.size()){
a=wifilist.size();
}
for(int r=0;r<wifilist.size();r++){
data[r] = new scan_date();
data[r].ssd=wifilist.get(r).ssd();//check syntax here ... just sample
}
//at end of onReceive()
if(TOTAL_SCANS < 20){
++TOTAL_SCANS;
wifi.startScan();
}else{
System.out.println(" Scan Completed [" + TOTAL_SCANS + "] times.");
//you can unregisterReceiver here too
}
:
:
check this sample, just add the if(TOTAL_SCANS<20)
at end on onReceive()
回答2:
Update: You can take a look at my demo for RF measurements using Android device, where you can found a couple of approaches, here:
https://github.com/panosvas/Measurements
where you can find an implementation of WiFi measurements one after another. I have also created a Server for storing these measurements as well as a remote trigger app using UDP packets where you can find here:
https://github.com/panosvas/IndoorPositioningServer
It is possible to obtain multiple measurements. Your approach is wrong due to the fact that the for loop will be executed probably in mseconds and each wifi measurement in Android keeps approximately 5 seconds based on the device. One approach to achieve your goal is the following:
- Create an Asynch task or a task that calls the startScan()
- Keep a counter and update it each time the onRecieve is triggered
- If the counter does not reach the limit then inside the onRecieve call again the task
- If the counter reaches the limit then inside the onRecieve you don't have to call again the task
Keep in mind that in order to obtain correct measurements you have to wait until each measurement finishes otherwise you will take duplicates of the same measurement.
来源:https://stackoverflow.com/questions/24059997/wifi-scanner-which-scans-20-times