ApiException:9003:PLACES_API_ACCESS_NOT_CONFIGURED

Posted

技术标签:

【中文标题】ApiException:9003:PLACES_API_ACCESS_NOT_CONFIGURED【英文标题】:ApiException: 9003: PLACES_API_ACCESS_NOT_CONFIGURED 【发布时间】:2019-07-24 16:33:30 【问题描述】:

我正在关注当前的地方教程:Select Current Place and Show Details on a Map

我不断收到以下运行时异常:

com.google.android.gms.common.api.ApiException: 9003: PLACES_API_ACCESS_NOT_CONFIGURED

我尝试了以下步骤:

    在开发者控制台中启用 Places API 使用迁移指南:Migrating to the New Places SDK Client #New methods 对于新的 Places SDK,因为本教程使用已弃用的 Places SDK,即添加新的依赖项。 在我的 Android 清单文件中添加以下代码
<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />    
<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="@string/api_key" />
    重新生成了我的 API 密钥。

我也在使用似乎工作正常的 Maps SDK。 Maps SDK 和 Places API 都在开发者控制台上启用。

即使在尝试了所有这些步骤之后,我仍然会收到运行时错误:

ApiException: 9003: PLACES_API_ACCESS_NOT_CONFIGURED 错误

我的代码:

package com.arnav.akapplications.mapfinder;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.PersistableBundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.PlaceDetectionClient;
import com.google.android.gms.location.places.PlaceLikelihood;
import com.google.android.gms.location.places.PlaceLikelihoodBufferResponse;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.squareup.picasso.Picasso;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, LocationListener 
    public static final String GOOGLE_ACCOUNT = "google_account";
    private static final String TAG = MainActivity.class.getSimpleName();
    public DrawerLayout drawerLayout;
    public Toolbar toolbar;
    TextView profileName,profileEmailID;
    ImageView profilePhoto;

    GoogleSignInAccount googleSignInAccount;
    GoogleSignInClient googleSignInClient;

    private GeoDataClient geoDataClient;
    private PlaceDetectionClient placeDetectionClient;
    private FusedLocationProviderClient fusedLocationProviderClient;
    private GoogleMap mMap;
    private Location lastKnownLocation;
    private CameraPosition cameraPosition;
    public LocationManager locationManager;
    public Criteria criteria;
    public String bestProvider;
    public double latitude,longitude;

    private boolean LocationPermissionGranted;
    private static final int PERMISSION_REQUEST_ACCESS_LOCATION = 1;
    private static final int DEFAULT_ZOOM = 15;
    private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
    private static final int M_MAX_ENTRIES = 5;
    private static final String KEY_CAMERA_POSITION = "camera_position";
    private static final String KEY_LOCATION = "location";

    private String[] likelyPlaceNames;
    private String[] likelyPlaceAddresses;
    private String[] likelyPlaceAttributions;
    private LatLng[] likelyPlaceLatLng;

    SupportMapFragment supportMapFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        if(savedInstanceState!=null)
        
            lastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
            cameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
        

        setContentView(R.layout.activity_main);

