Permission issues for location in android Marshmallow applicaton

25,367

Solution 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.

Solution 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. :-)

Share:
25,367
Naveen
Author by

Naveen

Updated on July 09, 2022

Comments

  • Naveen
    Naveen almost 2 years

    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'
    }
    
  • Bhavdip Sagar
    Bhavdip Sagar over 8 years
  • kadik
    kadik about 8 years
    @Annes U What abou 'PERMISSION_REQUEST_CODE_LOCATION'
  • hi0001234d
    hi0001234d almost 8 years
    Though it's late but if it helps someone else too, @kadik it's int constant that you need to define in your app which is later passed back to you in onRequestPermissionsResult function
  • Hammad Nasir
    Hammad Nasir over 7 years
    I'm doing something similar, still having this issue: stackoverflow.com/questions/41206885/…'