Android WifiManager getScanResult抱怨虽然声明了权限,但需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限

时间:2015-11-16 08:05:48

标签: java android android-wifi wifimanager

我正在开发一个应用程序来检查Wifi点。

我收到错误" java.lang.SecurityException:需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限才能获得扫描结果"在wifiManager.getScanResults()中,即使我已经声明了这些权限。

主要活动

import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.ListView;
import android.widget.EditText;
import android.widget.Toast;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import android.view.View;

import org.json.JSONArray;
import org.json.JSONObject;
//import org.json.JSONArray;
import org.json.JSONException;
//import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;


public class MainActivity extends Activity {

    String TAG = "Response";
    TextView responseText;
    Button bt;
    EditText celcius;
    String getCel;
    SoapPrimitive resultString;
    String color, item;
    String str = "<font color=\"%s\">%s</font>";
   //private static final String name = "ID_NUMERIC";
   // private static final String test = "TEST";
    private static final String component = "COMPONENT";
   // private static final String units = "UNITS";
    private static final String value = "VALUE";
    private static final String flag = "FLAG";
    //private static final String color = "color";
    //private static final String samplingpoint = "SAMPLINGPOINT";
    JSONArray Response = null;
    String jsonObject_string ;
    String jArray;
    ListView list;
    TextView vers;
    TextView name;
    TextView flg;
    TextView api;
    ListAdapter adapter;
    ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();

    public void calculate() {
        String SOAP_ACTION = "";
        String METHOD_NAME = "";
        String NAMESPACE = "";
        String URL = "";

        try {
            SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
            Request.addProperty("SmapleID", getCel);

            SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            soapEnvelope.dotNet = true;
            soapEnvelope.setOutputSoapObject(Request);

            HttpTransportSE transport = new HttpTransportSE(URL);

            transport.call(SOAP_ACTION, soapEnvelope);
            resultString = (SoapPrimitive) soapEnvelope.getResponse();

            //Log.i(TAG, "Result SmapleID: " + resultString);
        } catch (Exception ex) {
            Log.e(TAG, "Error: " + ex.getMessage());
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       // ListView list = (ListView) findViewById(R.id.list);
        responseText = (TextView) findViewById(R.id.responseText);
        bt = (Button) findViewById(R.id.bt);
        celcius = (EditText) findViewById(R.id.cel);
        list = (ListView) findViewById(R.id.list);


        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                getCel = celcius.getText().toString();
                AsyncCallWS task = new AsyncCallWS();
                task.execute();


            }
        });

    }

    private class AsyncCallWS extends AsyncTask<String, Void, String> {

        @Override
        protected void onPreExecute() {
            Log.i(TAG, "onPreExecute");
        }

        @Override
        protected String doInBackground(String... params) {
            Log.i(TAG, "doInBackground");
            calculate();
            return null;
        }



        @Override
        protected void onPostExecute(String result) {
            //calculate();

            SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, oslist,R.layout.list_child,new String[] {component, value, flag, color }, new int[] {R.id.name, R.id.vers, R.id.flg});
            list.setAdapter(adapter);    

             oslist.clear();

            // Making a request to url and getting response
            String data = "";
            String data1 = "";
            String data2 = "";
            String data3 = "";
            String data4 = "";
            String data5 = "";
            String jsonStr = resultString.toString();

            //Log.d("Response: ", "> " + jsonStr);

            if (jsonStr != null) {

              try 

            {

              JSONArray jArray = new JSONArray(jsonStr);

            for(int i=0;i<jArray.length();i++){
                JSONObject json_obj = jArray.getJSONObject(i);

               // String name = json_obj.getString("ID_NUMERIC");
               // String test = json_obj.getString("    TEST");
                String component = json_obj.getString("COMPONENT");
                //String units = json_obj.getString("UNITS");
                String value = json_obj.getString("VALUE");
                String flag = json_obj.getString("FLAG");
               if ("F".equalsIgnoreCase(flag));{
                   color = "red";
               }
                //data = name;
               // data1 = test + ", ";
                data2 = component;
               // data3 = units;
                data4 =  value;
                data =  flag;

                HashMap<String, String> map = new HashMap<String, String>();
                map.put("COMPONENT", data2);
                map.put("VALUE", data4);
                map.put("FLAG", data);

                oslist.add(map);

        }
            }catch (JSONException e) {
                // handle exception
            }

        }
          // return null;
        }

    }}

清单

public class MainActivity extends AppCompatActivity {

WifiManager wifiManager;
String[] wifis;
WifiReceiver wifiReceiver;

ListView wifiListView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    wifiListView = (ListView) findViewById(R.id.wifi_list);

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    wifiReceiver = new WifiReceiver();
    wifiManager.startScan();
}

protected void onPause() {
    unregisterReceiver(wifiReceiver);
    super.onPause();
}

protected void onResume() {
    registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    super.onResume();
}

private class WifiReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        List<ScanResult> wifiScanList = wifiManager.getScanResults();
        wifis = new String[wifiScanList.size()];

        for (int i = 0; i < wifiScanList.size(); i++) {
            wifis[i] = wifiScanList.get(i).toString();
        }

        wifiListView.setAdapter(new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, wifis));
    }
}

我在SDK 6.0上

我观察到类似question,但解决方案不适用,因为我已经宣布了许可。

任何人都知道可能有什么问题?谢谢。

3 个答案:

答案 0 :(得分:6)

在Android M中,您需要在每次开始使用之前向用户请求在PermissionModel中定义为危险的权限,如下所示:

private boolean mayRequestLocation() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        if (checkSelfPermission(ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
            Snackbar.make(mView, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
                    .setAction(android.R.string.ok, new View.OnClickListener() {
                        @Override
                        @TargetApi(Build.VERSION_CODES.M)
                        public void onClick(View v) {
                            requestPermissions(new String[]{ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
                        }
                    });
        } else {
            requestPermissions(new String[]{ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
        }
        return false;
    }

将此添加到您的活动:

private static final int REQUEST_FINE_LOCATION=0

并在运行时使用以下命令加载:

loadPermissions(Manifest.permission.ACCESS_FINE_LOCATION,REQUEST_FINE_LOCATION);

要评估您的权限请求的结果,您可以覆盖onRequestPermissionsResult方法:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case REQUEST_FINE_LOCATION: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // The requested permission is granted.
            }
            else{
                // The user disallowed the requested permission.
            }
            return;
        }

}

答案 1 :(得分:1)

MADAO is right:您应该打开GPS以获取WIFI接入点列表。

但我不确定PEERS_MAC_ADDRESS。如果你看一下the source code(第957行):

/**
 * Return the results of the most recent access point scan, in the form of
 * a list of {@link ScanResult} objects.
 * @return the list of results
 */
public List<ScanResult> getScanResults(String callingPackage) {
    enforceAccessPermission();
    int userId = UserHandle.getCallingUserId();
    int uid = Binder.getCallingUid();
    boolean canReadPeerMacAddresses = checkPeersMacAddress();
    boolean isActiveNetworkScorer =
            NetworkScorerAppManager.isCallerActiveScorer(mContext, uid);
    boolean hasInteractUsersFull = checkInteractAcrossUsersFull();
    long ident = Binder.clearCallingIdentity();
    try {
        if (!canReadPeerMacAddresses && !isActiveNetworkScorer
                && !isLocationEnabled()) {
            return new ArrayList<ScanResult>();
        }
        if (!canReadPeerMacAddresses && !isActiveNetworkScorer
                && !checkCallerCanAccessScanResults(callingPackage, uid)) {
            return new ArrayList<ScanResult>();
        }
        if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
                != AppOpsManager.MODE_ALLOWED) {
            return new ArrayList<ScanResult>();
        }
        if (!isCurrentProfile(userId) && !hasInteractUsersFull) {
            return new ArrayList<ScanResult>();
        }
        return mWifiStateMachine.syncGetScanResultsList();
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

第一个if正在检查canReadPeerMacAddressescheckPeersMacAddress()的代码是:

/**
 * Returns true if the caller holds PEERS_MAC_ADDRESS.
 */
private boolean checkPeersMacAddress() {
    return mContext.checkCallingOrSelfPermission(
            android.Manifest.permission.PEERS_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED;
}

如果您添加权限,则可以绕过if (!canReadPeerMacAddresses && !isActiveNetworkScorer && !isLocationEnabled()) {。我已经测试但是我只能通过使用权限和禁用位置来获取WIFI MAC列表。

答案 2 :(得分:0)

ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION是必要的。要获得有效的结果,您还必须打开GPS或获得PEERS_MAC_ADDRESS的{​​{1}}权限。