Am trying to build a dynamic url, using Firebase dynamic links but i get a exception.
private void sendNativeInvites(){
String email = UserUtils.getCurrentUser(this).getEmail();
String link = "https://play.google.com/store/apps/details?id=com.mindedges.beephourly?invitedby=" + email;
FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse(link))
.setDomainUriPrefix("https://c6yge.app.goo.gl")
.setAndroidParameters(
new DynamicLink.AndroidParameters.Builder("com.example.android")
.setMinimumVersion(125)
.build())
.buildShortDynamicLink()
.addOnSuccessListener(new OnSuccessListener<ShortDynamicLink>() {
#Override
public void onSuccess(ShortDynamicLink shortDynamicLink) {
Log.e(TAG, "Successfully built build dynamic link");
Uri invitationUrl = shortDynamicLink.getShortLink();
doSendInvite(invitationUrl);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "failed to build dynamic link", e);
}
});
}
failed to build dynamic link
com.google.android.gms.common.api.ApiException: 400: Request contains an invalid argument.
at com.google.android.gms.common.api.internal.TaskUtil.setResultOrApiException(Unknown Source:12)
at com.google.firebase.dynamiclinks.internal.zzi.zza(Unknown Source:4)
at com.google.firebase.dynamiclinks.internal.zzn.dispatchTransaction(Unknown Source:10)
at com.google.android.gms.internal.firebase_dynamic_links.zzb.onTransact(Unknown Source:12)
at android.os.Binder.execTransact(Binder.java:697)
Am not getting what wrong param am passing. I own the domain "https://c6yge.app.goo.gl" as per firebase console.
I can see a minor error in your code. That have been caused by mistakenly copying some codes from the documentation without editing them.
Here is the lines that has caused your problems:
.setAndroidParameters(
new DynamicLink.AndroidParameters.Builder("com.example.android")
.setMinimumVersion(125)
.build())
Instead of "com.example.android" you were supposed to replace that with your own package name which I think it is "com.mindedges.beephourly". So in the documentation they wrote that just like an example but you were expected to change it to your own package name.
Also in the same code above instead of (125) you are supposed to change that to your own version code. In android there are version codes for Apps and when you update an app you will have to change version code (integer) and version name (String) so you may have a number of App versions but in there you were supposed to pass the minimum the lowest version code that can open that dynamic link. I am forced not to believe you have ever made 125 updates in your app in Playstore. So if you want all your apps old and new version to open you could replace (125) with (1). You can find the current version code in your build.gradle files. In your project.
Let me know if you still face some difficulties.
Can you double check if you got the correct domain? Based on your code, it looks like everything works fine. However, the issue seems to be with your domain.
Checking the link as https://c6yge.app.goo.gl/?link=https://google.com, you should be redirected to https://google.com but it didn't. Instead, it just shows Dynamic Link not Found. So I'm thinking it's not properly configured.
Here's a sample working link: https://ratbu.page.link/?link=https://google.com.
Related
I have the current workflow for my authentication
User signs in via google OAuth2
User is then given a server_auth_code which they send to my backend authentication
The auth code is validated on the back end and users is sent a JWT
I had this all working in raw Java with the Android SDK, but Flutter seemed a lot nicer. But now when using the google_sign_in plugin on android, I am unable to retrieve the serverAuthCore anymore, this plugin just wants to return null the entire time.
I Am using the client ID that's specified for Android, however, I tested the WebApplication that's auto-generated by google too but that's the same issue (Null serverAutHCode)
This is the code that I am currently using:
/// Provides the `GoogleSignIn` class
import 'package:google_sign_in/google_sign_in.dart';
class GoogleLoginPage extends StatefulWidget {
final String name = "Logging in with google.";
late GoogleSignIn _googleSignIn;
GoogleLoginPage() : super() {
_googleSignIn = GoogleSignIn(
scopes: ['https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'],
serverClientId: "XX-XXX.apps.googleusercontent.com"
);
}
Future<void> fetchAuthToken() async {
try {
var response = await _googleSignIn.signIn();
log(response?.serverAuthCode ?? "No server auth code");
_googleSignIn.signOut();
} catch (error) {
print("ERR");
print(error);
}
}
#override
State<GoogleLoginPage> createState() => GoogleLoginState();
}
The output of this code is: [log] No server auth code
The question:
Am I doing something wrong? As mentioned this works 100% on my java project using the google play services SDK so I know it's nothing to do with my google console configurations.
Okay so I figured out the issues:
It appears that by default the google login plugin for flutter comes on an older version (If I remember correctly it was 20.0.5)
I Simply changed the version to the latest version:
'com.google.android.gms:play-services-auth:20.2.0'
You can do this by editing the project's build.gradle (In IntelliJ you open build.gradle and click "Open for editing in the android studio" in the top right, from there you need to find the gradle file for google_sign_in, and change the import there, remember to click sync in the top right of android studio before you close out of it)
And I began to receive my serverAuthCode as normal, cheers!
So, I've spent the past 2 hours searching for a solution for this but I cannot get anywhere.
I've followed this link to setup the google sheet API in order to use it with Flutter.
I keep getting this error:
ServerRequestFailedException (Failed to obtain access credentials. Error: invalid_grant Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim. Status code: 400)
As far as I've seen, this is related to a time problem but I've made sure the device's time is correct + enabled auto setting in the settings.
I'm using an android emulator (Pixel 4 API 27)
These are 2 pictures to show my time settings:
My code: (I'm calling the initSheet() in main)
class SpreadSheet {
static late final gsheets;
static late final spreadsheet;
static Future<bool> initSheet() async {
// TODO: Handle errors (Wrong time....)
gsheets = GSheets(_credentials);
/// link looks like so https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit#gid=0
/// [YOUR_SPREADSHEET_ID] in the path is the id your need
spreadsheet = await gsheets
.spreadsheet("1t51H_CSHPFoKB7KW_AcGMi3gwyJnecfM_k5wvk4OQ04");
return (spreadsheet == null ? false : true);
}
}
Somehow, the code is running perfectly now.
I used flutter clean & had to re-download gradle-6.9 zip because it got corrupted somehow.
I still don't know if that's exactly what actually fixed it or no but it'll be worth the try if someone faces this problem again.
An application is published on Play Store and it is using 'application data folder' for the backup-restore purpose using Drive API. Everything works fine. However, this API is about to be turned down on 6th December, 2019 according to Google's announcement. Therefore, in order to support existing users, I have been migrating to latest API according to migration guidlines and an official sample app.
I can successfully authenticate using the code (from the official link) below.
GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
.build();
GoogleSignInClient client = GoogleSignIn.getClient(this, signInOptions);
// The result of the sign-in Intent is handled in onActivityResult.
startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN);
I am also using correct scope - DriveScopes.DRIVE_APPDATA as mentioned in the official documentation.
I am also seeing correct values of 'email' and 'granted scopes' inside onActivityResult()
if (requestCode == REQUEST_CODE_SIGN_IN && resultCode == RESULT_OK) {
GoogleSignIn.getSignedInAccountFromIntent(data).addOnSuccessListener(new OnSuccessListener<GoogleSignInAccount>() {
#Override
public void onSuccess(GoogleSignInAccount googleSignInAccount) {
Log.e("TAG", "Email - " + googleSignInAccount.getEmail()); // prints correct value
Log.e("TAG", "Granted scopes - " + googleSignInAccount.getGrantedScopes()); // prints correct value
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(getActivity(), Collections.singleton(DriveScopes.DRIVE_APPDATA));
credential.setSelectedAccount(googleSignInAccount.getAccount());
Drive googleDriveService = new Drive.Builder(
AndroidHttp.newCompatibleTransport(),
new GsonFactory(),
credential)
.setApplicationName("App Name") // Changed it for now
.build();
mDriveServiceHelper = new DriveServiceHelper(googleDriveService);
queryFiles();
}
});
}
However, whenever I try to access a backup file in queryFiles() using the code (from the official link) below,
FileList files = driveService.files().list()
.setSpaces("appDataFolder")
.setFields("nextPageToken, files(id, name)")
.setPageSize(10)
.execute();
for (File file : files.getFiles()) {
System.out.printf("Found file: %s (%s)\n",
file.getName(), file.getId());
}
It throws the following error
{
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
Kindly help me fix the error. I believe that as everything is working fine with the published version, everything should be correct in terms of configuring on Google API console.
I probably can't find ALL threads with this problem but I can try to help in a few or so.
PRIMARY ANSWER
IF you're using ProGuard same as I am. ProGuard can cause this error to happen during query. I fixed it using the following.
# Fix OAuth Drive API failure for release builds
-keep class * extends com.google.api.client.json.GenericJson { *; }
-keep class com.google.api.services.drive.** { *; }
-keepclassmembers class * { #com.google.api.client.util.Key <fields>; }
SECONDARY ANSWER
Note that you DO NOT need to use keys/tokens using the Drive rest API with Android like you may find from other solutions (it may not hurt either, but it can). It doesn't match up here to what people talk about elsewhere (here they don't know what they're talking about).
See my notes here for further info: Google Drive via OAuth release version receives dailyLimitExceededUnreg
IF you have the problem however in debug build then you did not do everything correctly. My notes should get you on the right track.
If you need further help, I might assist because of how nuts it is.
EXAMPLE OF GETTING A FILE FROM DRIVE WITH THE NEW API USE
Just see from the following link
public Task<Pair<String, String>> readFile(String fileId)
https://github.com/gsuitedevs/android-samples/blob/master/drive/deprecation/app/src/main/java/com/google/android/gms/drive/sample/driveapimigration/DriveServiceHelper.java
The id comes from the query result where the id is part of that query info attached to that which is returned from the Drive query. The id is the file id for the file you want to retrieve. Pass that in to readFile and it gives you the file contents back that you can save locally to java.io.File eg fileOutputStream.write(contents.getBytes()); the contents of which is pair.second. You would then have your hopefully (because sometimes we have more work to do) identical java.io.File.
You can see a basic query if you need one in the the link sample as well but its missing some important info because depending on what you do you may need to check if trashed, get file size, modify time, md5, set order, etc. You may need to see https://developers.google.com/drive/api/v2/reference/files/list and https://developers.google.com/drive/api/v3/reference/files etc to figure that out. If enough files, there will be a paged requirement as well.
I know using Drive from code is a bit nuts (well, it is to me anyway lol) so hang in there =)
For Documentation purposes as a troubleshooting step:
Go to
https://console.developers.google.com/project/<project-id>/apiui/api
Or for Google Scripts:
https://script.google.com/home/usersettings
Replace with the ID of your application and check that the Google Drive API is turned on.
If it isn't - make sure to get a new token after turning it on if this is the case.
I have some code that has worked for months in production which suddenly has stopped working yesterday in all my apps.
I use Google Fit to retrieve locations via the Fitness.SensorClient API.
Locations permissions are requested correctly to the user at installation time (both the generic Android FINE_LOCATION permission and the permission to read and store locations into Google Fit).
I create the Fitness Option in this way:
setFitnessOptions(
FitnessOptions.builder()
.addDataType(DataType.TYPE_LOCATION_SAMPLE, FitnessOptions.ACCESS_WRITE));
I then look for the DataSources in this way:
GoogleSignInAccount lastSignedAccount = GoogleSignIn.getAccountForExtension(context, getFitnessOptions());
if (lastSignedAccount != null) {
Fitness.getSensorsClient(context, lastSignedAccount)
.findDataSources(
new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_LOCATION_SAMPLE)
.setDataSourceTypes(DataSource.TYPE_RAW)
.build())
.addOnSuccessListener(
new OnSuccessListener<List<DataSource>>() {
#Override
public void onSuccess(List<DataSource> dataSources) {
for (DataSource dataSource : dataSources) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
...
The value of the parameter dataSources in OnSuccessListener is an empty list. If I try other data types .setDataTypes(DataType.TYPE_STEP_COUNT_DELTA), dataSources is not an empty list. However neither DataType.TYPE_LOCATION_SAMPLE nor DataType.TYPE_LOCATION_TRACK return any data source.
I have checked the release notes of google services and nothing relevant seems to have changed.
The code above seems to be equivalent to all the examples provided by Google, e.g. this one
Does anyone have an idea of why suddenly that code has stopped working? Thanks
UPDATE: I have verified that it does not work with Android 6, 7, 8, or 9.
I have found the solution. In another part of my code I was subscribing using GoogleSignIn.getLastSignedInAccount. Apparently this may cause a mismatch and the locations are not returned. Changing the subscription to GoogleSignIn.getAccountForExtension solved the issue
In an app we upload user activity data to Google Fit like this :
Fitness.getSessionsClient(context, GoogleSignIn.getLastSignedInAccount(context))
.insertSession(((SessionInsertRequest) object))
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// At this point, the session has been inserted and can be read.
if (BuildConfig.DEBUG) {
Log.i(TAG, "Session insert was successful!");
}
//more success handling
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (BuildConfig.DEBUG) {
Log.w(TAG, "There was a problem inserting the session: " + e.toString()+ "\n"+ e.getLocalizedMessage());
}
//more error handling
}
}
});
This was working fine until approx sep 4 2019.
Then Google seemed to have changed something resulting in the following warning when creating the SessionInsertRequest
App com.foo.bar does not have access to data types in request
and in onFailureListener(...) we get the following message:
There was a problem inserting the session: com.google.android.gms.common.api.ApiException: 5002: DataType's name does not match package name.
DataTypes were not changed. They are requested when the user is asked to give permission to upload :
private FitnessOptions getFitnessSignInOptions(OAuthType type) {
switch (type) {
case Activity:
return FitnessOptions.builder()
.addDataType(DataType.TYPE_LOCATION_SAMPLE, FitnessOptions.ACCESS_WRITE)
.addDataType(DataType.TYPE_CALORIES_EXPENDED, FitnessOptions.ACCESS_WRITE)
.build();
}
}
and created in a DataSource like :
DataSource locationDataSource = new DataSource.Builder()
.setAppPackageName(packageName)
.setDataType(DataType.TYPE_LOCATION_SAMPLE)
.setName(uniqueIdentifier + "-locations")
.setType(DataSource.TYPE_RAW)
.build();
similar as the Google sample shows.
It does not matter if we omit setting the name of the dataSource or using setName(packageName). Also using setStreamName(packageName) instead does not resolve the issue.
Anybody else having this or a similar issue ?
Thank you
Robert
I wonder if the issue is related to the use of GoogleSignIn.getLastSignedInAccount. Apparently in the new version of the library this is not liked. Using GoogleSignIn.getAccountForExtension should do the trick. It worked for my issue with locations
I believe that you may have provided an invalid google-services.json file or at least one that is not compatible with the one used when you acquired permission from the user to use Google Fit.
I had the same issue: when I uploaded the new version of my app on top of the one downloaded from Google Play, it gave this error. It did not happen if instead I installed the new version of the app from scratch.
Regenerating the google-services.json file on Firebase and giving it to the new version of the app solved the issue. Now I can upload the app on top of the existing one and I do not get this error any more.
Note however that before I did not have Firebase enabled so it is possible that Google does not allow any more using google-services.json that is not generated via Firebase