//        Places.initialize(getApplicationContext(), "AIzaSyCpmMHo0xQs-U_mXlGUOxFOReO0NlKv3CU");
//
//        PlacesClient placesClient = Places.createClient(this);


        googleSignInAccount = getIntent().getParcelableExtra(GOOGLE_ACCOUNT);

        GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build();

        googleSignInClient = GoogleSignIn.getClient(this,googleSignInOptions);

        drawerLayout=findViewById(R.id.drawer_layout);
        toolbar=findViewById(R.id.toolbar);

        ActionBar actionbar = getSupportActionBar();
        actionbar.setDisplayHomeAsUpEnabled(true);
        actionbar.setHomeButtonEnabled(true);
        actionbar.setHomeAsUpIndicator(R.drawable.ic_menu_black_24dp);

        geoDataClient = Places.getGeoDataClient(this);
        placeDetectionClient = Places.getPlaceDetectionClient(this);
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);

        supportMapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
        supportMapFragment.getMapAsync(this);


        NavigationView navigationView=findViewById(R.id.navigation_view);

        profileName = navigationView.getHeaderView(0).findViewById(R.id.profileName);
        profileEmailID = navigationView.getHeaderView(0).findViewById(R.id.profileEmailID);
        profilePhoto = navigationView.getHeaderView(0).findViewById(R.id.profilePhoto);
        Uri photoUrl = googleSignInAccount.getPhotoUrl();

        profileName.setText(googleSignInAccount.getDisplayName());
        profileEmailID.setText(googleSignInAccount.getEmail());
        Picasso.with(getApplicationContext())
                .load(photoUrl.toString())
                .placeholder(android.R.drawable.sym_def_app_icon)
                .resize(100, 100)
                .transform(new CircleTransform())
                .centerCrop()
                .into(profilePhoto);

        navigationView.setNavigationItemSelectedListener(   new NavigationView.OnNavigationItemSelectedListener() 
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) 
//                item.setChecked(true);
                switch(item.getItemId())
                
                    case R.id.search_books:  //do something
                        break;

                    case R.id.search_movie:  //do something
                        break;

                    case R.id.logout:
                        googleSignInClient.signOut().addOnCompleteListener(new OnCompleteListener<Void>() 
                            @Override
                            public void onComplete(@NonNull Task<Void> task) 
                                Intent intent = new Intent(MainActivity.this,LoginActivity.class);
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                                startActivity(intent);
                            
                        );
                        break;

                    case R.id.finish:
                        System.exit(0);
                        break;

                

                drawerLayout.closeDrawers();
                return true;
            
        );

    

    @Override
    public void onSaveInstanceState(Bundle outState) 
        if(mMap != null)
        
            outState.putParcelable(KEY_CAMERA_POSITION,mMap.getCameraPosition());
            outState.putParcelable(KEY_LOCATION,lastKnownLocation);
            super.onSaveInstanceState(outState);
        
    

    @Override
    public void onBackPressed() 
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) 
            drawer.closeDrawer(GravityCompat.START);
         else 
            super.onBackPressed();
        
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_items,menu);
        return super.onCreateOptionsMenu(menu);
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch(item.getItemId())
        
            case R.id.aboutProfile:
                Intent intent = new Intent(this,ProfileActivity.class);
                intent.putExtra(ProfileActivity.GOOGLE_ACCOUNT,googleSignInAccount);
                startActivity(intent);
                break;
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.option_get_place:
                showCurrentPlace();
                break;

        
        return true;
    

    private void updateLocationUI()
    
        if(mMap == null)
            return;

        try
        
            if(LocationPermissionGranted)
            
                mMap.setMyLocationEnabled(true);
                mMap.getUiSettings().setMyLocationButtonEnabled(true);
            
            else
            
                mMap.setMyLocationEnabled(false);
                mMap.getUiSettings().setMyLocationButtonEnabled(false);
                lastKnownLocation = null;
                getLocationPermission();
            
        
        catch (SecurityException e)
        
            Log.e("Exception: %s",e.getMessage() );
        
    

    private void getLocationPermission()
    
        if(ContextCompat.checkSelfPermission(this.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
        
            LocationPermissionGranted = true;
        
        else
        
            ActivityCompat.requestPermissions(this,new String[]Manifest.permission.ACCESS_FINE_LOCATION,PERMISSION_REQUEST_ACCESS_LOCATION);
        
    

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
        LocationPermissionGranted = false;
        switch(requestCode)
        
            case PERMISSION_REQUEST_ACCESS_LOCATION:
            
                if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) 
                    LocationPermissionGranted = true;
                
            
        
        updateLocationUI();
    

    private void getDeviceLocation()
    
        try
        
            if(LocationPermissionGranted)
            
                locationManager = (LocationManager)  this.getSystemService(Context.LOCATION_SERVICE);
                criteria = new Criteria();
                bestProvider = String.valueOf(locationManager.getBestProvider(criteria, true));

                Location location = locationManager.getLastKnownLocation(bestProvider);
                if(location != null)
                
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),DEFAULT_ZOOM));
                
                else
                
                    locationManager.requestLocationUpdates(bestProvider,1000,0,this);
                


            
        
        catch(SecurityException e)
        
            Log.e("Exception : %s" , e.getMessage());
        
    

    @Override
    public void onMapReady(GoogleMap googleMap) 

        mMap = googleMap;

        googleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() 
            @Override
            public View getInfoWindow(Marker marker) 
                return null;
            

            @Override
            public View getInfoContents(Marker marker) 
                View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents,null);

                TextView title = ((TextView) infoWindow.findViewById(R.id.title));
                TextView snippet = ((TextView)infoWindow.findViewById(R.id.snippet));

                title.setText(marker.getTitle());
                snippet.setText(marker.getSnippet());

                return infoWindow;
            
        );

        getLocationPermission();

        updateLocationUI();

        getDeviceLocation();

    

    private void showCurrentPlace()
    
        if(mMap == null) 
            Toast.makeText(this, "hello", Toast.LENGTH_LONG).show();
        


       if(LocationPermissionGranted)
       
           @SuppressLint("MissingPermission") final Task<PlaceLikelihoodBufferResponse> placeResult = placeDetectionClient.getCurrentPlace(null);

           placeResult.addOnCompleteListener(new OnCompleteListener<PlaceLikelihoodBufferResponse>() 
               @Override
               public void onComplete(@NonNull Task<PlaceLikelihoodBufferResponse> task) 
                   if(task.isSuccessful() && task.getResult()!= null) 
                       PlaceLikelihoodBufferResponse placeLikelihoodBufferResponse = task.getResult();

                       int count,i=0;

                       if(placeLikelihoodBufferResponse.getCount() < M_MAX_ENTRIES) 
                           count = placeLikelihoodBufferResponse.getCount();
                       
                       else 
                           count = M_MAX_ENTRIES;
                       

                       likelyPlaceNames = new String[count];
                       likelyPlaceAddresses = new String[count];
                       likelyPlaceAttributions = new String[count];
                       likelyPlaceLatLng = new LatLng[count];

                       for(PlaceLikelihood placeLikelihood : placeLikelihoodBufferResponse)     
                           likelyPlaceNames[i] = (String) placeLikelihood.getPlace().getName();
                           likelyPlaceAddresses[i] = (String) placeLikelihood.getPlace().getAddress();
                           likelyPlaceAttributions[i] = (String) placeLikelihood.getPlace().getAttributions();
                           likelyPlaceLatLng[i] = placeLikelihood.getPlace().getLatLng();

                           i++;
                           if (i > (count - 1)) 
                               break;
                           
                       
                       placeLikelihoodBufferResponse.release();

                       openPlacesDialog();
                   
                   else
                   
                       Log.e(TAG,"Exception :%s" + task.getException());
                   
               
           );
       
       else
       
           Log.i(TAG,"the user did not grant location permission");

           mMap.addMarker(new MarkerOptions().title(getString(R.string.default_info_title)).position(mDefaultLocation).snippet(getString(R.string.default_info_snippet)));

           getLocationPermission();
       
    

    private void openPlacesDialog()
    
        DialogInterface.OnClickListener dialogListener = new DialogInterface.OnClickListener() 
            @Override
            public void onClick(DialogInterface dialog, int which) 
                LatLng markerLatLng = likelyPlaceLatLng[which];
                String markerSnippet = likelyPlaceAddresses[which];
                if(likelyPlaceAttributions[which] != null)
                
                    markerSnippet = markerSnippet + "\n" + likelyPlaceAttributions[which];
                

                mMap.addMarker(new MarkerOptions().title(likelyPlaceNames[which]).position(markerLatLng).snippet(markerSnippet));

                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(markerLatLng,DEFAULT_ZOOM));

            
        ;

        AlertDialog dialog = new AlertDialog.Builder(this).setTitle(R.string.pick_place).setItems(likelyPlaceNames,dialogListener).show();
        dialog.create();

    


    @Override
    public void onLocationChanged(Location location) 
        locationManager.removeUpdates(this);

        //open the map:
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        Toast.makeText(MainActivity.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();

    

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) 

    

    @Override
    public void onProviderEnabled(String provider) 

    

    @Override
    public void onProviderDisabled(String provider) 

    

