How to use Google API in flutter? - dart

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 ?

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));
}

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.

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.

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,
);
}

Related

Import dart:html in Service got exception No provider found for dynamic

I have a working UserService similar to HeroService from AngularDart tutorial with BrowserClient.
And now I need to use localStorage to save the API response.
After I import dart:html, I refresh my browser, suddenly I got error on console:
EXCEPTION: No provider found for dynamic: UserService -> dynamic.
When I remove the import, the service running well.
this is my UserService code.
import 'dart:convert';
import 'dart:html';
import 'package:http/http.dart';
import 'package:my_app/src/instance_logger.dart';
class UserService with InstanceLogger {
static final _headers = {'Content-Type': 'application/json'};
static const _authUrl = 'https://my.domain/api-token-auth/';
String get loggerPrefix => 'UserService'; // or set ''
final Client _http;
UserService(this._http);
dynamic _extractData(Response resp) => json.decode(resp.body)['data'];
Exception _handleError(dynamic e) {
log(e); // for demo purposes only
return Exception('Server error; cause: $e');
}
}
in Component meta-data:
providers: [ClassProvider(UserService)],
how to use dart:html within service? If I want to access localStorage.
thank you.
Both dart:html and package:http/http.dart unfortunately have a class named Client.
How you get around this collision is to hide an unwanted class from being imported with its package.
Change
import 'dart:html';
to
import 'dart:html' hide Client;
That will take care of the collision. You could alternatively give the import an alias such as:
import 'dart:html' as html;
Then you can use localStorage by using the prefix html.localStorage;
When I run into this problem I just hide the Client class from the dart:html import.

How to get Client parameter for google_api from firebase auth [duplicate]

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 ?
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));
}
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.
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.
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,
);
}

How to do JSON parsing in GRPC micro-services in iOS using Swift 4.1 (Xcode 10)?

