Permission issues for location in android Marshmallow applicaton

南楼画角 提交于 2020-01-19 01:48:46

问题


I am learning to develop an android application for getting device location following Google developers forum: @http://developer.android.com/training/location/retrieve-current.html#last-known @http://developer.android.com/training/location/receive-location-updates.html

The example shows how to use Google PLay Services for this purpose. But the getLastLocation() function always return null.

Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

As initially the location might be null, I added the following lines to receive periodic location updates

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

which throws an Exception with the following Message

Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations

I have already added the permissions in manifest file:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

I have opened Google Maps to update current location in Google Play Service as well, but the same problem persists. I am newbie to Android development, and before posting this question I already searched up a lot but didn't find any solution working for me. I am testing it on Android Marshmallow device, developing using Android Studio 1.3.2

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="newray.acpsa1">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <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">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

onCreate function in Activity

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(10 * 1000)        
                .setFastestInterval(1 * 1000); 
        /* Rest functionality */
    }

onConnected function

@Override
    public void onConnected(Bundle bundle) {
        try{
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        LatLng loc = new LatLng(21.356993, 72.826647);
        if (location == null) {
            Log.d(TAG,"location is again null");
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            Log.d(TAG, "Requested for updates");
        }
        else {
            loc = new LatLng(location.getLatitude(),location.getLongitude());
            handleNewLocation(location);
        }            
        } catch (Exception e) {
            Log.d(TAG, "Error in onConnected.  "+e.getMessage());

        }
    }

Logs:

XXXX: Error in onConnected.  Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.

dependencies in build.gradle file:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.google.android.gms:play-services:8.1.0'
    compile 'com.google.android.gms:play-services-location:8.1.0'
}

回答1:


In Marshmallow there are lots of new things in android SDK. Asking the permission is one of it's new update that every developer should keep in mind. The similar thing happen with you. if your application target version 23 then you probably should have to take grant from the user before start to use it. You can only use it if user allow to access.Therefor developer need to take care all the test-case while taking the permission from the user into the application

For example your application need the access of the Location. In earlier version of android at time on installed it was show the permission dialog and they were granted the defined permission in your manifest file to the application. This things changed into the Marshmallow. Now each application should have to take permission from user to access the it.

See the developer sites and learn the basic steps for how to guide the user into the application for asking the runtime permission into the application.

There are lots of sites showing your the basic tutorial about how to ask the permission in Marshmallow. few can suggest as below

Building better application with runtime permission

Permissions design guide

This link guide you the basic info of how to guide the user into the application before asking the permission.

Thanks.




回答2:


Straight forward solution/example for your question:

package com.my.packagename;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private static final int PERMISSION_REQUEST_CODE_LOCATION = 1;

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

    if (checkPermission(Manifest.permission.ACCESS_FINE_LOCATION,getApplicationContext(),CopyOfMap.this)) {
        fetchLocationData();
    }
    else
    {
        requestPermission(Manifest.permission.ACCESS_FINE_LOCATION,PERMISSION_REQUEST_CODE_LOCATION,getApplicationContext(),CopyOfMap.this);
    }
}

public static void requestPermission(String strPermission,int perCode,Context _c,Activity _a){

    if (ActivityCompat.shouldShowRequestPermissionRationale(_a,strPermission)){
                Toast.makeText(getApplicationContext(),"GPS permission allows us to access location data. Please allow in App Settings for additional functionality.",Toast.LENGTH_LONG).show();
            } else {

                ActivityCompat.requestPermissions(_a,new String[]{strPermission},perCode);
            }
    }

public static boolean checkPermission(String strPermission,Context _c,Activity _a){
        int result = ContextCompat.checkSelfPermission(_c, strPermission);
        if (result == PackageManager.PERMISSION_GRANTED){

            return true;

        } else {

            return false;

        }
    }

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {

        case PERMISSION_REQUEST_CODE_LOCATION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                fetchLocationData();

            } else {

                Toast.makeText(getApplicationContext(),"Permission Denied, You cannot access location data.",Toast.LENGTH_LONG).show();

            }
            break;

    }
}


    private void fetchLocationData()
    {
    //code to use the granted permission (location)
    }
}

Here i've made the requestPermission() and checkPermission() method as public static because i can reuse them for other permission requests like phone call, write storage, and others. Hope this will help some one. :-)



来源:https://stackoverflow.com/questions/33579280/permission-issues-for-location-in-android-marshmallow-applicaton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!