AndroidManifest.xml

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



    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/api_key" />
        <activity android:name=".ProfileActivity"/>
        <activity android:name=".MainActivity"
            android:theme="@style/AppTheme"/>
        <activity android:name=".LoginActivity"
            android:theme="@style/AppTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

应用级 build.gradle 文件:

apply plugin: 'com.android.application'

android 
    compileSdkVersion 27
    defaultConfig 
        applicationId "com.arnav.akapplications.mapfinder"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
        resValue "string", "google_places_key", (project.findProperty("GOOGLE_PLACES_API_KEY") ?: "")
    
    buildTypes 
        release 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        
    


dependencies 
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //noinspection GradleCompatible
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.android.gms:play-services-auth:16.0.1'
    implementation 'com.squareup.picasso:picasso:2.5.2'
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.google.android.gms:play-services-location:16.0.0'
    implementation 'com.google.android.libraries.places:places-compat:1.0.0'


【问题讨论】:

过去两天我也面临同样的问题。如果您找到解决方案,请告诉我。 当然。您还尝试过哪些无效的方法? @arnavJJ 我认为您无法为您的代码实施迁移指南。我正在发布我的答案。查看并实施它。 【参考方案1】:

很多朋友建议我发布我是如何在我的项目上实现这个(自动完成)的。所以我建议你看看这个迁移指南并逐步在你的项目上实现。

