我正在开发一个应用程序来检查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,但解决方案不适用,因为我已经宣布了许可。
任何人都知道可能有什么问题?谢谢。
答案 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
正在检查canReadPeerMacAddresses
,checkPeersMacAddress()
的代码是:
/**
* 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_LOCATION
或ACCESS_COARSE_LOCATION
是必要的。要获得有效的结果,您还必须打开GPS或获得PEERS_MAC_ADDRESS
的{{1}}权限。