简体   繁体   English

android Marshmallow应用程序中位置的权限问题

[英]Permission issues for location in android Marshmallow applicaton

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 我正在学习开发一个Android应用程序,以便在Google开发者论坛之后获取设备位置:@ http://developer.android.com/training/location/retrieve-current.html#last-known @ http://developer.android。 COM /培训/位置/接收位置updates.html

The example shows how to use Google PLay Services for this purpose. 该示例显示了如何将Google PLay服务用于此目的。 But the getLastLocation() function always return null. getLastLocation()函数始终返回null。

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

As initially the location might be null, I added the following lines to receive periodic location updates 最初位置可能为null,我添加了以下行以接收定期位置更新

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 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 客户端必须具有ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限才能执行任何位置操作

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. 我已经打开Goog​​le地图以更新Google Play服务中的当前位置,但同样的问题仍然存在。 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. 我是Android开发的新手,在发布这个问题之前我已经搜索了很多但没有找到适合我的任何解决方案。 I am testing it on Android Marshmallow device, developing using Android Studio 1.3.2 我在Android Marshmallow设备上测试它,使用Android Studio 1.3.2

AndroidManifest.xml 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 onCreate函数在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 onConnected功能

@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: build.gradle文件中的依赖项:

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'
}

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. 在这里,我将requestPermission()和checkPermission()方法设置为公共静态,因为我可以将它们重用于其他权限请求,如电话呼叫,写入存储等。 Hope this will help some one. 希望这对一些人有所帮助。 :-) :-)

In Marshmallow there are lots of new things in android SDK. 在Marshmallow中,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. 如果您的应用程序目标版本为23,则您可能必须在开始使用之前从用户获取授权。 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. 在安装时的早期版本的android中,它显示了权限对话框,并且它们被清单文件中的已定义权限授予应用程序。 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. 查看开发人员站点并了解如何引导用户进入应用程序以询问应用程序的runtime permission的基本步骤。

There are lots of sites showing your the basic tutorial about how to ask the permission in Marshmallow. 有很多网站显示了关于如何在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. 谢谢。

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

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