Google Places API Error - ApiException: 9008: PLACES_API_INVALID_APP
B

2

7

I want to use Google Places API in one of my Android Application. But I'm getting this error:

com.google.android.gms.tasks.RuntimeExecutionException: com.google.android.gms.common.api.ApiException: 9008: PLACES_API_INVALID_APP

What I have done until now.

  • I created API key in https://console.developers.google.com
  • Selected Android apps in Application restrictions and added Package name & SHA-1 certificate fingerprint.
  • I added <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_places_api_key" /> in AndroidManifest.xml file.
  • I checked more than 3 times that I'm using the same API key in which I have added Package name & SHA-1 certificate fingerprint.
  • I created another API KEY to just check If it is working with that or not. I found that when I add Package name & SHA-1 certificate fingerprint, It will give me ERROR mentioned above otherwise It is working fine.
  • I tried to add Release SHA-1 also but getting same error.

My code is like below.

EmploymentDetailsActivity.java

    public class EmploymentDetailsActivity extends BaseActivity {


    @BindView(R.id.aet_employment_employer)
    AutoCompleteTextView employerAutoCompleteTextView;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_employment_details);
        ButterKnife.bind(this);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        mGeoDataClient = Places.getGeoDataClient(this);

        final GooglePlacesAdapter adapter = new GooglePlacesAdapter(this);
        employerAutoCompleteTextView.setAdapter(adapter);
        employerAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                final AutocompletePrediction item = adapter.getItem(position);
                final String placeId = item.getPlaceId();
                final CharSequence primaryText = item.getPrimaryText(null);

                employerAutoCompleteTextView.setText(primaryText);

                Task<PlaceBufferResponse> placeResult = mGeoDataClient.getPlaceById(placeId);
                placeResult.addOnCompleteListener(mUpdatePlaceDetailsCallback);
            }
        });
    }
}

GooglePlacesAdapter.java

    public class GooglePlacesAdapter extends ArrayAdapter<AutocompletePrediction> implements Filterable {

    private Context mContext;
    private GeoDataClient mGeoDataClient;
    private static final String TAG = "mk";
    private ArrayList<AutocompletePrediction> mResultList;

    public GooglePlacesAdapter(Context context) {
        super(context, android.R.layout.simple_dropdown_item_1line);
        this.mContext = context;
        mGeoDataClient = Places.getGeoDataClient(mContext);
    }

    @Override
    public int getCount() {
        return mResultList.size();
    }

    @Override
    public AutocompletePrediction getItem(int position) {
        return mResultList.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_google_places, parent, false);
        }

        AutocompletePrediction autocompletePrediction = getItem(position);

        TextView placeName = convertView.findViewById(R.id.tv_primary_text);
        TextView placeAddress = convertView.findViewById(R.id.tv_secondary_text);

        placeName.setText(autocompletePrediction.getPrimaryText(null));
        placeAddress.setText(autocompletePrediction.getSecondaryText(null));

        return convertView;
    }

    @Override
    public Filter getFilter() {

        return new Filter() {

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();

                if (constraint != null) {

                    mResultList = getAutocomplete(constraint);

                    if (mResultList != null) {
                        results.values = mResultList;
                        results.count = mResultList.size();
                    }
                }

                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results != null && results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        };
    }

    private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {

        AutocompleteFilter.Builder filterBuilder = new AutocompleteFilter.Builder();
        filterBuilder.setTypeFilter(AutocompleteFilter.TYPE_FILTER_NONE).setCountry("IN");

        Log.e(TAG, "constraint.toString(): " + constraint.toString());

        Task<AutocompletePredictionBufferResponse> results =
                mGeoDataClient.getAutocompletePredictions(constraint.toString(), null,
                        filterBuilder.build());

        // 60s for a result from the API.
        try {
            Tasks.await(results, 60, TimeUnit.SECONDS);
        } catch (ExecutionException | InterruptedException | TimeoutException e) {
            e.printStackTrace();
        }

        try {

            AutocompletePredictionBufferResponse autocompletePredictions = results.getResult();

            // Freeze the results immutable representation that can be stored safely.
            return DataBufferUtils.freezeAndClose(autocompletePredictions);

        } catch (RuntimeExecutionException e) {

            // If the query did not complete successfully return null
            Toast.makeText(getContext(), "Error contacting API: " + e.toString(), Toast.LENGTH_SHORT).show();

            Log.e(TAG, "Error getting autocomplete prediction API call", e);

            return null;
        }
    }
}

AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.xxxxxxxx.xxxxx">

<application
        android:name=".ConsumerApplication"
        android:allowBackup="true"
        android:icon="@mipmap/app_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/app_icon"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_places_api_key" />
</application>

</manifest>

strings.xml

<resources>
    <string name="google_places_api_key">AIzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</string>
</resources>

build.gradle (app)

    dependencies {
    implementation 'com.android.support:support-v4:26.1.0'
    implementation 'com.google.android.gms:play-services-maps:15.0.1'
    ext {
        playServicesVersion = '15.0.1'
    }
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.razorpay:checkout:1.4.7'
    compile "com.google.android.gms:play-services-vision:${playServicesVersion}"
    compile "com.google.android.gms:play-services-location:${playServicesVersion}"
    //compile "com.google.android.gms:play-services:${playServicesVersion}"
    compile "com.google.android.gms:play-services-places:${playServicesVersion}"
    compile 'com.android.support:appcompat-v7:26.1.0'
    compile 'com.android.support:cardview-v7:26.1.0'
    compile 'com.android.support:recyclerview-v7:26.1.0'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.android.volley:volley:1.0.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'org.apache.commons:commons-lang3:3.4'
    compile 'commons-io:commons-io:2.4'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'com.google.dagger:dagger:2.10'
    compile 'com.jakewharton:butterknife:8.5.1'
    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
    compile 'com.squareup.okio:okio:1.13.0'
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.retrofit2:converter-gson:2.0.1'
    compile 'com.android.support:multidex:1.0.1'
    compile 'org.apache.commons:commons-lang3:3.4'
    compile 'com.android.support:design:26.1.0'
    compile 'com.github.arthurghazaryan:floatingactionmenu:1.0.0'
    compile 'com.quiklo.jsonapi.customer:cust-app:1.0'
    compile 'com.quiklo.jsonapi.shared:basic:1.0'
    compile 'com.olmec.smartloan.shared:shared-api:1.0'
    compile 'com.jaredrummler:material-spinner:1.1.0'
    compile 'com.f2prateek.dart:dart:2.0.2'
    compile 'com.f2prateek.dart:henson:2.0.2'
    //    compile 'uk.co.markormesher:android-fab:2.2.2'
    testCompile 'junit:junit:4.12'
    annotationProcessor 'com.f2prateek.dart:dart-processor:2.0.2'
    annotationProcessor 'com.f2prateek.dart:henson-processor:2.0.2'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
    annotationProcessor 'com.google.guava:guava:19.0'
}
apply plugin: 'com.google.gms.google-services'

Let me know If any details required. Thanks in advance.

Berke answered 29/5, 2018 at 7:22 Comment(5)
Are you getting this error in production apk or in test? Probably is error with SHAManton
In test and production both. Strange thing is, While adding Package Name and SHA-1 finger print it is giving me error. Second strange thing is it giving me error for this particular app only. I have another app, in that app it is working fine.@ParaskevasNtsounosBerke
As per documentation, the error caused due to the app not being allowed to use the API key. Maybe the API key is not configured, go to your API console and check API key Restrictions if it is allowed to use by Android apps. /PlacesStatusCodes.html#INVALID_APPPricilla
As I mentioned in above comment, problem remains same. If I will enter package name & SHA-1 finger print It will give me error. Otherwise It is working fine. Can you provide Google Group for this, where I will ask question regarding this **ISSUE**@ArpanßløødyßadßøyBerke
Enable the Android Places Api . Check also the SHA-1 that are created correct.Ladawnladd
B
3

I got the solution. It was package name who was causing problem.

In build.gradle (Module: app) I'm having applicationIdSuffix which will change package name when you switch to mock version.

Since package name will change, CORRECT SHA-1 finger print will also not work. So, I need to append .mock and put it in Google API Console then It started working.

productFlavors {
    mock {
        versionNameSuffix ":test"
        applicationIdSuffix = ".mock"
        buildConfigField "String", "PING_URL", '"https://demoapps.xxxxxxxxx.com/"'
        signingConfig signingConfigs.ReleaseBuild
    }
    prod {
        buildConfigField "String", "PING_URL", '"https://apps.xxxxxxxxx.com/"'
    }
}
Berke answered 5/6, 2018 at 5:37 Comment(0)
S
0

It is most likely you are missing one of this

  • You have to enable places API from console.
  • You are storing keys as string resources. There are two variants of string resources - debug and release.
Stefanstefanac answered 4/6, 2018 at 18:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.