简体   繁体   English

启动定位服务时出现java.lang.SecurityException

[英]java.lang.SecurityException when starting location service

I tried to run location service as background service.我尝试将位置服务作为后台服务运行。 It works fine in activity, but when I used service, I got java.lang.securityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.它在活动中工作正常,但是当我使用服务时,我得到 java.lang.securityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION 权限才能执行任何位置操作。 I already put appropriate permissions but the problem still persists.我已经设置了适当的权限,但问题仍然存在。 I am using nexus 5 (Marshmallow) for testing.我正在使用 nexus 5 (Marshmallow) 进行测试。

This is my service这是我的服务

public class LocationService extends Service implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

private static final String TAG = "LocationService";

// use the websmithing defaultUploadWebsite for testing and then check your
// location with your browser here: https://www.websmithing.com/gpstracker/displaymap.php
private String defaultUploadWebsite;

private boolean currentlyProcessingLocation = false;
private LocationRequest locationRequest;
private GoogleApiClient locationClient;
private String username;

@Override
public void onCreate() {
    super.onCreate();
    //defaultUploadWebsite = getString(R.string.default_upload_website);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // if we are currently trying to get a location and the alarm manager has called this again,
    // no need to start processing a new location.
    if (!currentlyProcessingLocation) {
        currentlyProcessingLocation = true;
        startTracking();
    }

    return START_NOT_STICKY;
}

private void startTracking() {
    Log.d(TAG, "startTracking");

    if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
        locationClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();


        if (!locationClient.isConnected() || !locationClient.isConnecting()) {
            locationClient.connect();
        }
    } else {
        Log.e(TAG, "unable to connect to google play services.");
    }
}

protected void sendLocationDataToWebsite(Location location) {
    // formatted for mysql datetime format
    Log.i(TAG, String.valueOf(location.getLatitude()) + " " + String.valueOf(location.getLongitude()));


}

@Override
public void onDestroy() {
    super.onDestroy();


    stopLocationUpdates();
    stopSelf();

}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onLocationChanged(Location location) {
    if (location != null) {
        Log.e(TAG, "position: " + location.getLatitude() + ", " + location.getLongitude() + " accuracy: " + location.getAccuracy());

        // we have our desired accuracy of 500 meters so lets quit this service,
        // onDestroy will be called and stop our location uodates
        sendLocationDataToWebsite(location);
    }
}

private void stopLocationUpdates() {
    if (locationClient != null && locationClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(locationClient, this);
        locationClient.disconnect();
    }
}

/**
 * Called by Location Services when the request to connect the
 * client finishes successfully. At this point, you can
 * request the current location or start periodic updates
 */
@Override
public void onConnected(Bundle bundle) {
    Log.d(TAG, "onConnected");

    locationRequest = new LocationRequest();
    locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    locationRequest.setInterval(Constants.UPDATE_INTERVAL);
    locationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);
    LocationServices.FusedLocationApi.requestLocationUpdates(locationClient,
            locationRequest, this);
}

@Override
public void onConnectionSuspended(int i) {
    stopLocationUpdates();
}

/**
 * Called by Location Services if the connection to the
 * location client drops because of an error.
 */

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.e(TAG, "onConnectionFailed");

    stopLocationUpdates();
    stopSelf();
}

public String getCurrentTime()
{
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
    String currentTime = sdf.format(new Date());
    return currentTime;
}

public String getDeviceName() {
    String manufacturer = Build.MANUFACTURER;
    String model = Build.MODEL;
    if (model.startsWith(manufacturer)) {
        return capitalize(model);
    } else {
        return capitalize(manufacturer) + " " + model;
    }
}

private String capitalize(String s) {
    if (s == null || s.length() == 0) {
        return "";
    }
    char first = s.charAt(0);
    if (Character.isUpperCase(first)) {
        return s;
    } else {
        return Character.toUpperCase(first) + s.substring(1);
    }
}

And this is my manifest这是我的清单

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.fikri.com.navigationsystem" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--
     The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
     Google Maps Android API v2, but you must specify either coarse or fine
     location permissions for the 'MyLocation' functionality. 
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar" >
    </activity>
    <activity
        android:name=".SplashScreen"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:label="@string/title_activity_splash_screen"
        android:theme="@style/FullscreenTheme" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!--
         The API key for Google Maps-based APIs is defined as a string resource.
         (See the file "res/values/google_maps_api.xml").
         Note that the API key is linked to the encryption key used to sign the APK.
         You need a different API key for each encryption key, including the release key that is used to
         sign the APK for publishing.
         You can define the keys for the debug and release targets in src/debug/ and src/release/. 
    -->
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key" />

    <activity
        android:name=".MapsActivity"
        android:label="@string/title_activity_maps" >
    </activity>

    <service android:name=".Service.LocationService">
    </service>

</application>

您可能应该阅读运行时权限使用运行时权限构建更好的应用程序,了解在针对 Android Marshmallow 时如何使用运行时权限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM