I'm using flutter secure storage (^5.0.2) to save tokens but I'm getting the following error when storage.write() is called on an emulator (I'm using Pixel 5 API 30) whereas when I use it on my physical device (Honor 8x) it's working well :
PlatformException (PlatformException(Exception encountered, write, java.lang.NullPointerException: Attempt to invoke interface method 'byte[] com.it_nomads.fluttersecurestorage.ciphers.StorageCipher.encrypt(byte[])' on a null object reference
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.write(FlutterSecureStoragePlugin.java:202)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access$300(FlutterSecureStoragePlugin.java:37)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:289)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
, null))
Here is the output of the debug :
W/KeyStore( 2975): KeyStore exception
W/KeyStore( 2975): android.os.ServiceSpecificException: (code 7)
W/KeyStore( 2975): at android.os.Parcel.createExceptionOrNull(Parcel.java:2387)
W/KeyStore( 2975): at android.os.Parcel.createException(Parcel.java:2357)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2340)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2282)
W/KeyStore( 2975): at android.security.keystore.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:988)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:233)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:222)
W/KeyStore( 2975): at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificate(AndroidKeyStoreSpi.java:165)
W/KeyStore( 2975): at java.security.KeyStore.getCertificate(KeyStore.java:1120)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:90)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access$100(FlutterSecureStoragePlugin.java:37)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
W/KeyStore( 2975): at android.os.Handler.handleCallback(Handler.java:938)
W/KeyStore( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
W/KeyStore( 2975): at android.os.Looper.loop(Looper.java:223)
W/KeyStore( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
E/FlutterSecureStoragePl( 2975): StorageCipher initialization failed
E/FlutterSecureStoragePl( 2975): java.lang.Exception: No certificate found under alias: com.example.applielikya.FlutterSecureStoragePluginKey
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:92)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access$100(FlutterSecureStoragePlugin.java:37)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.handleCallback(Handler.java:938)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
E/FlutterSecureStoragePl( 2975): at android.os.Looper.loop(Looper.java:223)
E/FlutterSecureStoragePl( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
I don't know if it could be related, but I have min Sdk 19 in my code, due to some packages needing this version.
I need this to start both my physical device and an emulator on Vscode with two different accounts in my app (an admin and an user) to check the transmission of notifications from one to another, if another way to achieve that exists I'd also be up to know.
This is the code :
import 'package:applielikya/models/login_response.dart';
import 'package:applielikya/models/user.dart';
import 'package:applielikya/services/auth/login.dart';
import 'package:applielikya/views/homepage.dart';
import 'package:applielikya/widgets/createRoute.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
State<LoginPage> createState() => LoginPageState();
}
enum ButtonState { init, loading, done }
class LoginPageState extends State<LoginPage> {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final FlutterSecureStorage storage = const FlutterSecureStorage();
ButtonState _state = ButtonState.init;
bool _passwordVisible = false;
final TextEditingController _usernameController = TextEditingController(text: "kentay");
final TextEditingController _passwordController = TextEditingController(text: "kentay");
bool _isAuth = false;
String _responseMessage = "";
void saveToken(SuccessResponse response) async {
await storage.write(key: "accessToken", value: response.accessToken);
await storage.write(key: "refreshToken", value: response.refreshToken);
}
void saveUser(UserResponse user) async {
final SharedPreferences prefs = await _prefs;
prefs.setString('username', user.username as String);
prefs.setInt('id', user.id as int);
prefs.setString('role', user.role as String);
if (user.role == "prof") {
prefs.setString("firstname", user.firstname!);
prefs.setString("lastname", user.lastname!);
prefs.setString("email", user.email!);
}
}
submitLogin() async {
setState(() => _state = ButtonState.loading);
final response = await login(
UserRequest(username : _usernameController.text, password: _passwordController.text)
);
setState(() {
_isAuth = response.auth;
_state = ButtonState.done;
});
if (response is SuccessResponse) {
saveToken(response);
saveUser(response.user);
setState(() => _state = ButtonState.init);
Navigator.of(context).push(
createRoute(
const MyHomePage(),
const Offset(0.0, 1.0),
Offset.zero,
Curves.easeInCirc
)
);
} else {
if (response is ErrorResponse) {
setState(() => _responseMessage = response.message);
}
}
}
In case it helps someone, I fixed it by clearing datas and cache of the app on my emulator in the parameters of the device.
i think the isseus was form arecent update.
just add the option below for android.
final FlutterSecureStorage storage = const FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
),
);
Related
I have a problem with showing notification for open file in my app.
Here's the code for create a csv file
getCsv() async {
if (await Permission.storage.request().isGranted) {
//store file in documents folder
String dir =
"${(await getExternalStorageDirectory())!.path}/csv_bodega.csv";
String file = dir;
File f = File(file);
// convert rows to String and write as csv file
String csv = const ListToCsvConverter().convert(itemsList);
f.writeAsString(csv);
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Archivo descargado')),
);
const android = AndroidNotificationDetails('0', 'Adun Accounts',
channelDescription: 'channel description',
priority: Priority.high,
importance: Importance.max,
icon: '');
const platform = NotificationDetails(android: android);
await flutterLocalNotificationsPlugin
.show(0, "CSV Bodega", "Descarga completada", platform, payload: dir);
} else {
// ignore: unused_local_variable
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
}
}
Here's the code I paste in main.dart for initializate flutterLocalNotificationsPlugin
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> initNotification() async {
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('notification_icon');
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
);
}
I get this error:
PlatformException (PlatformException(error, Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.setSmallIcon(FlutterLocalNotificationsPlugin.java:425)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.createNotification(FlutterLocalNotificationsPlugin.java:326)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.showNotification(FlutterLocalNotificationsPlugin.java:1146)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.show(FlutterLocalNotificationsPlugin.java:1462)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1299)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
))
I don't know what to do. Apart from that, I searched that the plugin open_filex helps for open a file with a specified path. But I don't know where to use in my code. Help me, please.
I try initialize Firebase Messaging and get token, but I receive this error
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print('on Background Message : ${message.data}');
}
class MyHttpOverrides extends HttpOverrides {
#override
HttpClient createHttpClient(SecurityContext context) {
return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
}
}
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await GlobalConfiguration().loadFromAsset("configurations");
NotificationSettings settings = await FirebaseMessaging.instance.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
} else if (settings.authorizationStatus == AuthorizationStatus.provisional) {
print('User granted provisional permission');
} else {
print('User declined or has not accepted permission');
}
try{
await FirebaseMessaging.instance.getToken();
FirebaseMessaging.instance.getInitialMessage();
if(GetPlatform.isMobile){
FirebaseMessaging.instance.subscribeToTopic('suitableUser');
}else{
}
FirebaseMessaging.onMessage.listen((event) {
}).onError((error){
print('error');
});
FirebaseMessaging.onMessageOpenedApp.listen((event) {
print('success : ${event.data}');
}).onError((error){
print('error');
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}catch(e){
print('555555 FirebaseMessaging ::: $e');
}
HttpOverrides.global = new MyHttpOverrides();
runApp(MyApp());
}
I have tried many methods such as deleting the build file, downloading Json file from firebase again, and creating another API, but i get this error in run
E/FirebaseInstanceId(13464): Failed to get FIS auth token
E/FirebaseInstanceId(13464): Caused by: com.google.firebase.installations.FirebaseInstallationsException: Firebase Installations Service is unavailable. Please try again later.
E/FirebaseInstanceId(13464): at com.google.firebase.installations.remote.FirebaseInstallationServiceClient.createFirebaseInstallation(FirebaseInstallationServiceClient.java:153)
E/FirebaseInstanceId(13464): at com.google.firebase.installations.FirebaseInstallations.registerFidWithServer(FirebaseInstallations.java:530)
E/FirebaseInstanceId(13464): at com.google.firebase.installations.FirebaseInstallations.doNetworkCallIfNecessary(FirebaseInstallations.java:385)
E/FirebaseInstanceId(13464): at com.google.firebase.installations.FirebaseInstallations.lambda$doRegistrationOrRefresh$2$FirebaseInstallations(FirebaseInstallations.java:374)
E/FirebaseInstanceId(13464): at com.google.firebase.installations.-$$Lambda$FirebaseInstallations$VZq1h0TBcWNH8Y5yY86ujrFFyLo.run(Unknown Source:4)
E/FirebaseInstanceId(13464): at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
E/FirebaseInstanceId(13464): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
E/FirebaseInstanceId(13464): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/FirebaseInstanceId(13464): ... 1 more
E/FirebaseInstanceId(13464): Topic sync or token retrieval failed on hard failure exceptions: FIS_AUTH_ERROR. Won't retry the operation.
I/flutter (13464): 555555 FirebaseMessaging ::: [firebase_messaging/unknown] java.io.IOException: FIS_AUTH_ERROR
Note: I use this code in another application and it works efficiently without any error
I'm trying to use the FlutterLocalNotification in my app and I'm getting errors when executing it. Can anyone know how can solve this? I try some similar questions but nothing works. (like included " proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'" inside the build.gradle)
class Notification extends StatefulWidget {
#override
_Notification createState() => _Notification();
}
class _Notification extends State<Notification> {
FlutterLocalNotificationsPlugin flutterNotification =
new FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
var androidInitilize = new AndroidInitializationSettings("app_icon");
var IOSinitialize = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
android: androidInitilize, iOS: IOSinitialize);
flutterNotification = new FlutterLocalNotificationsPlugin();
flutterNotification.initialize(initializationSettings,
onSelectNotification: notificationSelected('play'));
}
Future _showNotification() async {
var androidDetails = new AndroidNotificationDetails(
"Channel ID", "Details",
importance: Importance.max);
var IOSDetails = new IOSNotificationDetails();
var generalNotificationDetails =
new NotificationDetails(android: androidDetails, iOS: IOSDetails);
await flutterNotification.show(
0,
"Title:",
"body",
generalNotificationDetails);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
notificationSelected(String payload) async {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Text("Notification : $payload"),
),
);
}
}
class that calls the showNotification method:
class TriggeredNotification extends StatelessWidget {
final Map<dynamic, dynamic> _imageData;
ImagePage(this._imageData);
downloadImage() async {
try {
// Saved with this method.
var imageId = await ImageDownloader.downloadImage(
_imageData["images"]["fixed_height"]["url"],
destination: AndroidDestinationType.directoryDownloads);
if (imageId == null) {
print("imageid : $imageId");
return;
} else {
_Notification()._showNotification();
}
// Below is a method of obtaining saved image information.
var fileName = await ImageDownloader.findName(imageId);
var path = await ImageDownloader.findPath(imageId);
var size = await ImageDownloader.findByteSize(imageId);
var mimeType = await ImageDownloader.findMimeType(imageId);
print(
"filename: $fileName | path: $path | size: $size | mimetype: $mimeType");
} on PlatformException catch (error) {
print(error);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_imageData['title']),
backgroundColor: Colors.black,
actions: [
IconButton(
onPressed: () {
downloadImage();
},
icon: Icon(Icons.download))
],
),
backgroundColor: Colors.black,
body: Center(
child: Image.network(_imageData["images"]["fixed_height"]["url"]),
),
);
}
}
Error:
PlatformException (PlatformException(error, Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.setSmallIcon(FlutterLocalNotificationsPlugin.java:300)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.createNotification(FlutterLocalNotificationsPlugin.java:215)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.showNotification(FlutterLocalNotificationsPlugin.java:1024)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.show(FlutterLocalNotificationsPlugin.java:1362)
at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:1241)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:296)
at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$DartMessenger(DartMessenger.java:320)
at io.flutter.embedding.engine.dart.-$$Lambda$DartMessenger$TsixYUB5E6FpKhMtCSQVHKE89gQ.run(Unknown Source:12)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
))
For statement : var androidInitilize = new AndroidInitializationSettings("app_icon");
it should be path to app_icon
see the following example, specifying launcher icon from mipmap folder of android app , you should write this
var androidInitilize = new AndroidInitializationSettings('#mipmap/ic_launcher')
or if its from drawable folder of android app then
var androidInitilize = new AndroidInitializationSettings('#drawable/app_icon')
let me know if its work you or not.
I'm trying to create a database and store an API token for user login but I keep getting an error when the app builds/compiles:
Non-nullable instance field '_database' must be initialized
I've tried adding a late modifier as suggested which then throws:
E/flutter ( 6894): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)]
Unhandled Exception: Unhandled error LateInitializationError: Field
'_database#637109567' has not been initialized. occurred in Instance
of 'AuthenticationBloc'.
my user_db.dart
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
final userTable = 'userTable';
class DatabaseProvider {
static final DatabaseProvider dbProvider = DatabaseProvider();
//non nullable error on _database
Database _database;
Future <Database> get database async {
print('before condition');
if (_database != null){
return _database;
}
_database = await createDatabase();
return _database;
}
createDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "User.db");
var database = await openDatabase(
path,
version: 1,
onCreate: initDB,
onUpgrade: onUpgrade,
);
return database;
}
void onUpgrade(
Database database,
int oldVersion,
int newVersion,
){
if (newVersion > oldVersion){}
}
void initDB(Database database, int version) async {
await database.execute(
"CREATE TABLE $userTable ("
"id INTEGER PRIMARY KEY, "
"username TEXT, "
"token TEXT "
")"
);
}
}
my AuthBloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:equatable/equatable.dart';
import 'package:times/repository/user_repository.dart';
import 'package:times/model/user_model.dart';
part 'authentication_event.dart';
part 'authentication_state.dart';
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({required this.userRepository})
: super(AuthenticationUnauthenticated())
;
final UserRepository userRepository;
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is AppStarted) {
final bool hasToken = await userRepository.hasToken();
if (hasToken) {
yield AuthenticationAuthenticated();
} else {
yield AuthenticationUnauthenticated();
}
}
if (event is LoggedIn) {
yield AuthenticationLoading();
await userRepository.persistToken(
user: event.user
);
yield AuthenticationAuthenticated();
}
if (event is LoggedOut) {
yield AuthenticationLoading();
await userRepository.deleteToken(id: 0);
yield AuthenticationUnauthenticated();
}
}
}
The problem is being caused by this line
if (_database != null) {
You can't directly apply null check on a non-nullable variable and since it is a late variable and you didn't initialize it, the null check will always keep throwing the error.
One way to fix this would be to make your _database Nullable and instantiate it to null, like this
Database? _database = null;
In order to avoid using the Nullable type everywhere in code, you could modify your function to use the bang operator (!) like this,
Future <Database> get database async {
if (_database != null){
return _database!;
}
_database = await createDatabase();
return _database!;
}
I am able to Google Sign in using web version of my flutter app but can't Google sign in from android app.
This is the error I'm getting:
GraphicExtModuleLoader::CreateGraphicExtInstance false
D/Surface (29460): Surface::connect(this=0x753ab3e000,api=1)
D/Surface (29460): Surface::setBufferCount(this=0x753ab3e000,bufferCount=3)
D/Surface (29460): Surface::allocateBuffers(this=0x753ab3e000)
V/PhoneWindow(29460): DecorView setVisiblity: visibility = 0, Parent = android.view.ViewRootImpl#9837577, this = DecorView#bcd75e4[MainActivity]
V/PhoneWindow(29460): DecorView setVisiblity: visibility = 4, Parent = android.view.ViewRootImpl#9de9d56, this = DecorView#63bb4f5[SignInHubActivity]
D/Surface (29460): Surface::disconnect(this=0x753ab3e000,api=1)
D/View (29460): [Warning] assignParent to null: this = DecorView#63bb4f5[SignInHubActivity]
E/flutter (29460): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)
Refereing to this Flutter and google_sign_in plugin: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null) answer on StackOverflow, I couldn't understand what this answer is trying to say...
However, I do have provided my SHA1 key on firebase. Re-downloaded and replaced the google-services.json in my flutter app, but still can't sign in on Android.
This is my GoogleSignIn code:
onPressed: () async {
await Firebase.initializeApp();
final FirebaseAuth _firebaseAuth =
FirebaseAuth.instance;
final GoogleSignIn _googleSignIn =
GoogleSignIn();
Future<User> _signIn(BuildContext context) async {
debugPrint("1");
final GoogleSignInAccount googleUser =
await _googleSignIn.signIn();
debugPrint("2");
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
debugPrint("a");
final AuthCredential credential =
GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken);
User userDetails = (await _firebaseAuth
.signInWithCredential(credential))
.user;
ProviderDetails providerInfo =
ProviderDetails(userDetails.uid);
List<ProviderDetails> providerData =
<ProviderDetails>[];
providerData.add(providerInfo);
UserDetails details = UserDetails(
userDetails.uid,
userDetails.displayName,
userDetails.email,
userDetails.photoURL,
providerData);
if (details.userName.toString() != '') {
debugPrint("Email ${details.userEmail}");
globals.isLoggedIn = true;
SharedPref prefs = SharedPref();
String photoUrl = details.photoUrl.toString();
prefs.save("photoUrl", photoUrl);
prefs.save("username",
details.userName.toString());
prefs.save(
"email", details.userEmail.toString());
if (mounted) {
setState(() {
inProgress = false;
});
}
} else {
globals.isLoggedIn = false;
debugPrint(
"Check your internet Connection");
}
}
if (mounted) {
setState(() {
inProgress = true;
});
}
await _signIn(context);
debugPrint("LoggedIn");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Dashboard()),
);
}
Actually I needed to add this line into my app level build.gradle file dependencies section.
implementation 'com.google.android.gms:play-services-auth:19.0.0'
As well needed to link my project from this link too.
https://developers.google.com/identity/sign-in/android/start-integrating#configure_a_project
Might it help someone in future!
Problem is When you registered your app on google console and created clientId, you choose web platform, now you have to create another clientId with Android Platform. You can use same sha1 key.