26

I want to use Google Cloud Natural Language in my Flutter app,I got Google API package This works for flutter and theGoogle API_AUTH dependence is working for 0.2.1. How do I implement them ?

PrimeNexes
  • 565
  • 1
  • 7
  • 17

4 Answers4

35

This worked for me:

Logging in using package google_sign_in and then get auth headers from it:

import 'package:google_sign_in/google_sign_in.dart'
    show GoogleSignIn, GoogleSignInAccount;

import 'package:googleapis/people/v1.dart'
    show ListConnectionsResponse, PeopleApi;

useGoogleApi() async {
  final _googleSignIn = new GoogleSignIn(
    scopes: [
      'email',
      'https://www.googleapis.com/auth/contacts.readonly',
    ],
  );

  await _googleSignIn.signIn();

  final authHeaders = _googleSignIn.currentUser.authHeaders;

  // custom IOClient from below
  final httpClient = GoogleHttpClient(authHeaders); 

  data = await PeopleApi(httpClient).people.connections.list(
      'people/me',
      personFields: 'names,addresses',
      pageToken: nextPageToken,
      pageSize: 100,
  );
}

This is a custom IOClient implementation that automatically adds the auth headers to each request. The googleapis call support passing a custom HTTP client to be used instead of the default (see above)

import 'package:http/io_client.dart';
import 'package:http/http.dart';

class GoogleHttpClient extends IOClient {
  Map<String, String> _headers;

  GoogleHttpClient(this._headers) : super();

  @override
  Future<StreamedResponse> send(BaseRequest request) =>
      super.send(request..headers.addAll(_headers));

