我正在开发一个使用谷歌地图更新位置的应用程序。到目前为止,我只有一个问题,那就是访问精细位置权限。这是我的清单文件。
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- Network State Permissions -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- <android:uses-permission android:name="android.permission.READ_PHONE_STATE" /> -->
<!-- <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> -->
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps" >
</activity>
<activity
android:name=".HelpMe"
android:label="@string/title_activity_help_me"
android:theme="@style/AppTheme" >
</activity>
<service
android:name=".MyLocationUpdate"
android:exported="false" >
</service>
</application>
这是我的意向服务,通过它,我将控制权传递给我的服务类。
public class MyLocationUpdate extends IntentService {
double latitude,longitude;
AppLogic app = new AppLogic();
HelpMe activity;
IETrackerDTO iedto= new IETrackerDTO();
public MyLocationUpdate() {
super("MyLocationUpdate");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("Inside", "Intent Service");
/*IETrackerDTO ide = intent.getExtras().("currentUser");*/
ScheduledThreadPoolExecutor s = new ScheduledThreadPoolExecutor(1);
s.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
LocationFinder gps;
Log.d("Calling other service", "Calling other service");
gps = new LocationFinder(MyLocationUpdate.this);
latitude = gps.getLatitude();
longitude = gps.getLongitude();
Log.d("Location", latitude + " " + longitude);
updateLocation();
toast();
}
}, 0, 10, TimeUnit.SECONDS);
}
public void toast() {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Lat: " + latitude + " long:" + longitude, Toast.LENGTH_SHORT).show();
}
});
}
这是我的服务类,可以及时更新用户的经度
public class LocationFinder extends Service implements LocationListener {
private final Context mContext;
static Class<? extends Context> activity;
// flag for GPS status
// boolean isGPSEnabled = false;
boolean canGetLocation = false;
// flag for network status
// boolean isNetworkEnabled = false;
// flag for GPS status
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public LocationFinder(Context context) {
Log.d("Inside constructor", "Inside Constructor");
this.mContext = context;
Log.d("After setting context", "After setting context");
getLocation();
}
public Location getLocation() {
Log.d("Inside getLocation", "Inside getLocation");
Log.d("Inside doInBackground", "Inside doInBackground");
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
Log.d("Inside enabled", "Inside enabled");
this.canGetLocation = true;
if (isNetworkEnabled) {
Log.d("Inside networ enabled", "Inside network enabled");
if (locationManager != null) {
new Thread(){
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg) {
if (ActivityCompat.checkSelfPermission(mContext,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// public void requestPermissions(@NonNull String[] permissions, int requestCode)
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
}
};
Looper.loop();
}
}.start();
}/**/
/*locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, (LocationListener) this);*/
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
Log.d("Inside gps enabled", "Inside gps enabled");
if (location == null) {
new Thread(){
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg) {
if (ActivityCompat.checkSelfPermission(mContext,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// public void requestPermissions(@NonNull String[] permissions, int requestCode)
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
}
};
Looper.loop();
}
}.start();
/* locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);*/
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS() {
if (locationManager != null) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// public void requestPermissions(@NonNull String[] permissions, int requestCode)
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
locationManager.removeUpdates(LocationFinder.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* @return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
@Override
public void onLocationChanged(Location location) {
getLocation();
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
一切都运行良好,除了编译器要求位置权限并且没有它,控件不会传递给服务类方法
这是我的日志猫
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Calling other service﹕ Calling other service
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside constructor﹕ Inside Constructor
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/After setting context﹕ After setting context
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside getLocation﹕ Inside getLocation
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside doInBackground﹕ Inside doInBackground
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside enabled﹕ Inside enabled
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside gps enabled﹕ Inside gps enabled
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/GPS Enabled﹕ GPS Enabled
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ java.lang.SecurityException: "gps" location provider requires ACCESS_FINE_LOCATION permission.
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at android.os.Parcel.readException(Parcel.java:1599)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at android.os.Parcel.readException(Parcel.java:1552)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at android.location.ILocationManager$Stub$Proxy.getLastLocation(ILocationManager.java:717)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at android.location.LocationManager.getLastKnownLocation(LocationManager.java:1200)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at com.mindtree.igxbridge.getuseraddress.LocationFinder.getLocation(LocationFinder.java:206)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at com.mindtree.igxbridge.getuseraddress.LocationFinder.<init>(LocationFinder.java:59)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at com.mindtree.igxbridge.getuseraddress.MyLocationUpdate$1.run(MyLocationUpdate.java:56)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:278)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:270)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Location﹕ 0.0 0.0
02-11 11:05:56.980 2114-2779/com.mindtree.igxbridge.getuseraddress D/Inside updateLocatiion﹕ Inside UpdateLocation
02-11 11:05:57.050 2114-2131/com.mindtree.igxbridge.getuseraddress W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-11 11:05:57.050 2114-2131/com.mindtree.igxbridge.getuseraddress W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0x7f4e5aaabf40, error=EGL_SUCCESS
02-11 11:05:59.000 2114-2131/com.mindtree.igxbridge.getuseraddress E/Surface﹕ getSlotFromBufferLocked: unknown buffer: 0x7f4e5a8b93f0
简短的回答是你需要在清单中有一个清单块
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mycompany"
android:versionCode="1"
android:versionName="1.0" >
包名称必须是唯一的,因此按照惯例,您拥有的向后域名。这有助于将您标识为供应商,并授予对具有相同软件包名称(或供应商 ID,如果您愿意)的任何服务、其他活动、应用程序等的访问权限。没有用户可以授予权限,因为 android 是个人设备。此外,列出的任何外国特权,例如 使用权限 android:name="android.permission.ACCESS_FINE_LOCATION"将授予供应商,假设它们被用户/运营商接受。