迁移指南:-https://developers.google.com/places/android-sdk/client-migration

转到此link 以创建 API 密钥:

按照以下步骤在您的项目中实施自动完成:-

自动完成有两种实现方式。

    使用意图

    使用 AutocompleteFragment

    在这两种情况下,请按照以下步骤操作:-

     1. Add this line in build.gradle file
    
    dependencies 
      implementation 'com.google.android.libraries.places:places:2.1.0'
    
    
     2. Add other dependencies (This is optional) .
    
    dependencies 
      implementation 'com.google.android.libraries.places:places-compat:1.0.0'
    
    
    implementation 'com.google.android.gms:play-services-places:16.0.0'
    
     3. // Add an import statement for the client library.
    
    import com.google.android.libraries.places.api.Places;
    
    // Initialize Places.
    
    Places.initialize(getApplicationContext(), apiKey);
    
    // Create a new Places client instance.
    
    PlacesClient placesClient = Places.createClient(this);
    

    ---------现在选择您要在项目中实施的任何方法。-----

    使用意图

     if (!Places.isInitialized()) 
            Places.initialize(getApplicationContext(), "YOUR_API_KEY");
        
    
        ...
    
        // Set the fields to specify which types of place data to return.
        List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
    
        // Start the autocomplete intent.
        Intent intent = new Autocomplete.IntentBuilder(
                AutocompleteActivityMode.FULLSCREEN, fields)
                .build(this);
        startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
    
    
    and OnActivityResult method-------
    
    
        /**
         * Override the activity's onActivityResult(), check the request code, and
         * do something with the returned place data (in this example it's place name and place ID).
         */
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) 
            if (requestCode == AUTOCOMPLETE_REQUEST_CODE) 
                if (resultCode == RESULT_OK) 
                    Place place = Autocomplete.getPlaceFromIntent(data);
                    Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
                 else if (resultCode == AutocompleteActivity.RESULT_ERROR) 
                    // TODO: Handle the error.
                    Status status = Autocomplete.getStatusFromIntent(data);
                    Log.i(TAG, status.getStatusMessage());
                 else if (resultCode == RESULT_CANCELED) 
                    // The user canceled the operation.
                
            
        
    

    使用片段

    在 .xml 文件上初始化此自动完成片段

    <fragment
      android:id="@+id/autocomplete_fragment"
      android:layout_
      android:layout_
      android:name=
    "com.google.android.libraries.places.widget.AutocompleteSupportFragment"
      />
    

    -------------- 和.class文件--------------------------

    初始化 Places,传递应用程序上下文和您的 API 密钥。 初始化 AutocompleteSupportFragment。 调用 setPlaceFields() 以指示您想要获取的地点数据的类型。 添加 PlaceSelectionListener 以对结果进行处理,并处理可能发生的任何错误。 以下示例显示了向 Activity 添加自动完成小部件:

     if (!Places.isInitialized()) 
            Places.initialize(getApplicationContext(), "YOUR_API_KEY");
        
    
    
        // Initialize the AutocompleteSupportFragment.
    
        AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
                getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
    
    
        autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
    
    
        autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() 
            @Override
            public void onPlaceSelected(Place place) 
                // TODO: Get info about the selected place.
                Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
            
    
            @Override
            public void onError(Status status) 
                // TODO: Handle the error.
                Log.i(TAG, "An error occurred: " + status);
            
        );
    

然后像这样从选定的地方获取 LATLONG:-

    LatLng latLng = place.getLatLng();
    String mStringLatitude = String.valueOf(latLng.latitude);
    String mStringLongitude = String.valueOf(latLng.longitude);

希望这会对你有所帮助。

【讨论】:

places_compat有什么用? @IgorGanapolsky 抱歉回复晚了。但请参考此链接了解 place_compact。developers.google.com/places/android-sdk/…

以上是关于ApiException:9003:PLACES_API_ACCESS_NOT_CONFIGURED的主要内容,如果未能解决你的问题,请参考以下文章

Laravel ->Exceptions ->ApiException 自定义错误异常的封装

(ApiException.class) -> 从 java 到 C#?

Google 登录失败(ApiException:12501)

谷歌排行榜 ApiException

SQL SERVER 9003错误解决方法 只适用于SQL2000

Android 磨损:地理围栏 - ApiException:1000