  @override
  Future<Response> head(Object url, {Map<String, String> headers}) =>
      super.head(url, headers: headers..addAll(_headers));

}
Josh Metcalfe
  • 2,175
  • 2
  • 24
  • 34
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Can I use this `GoogleHttpClient` to send email using gmailAPI and/or to send invites using FireBase Invites? – mmccabe May 16 '18 at 22:54
  • I haven't used these APIs, but if Google provides APIs for these tasks, you should be able to do it with GiigleHttpClient. – Günter Zöchbauer May 17 '18 at 02:45
  • 2
    Was able to get it working for now using https://stackoverflow.com/questions/50079538/flutter-send-email-using-google-api . Will try to use your approach in future. – mmccabe May 17 '18 at 06:39
  • Where does GoogleHttpClient comes from? – Dpedrinha Sep 24 '19 at 02:18
  • 2
    I invented it in my answer above ;) It's just the name I used for my custom subclass of `IOClient` – Günter Zöchbauer Sep 24 '19 at 03:16
  • Oh god, sorry I didn't see it. Care to adapt your answer for this question? https://stackoverflow.com/questions/58072743/how-to-access-google-drive-appdata-folder-file-with-flutter – Dpedrinha Sep 24 '19 at 04:17
  • do you have a solution on what to do in case the access token expires? instead of calling SignIn() eveyr time – chitgoks Jan 29 '20 at 10:44
  • There should be a `await _googleSignIn.signInSilently();` for that. – Günter Zöchbauer Jan 29 '20 at 11:20
  • I have this verbatim, however am getting an error at GoogleHttpClient(authHeaders) saying 'The argument type Future> can't be assigned to the parameters type Map. The documentation link for the error is rather unhelpful. Any ideas? – Chris Hardaker Feb 01 '20 at 16:50
  • Try without `await`. I didn't work with Flutter since quite some time and haven't set up anything that would allow to check myself. – Günter Zöchbauer Feb 01 '20 at 17:00
  • For anyone experiencing the same issue with `authHeaders` as @ChrisHardaker, add `await` to the variable: `final authHeaders = _googleSignIn.currentUser.authHeaders;` – koopmac Mar 27 '20 at 10:38
  • Can you please elaborate on your answer and explain how you got your answer. For beginners, it can be confusing how to implement your solution into their own problems, i.e. using a different google api. – Hudson Kim Aug 04 '20 at 05:33
  • @HudsonKim sorry, but I won't have time for this anytime soon. – Günter Zöchbauer Aug 04 '20 at 05:38
  • @GünterZöchbauer do you have any resources that would be useful? – Hudson Kim Aug 04 '20 at 16:53
  • @HudsonKim sorry (again) I just saw the question and figured that I came up with a solution/workaround earlier and stripped it from project-specific code and posted it. I looked through the source of related packages and collected the bits from there. – Günter Zöchbauer Aug 04 '20 at 19:49
  • 1
    Thanks for this answer. Now with extension_google_sign_in_as_googleapis_auth package, you can use ready-to-use IOClient provided by this package instead of your own GoogleHttpClient implementation. It's a little change, but I posted as another answer. – kanji Apr 27 '21 at 09:03
  • @kanji Can you tell me more about this google_sign_in_as_googleapis_auth ? I'm relatively new in dart/flutter and I need to say that this documentation is very bad. – Flutter Supabase Jul 03 '21 at 12:54
  • @Tananga Though I agree that Google API package is not very easy to get to used to, I think the [documentation of google_sign_in_as_googleapis_auth](https://pub.dev/packages/extension_google_sign_in_as_googleapis_auth) is good enough. There is literally no more to explain than it is in the docs. Sorry that I cannot help... – kanji Jul 10 '21 at 00:10
14

I can't add comments yet, so I'll just post it as an answer.

I kept trying to make a GoogleHttpClient as per the top answer, but on the import, it says "The library 'package:http/http.dart' doesn't export a member with the shown name 'IOClient'."

I found the answer here https://pub.dartlang.org/packages/http#-changelog-tab-, which says you should import IOClient separately as such: import 'package:http/io_client.dart';

I thought this might help out others who are new to flutter and its implementation of Google APIs.

Kim Palao
  • 330
  • 4
  • 8
4

The accepted answer is most likely written towards an older version of the SDK I just couldn't get it to work. This is what works for me as of now.

As an example, the following allow us to access files in Google Drive which is part of googleapis.

Dependencies

pubspec.yaml:

dependencies:
  google_sign_in: any
  googleapis: any

(I just put any here as a example, but you should specific the version(s) for you actual app.)

How it works

Necessary imports:

import 'package:googleapis/drive/v3.dart' as drive;
import 'package:google_sign_in/google_sign_in.dart' as signIn;

Step 1, sign in the user and ask for access permission (scope) to google drive:

final googleSignIn = signIn.GoogleSignIn.standard(scopes: [drive.DriveApi.DriveScope]);
final sign.GoogleSignInAccount account = await googleSignIn.signIn();

Step 2, build a AuthenticateClient:

class AuthenticateClient extends http.BaseClient {
  final Map<String, String> headers;

  final http.Client client;

  AuthenticateClient(this.headers, this.client);

  Future<http.StreamedResponse> send(http.BaseRequest request) {
    return client.send(request..headers.addAll(headers));
  }
}

As suggested in http, this is using the BaseClient with extra authentication headers (being composable).

Step 3, create a authenticated http client with from step 1 and 2 and access google drive API.

final baseClient = new Client();
final authenticateClient = AuthenticateClient(authHeader, baseClient);
final driveApi = drive.DriveApi(authenticateClient);

Checkout How to Use the Google Drive API With Flutter Apps for details.

Yuchen
  • 30,852
  • 26
  • 164
  • 234
  • Can I ask what's the difference between this method and using the `authenticatedClient` function from the `googleapis_auth` package to get an authenticated client? – Nelson Yeung Dec 29 '20 at 13:28
3

Update to the accepted answer

Along with google_sign_in and googleapis packages, now you can use extension_google_sign_in_as_googleapis_auth package (provided by flutter.dev) to get configured http client. So the accepted answer can be simplified to below. No implementation of GoogleHttpClient is necessary.

import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/people/v1.dart';

useGoogleApi() async {
  final _googleSignIn = new GoogleSignIn(
    scopes: [
      'email',
      PeopleServiceApi.contactsReadonlyScope,
    ],
  );

  await _googleSignIn.signIn();

  // custom IOClient
  final httpClient = await _googleSignIn.authenticatedClient();

  data = await PeopleApi(httpClient!).people.connections.list(
      'people/me',
      personFields: 'names,addresses',
      pageToken: nextPageToken,
      pageSize: 100,
  );
}
kanji
  • 729
  • 9
  • 14
  • Where can I found "nextPageToken" ? – Flutter Supabase Jul 03 '21 at 14:03
  • @Tananga, I've not tested with this specific piece of code because that part of code is just copied from the accepted answer. But, according to the [People API documentation](https://developers.google.com/people/api/rest/v1/people.connections/list), `nextPageToken` is provided in the response of this method, and can be omitted or null since it is optional. – kanji Jul 10 '21 at 00:00