I am working on a project, that used GRPC microservices. Normally GRPC used protobuf as his default method to serialized data. But, we are using JSON as placed of protobuf. In general, we defined message and services in protobuf and complied with protoc , then merged generated file with the project. But somehow google made tough to merged JSON in GRPC. I thought Google should make a documentation like this (https://grpc.io/blog/grpc-with-json) for iOS developer too. But unfortunately, there is no separate documentation in Swift. I found it hard to used JSON type in GRPC. How will I call methods in CLIENT-SIDE code in Swift?
I want to pass two variable (data: String, idToken: String) i.e defined in Request struct after that services should give me a Response. In that way, I would understand both get and post method used in GRPC.
https://grpc.io/blog/grpc-with-json , In this link, we can check how java works with JSON+GRPC. I am adding this java code example for more understanding oh what I want to make in Swift, Maybe it will do some help.
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import io.grpc.MethodDescriptor;
public class UserManagerRpcGson {
private static final String SERVICE_NAME = "url";
public static final class Request {
public String data;
public String idToken;
}
public static final MethodDescriptor<Request, Response> REGISTER_METHOD =
MethodDescriptor.newBuilder(
marshallerFor(Request.class),
marshallerFor(Response.class))
.setFullMethodName(
MethodDescriptor.generateFullMethodName(SERVICE_NAME, "registerUser"))
.setType(MethodDescriptor.MethodType.UNARY)
.setSampledToLocalTracing(true)
.build();
static <T> MethodDescriptor.Marshaller<T> marshallerFor(Class<T> clz) {
return new MethodDescriptor.Marshaller<T>() {
#Override
public InputStream stream(T value) {
return new ByteArrayInputStream(GsonUtil.gson.toJson(value, clz).getBytes(StandardCharsets.UTF_8));
}
#Override
public T parse(InputStream stream) {
return GsonUtil.gson.fromJson(new InputStreamReader(stream, StandardCharsets.UTF_8), clz);
}
};
}
}

Flutter/dart- download data from mysql server database

To preface this i am new to all of this and don't need step by step information, just seeing what is possible.
I've been toying around with connecting my flutter/dart app to a mysql backend
Im connecting to it using sqljocky and was wondering if there is anyway users can download data from it for offline use. I read about NSUserDefaults (for ios) and Shared_Preferences (for android) for storage of persistent and simple data on the app and wanted to know if this is the correct route to continue on.
I think this answer is required here:
Few days ago I had to dealt with a existing MySQL database and there was no way to do it with Dart except over network requests(there is a sqljocky package which is Dart 2 incompatible). Read best options here.
Here Im going to show an example for a simple fetch data using Flutter http request with simple PHP & MySQL.
Note: This is may not 100% secure.
If you are doing in local server, you need to have server(ex: apache) running and MySQL(you can use XAMPP to get both).
Step 1: create a database.
Step 2: create a folder in htdocs(in XAMP). Next, inside that file create file called conn.php. Then, add below snippet and change
with your db credentials to connect to database.
<?php
$connection = new mysqli("localhost", "username", "password", "db_name");
if (!$connection) {
echo "connection failed!";
exit();
}
?>
Note: above snippet is a simple example and you can customize as you want.
Step 3: Create php file called fetch_data.php and copy paste below code snippet:
<?php
include("conn.php");
$queryResult = $connection->
query("SELECT * FROM your_table");//change your_table with your database table that you want to fetch values
$result = array();
while ($fetchdata=$queryResult->fetch_assoc()) {
$result[] = $fetchdata;
}
echo json_encode($result);
?>
Above code snippet will fetch the data from db table and display it after json_encode.
Step 4: Open up your Flutter project or create one. Below is a code snippet that requesting for fetched data and display them using a ListView.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Login",
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List data = [];
#override
void initState() {
fetchData();
super.initState();
}
void fetchData() async {
final response = await http.get('http://10.0.2.2/fluttertest/fetch_data.php');
if (response.statusCode == 200) {
setState(() {
data = json.decode(response.body);
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text(data[index]['title']),
)),
);
}
}
There is an important thing, you should keep in mind: 10.0.2.2 or your machine IP address(type ipconfig in cmd to get your IP address) have to use because emulator itself localhost(127.0.0.1).
Note: I didn't use any model or advanced things to show you bare minimum example. If you want a great CRUD example, check my github repo and you can also do some pull requests because it's can extended.
If you want to insert or update data, you can use http.post() and in php use INSERT, UPDATE sql statements(It's better using Prepared Statement to prevent sql injections).
Also you can read my article. There I have explained everything using a CRUD application.
For Android we can use SQLite and for Flutter, we have equivalent SQFlite that support both IOS and Android.
And there are other best solutions like Firebase database, Firestore and you can also create API and access through HTTP. Also you can store data in a JSON file.
For you to continue on these may help:
Using mysql in flutter.
Flutter connecting to a database in server.

how to configure an authorized service object using Google OAuth 2.0

On the following link there is code which should access the Google Calendar api using OAuth 2.0. Unfortunately it uses the Draft 10 Client Library which is apparently deprecated.
https://developers.google.com/google-apps/calendar/instantiate
The latest Client Library is google-api-java-client-1.12.0-beta. From what I can make out things have changed a lot since the Draft 10 Client Library and I can't work out how to rewrite this code for the current Client Library.
The deprecated code is shown below.
import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessProtectedResource;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAuthorizationRequestUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.calendar.Calendar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
...
public void setUp() throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
// The clientId and clientSecret are copied from the API Access tab on
// the Google APIs Console
String clientId = "YOUR_CLIENT_ID";
String clientSecret = "YOUR_CLIENT_SECRET";
// Or your redirect URL for web based applications.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
String scope = "https://www.googleapis.com/auth/calendar";
// Step 1: Authorize -->
String authorizationUrl = new GoogleAuthorizationRequestUrl(clientId, redirectUrl, scope)
.build();
// Point or redirect your user to the authorizationUrl.
System.out.println("Go to the following link in your browser:");
System.out.println(authorizationUrl);
// Read the authorization code from the standard input stream.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("What is the authorization code?");
String code = in.readLine();
// End of Step 1 <--
// Step 2: Exchange -->
AccessTokenResponse response = new GoogleAuthorizationCodeGrant(httpTransport, jsonFactory,
clientId, clientSecret, code, redirectUrl).execute();
// End of Step 2 <--
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
response.accessToken, httpTransport, jsonFactory, clientId, clientSecret,
response.refreshToken);
Calendar service = new Calendar(httpTransport, accessProtectedResource, jsonFactory);
service.setApplicationName("YOUR_APPLICATION_NAME");
...
}
...
Can anyone tell how to rewrite this code so it works with the current Client Library?
You can have a look at the documentation of the Google Drive API, which is up to date:
https://developers.google.com/drive/credentials
Then it shouldn't be hard to replace the Drive scope with the Calendar scope and to instantiate the correct Calendar class for the service instead of a Drive service object.
If that situation happens again, the best to be sure you can find the latest version of code samples is to have a look directly on the website of the Google APIs Client Library for Java. You can have a look at it's wiki about auth but also have a look at the sample apps which they make sure are compiling and working with he latest version of the library (it's just harder to keep all the docs up to date sometimes)

Resources