I'm in the middle of developing an Android app using Firebase, and have Phone Number Authentication enabled as a method of user sign-in. This all works fine.
Inside my app, I have an Account Details page that allows the user to edit their information and update their record in the FirebaseDatabase (in a separate node that I have created and called users). I'm able to update this table with no problems, but I need to update the table that Firebase keeps when users register, so that phone numbers don't get out of sync.
In theory, it should be really easy to do. I've done some reading up and seen that a method exists in the FirebaseUser class called updatePhoneNumber(PhoneAuthCredential). The only problem is that I have no idea how the PhoneAuthCredential class works and, after a couple of hours of Googling, haven't been able to find a single example, or many other forms of support for the method.
An example for the FirebaseUser.updateEmail(String) method can be seen here, so I'd guess that it can't be all that different, and should work fine if I can get the PhoneAuthCredential object set up correctly.
Update:
I tried to create an instance using new PhoneAuthCredential(...), but the suggested parameters aren't much help...
Android Studio displays the constructor as public PhoneAuthCredential(String s, String s1, boolean b, String s2, boolean b2, String s3), so I am very much none-the-wiser.
If I can figure out how to use this constructor, I might well be off the ground, hopefully.
If anyone can advise on how to use PhoneAuthCredential, or how the FirebaseUser.updatePhoneNumber() method should be implemented, that would be a huge help!
Thanks in advance,
Mark
Phone auth is quite complicated, so I'd recommend reading this guide. This section is especially relevant to your case. Basically, you'll have to go through the entire phone auth flow again to get a credential and set the user's new phone number.
If you're thinking of the phone number as a part of the user's profile, that's incorrect as you can see from the profile request. The phone number is considered to be a sort of user identifier, like the email which also requires a credential if the user's sign-in action is 5 mins old. Hope this helps!
Related
I'm trying to write a discord bot using JDA, and while I can get the presence of the bot fairly easily, I cannot get the presence of a selected user. An example use case for this might be the user typing in a command like !game and then the bot sends a message telling the user what game they're playing. As far as I know, the bot cannot get the user's game activity without getting the user's presence, and I do not see a way to do so. If I missed it in the documentation, please link the method/class.
After a bunch of digging and documentation reading, I have come to a solution. There is no way to get a presence like I was thinking, but since my original intent was to get the game activity, this solution works. First, the bot must have guild presence permissions granted through the developer portal. Then we need to include the line jdaBuilder.enableIntents(GatewayIntent.GUILD_PRESENCES); before we call the build method in our main method. Finally, to get member activities, we need to include jdaBuilder.enableCache(CacheFlag.ACTIVITY);. This lets us use the member.getActivities() method. Generally speaking, getting data associated with specific users requires enabling guild presences.
I created a class called VideoExchangeCenter which represents the company website that users log in and out of in order to download videos. The class contains the attribute: users - an ArrayList of all registered Users (which may be either logged on or not logged on).
Additionally, I am required to create an onlineUsers() method that returns an ArrayList of all Users that are currently online. This method essentially creates and returns a new ArrayList each time it is called.
I'm struggling to figure out some way to determine if a specific user is online or not. I tried looking up similar problems, but most of the results I found were too complex for my programming level or were either unrelated to my problem. I would really appreciate some help or a push in the right direction.
import java.util.ArrayList;
public class VideoExchangeCenter {
ArrayList<User> users;
public VideoExchangeCenter() {
users = new ArrayList<User>();
}
public onlineUsers(){
}
}
Basically you have to define what "being online" means.
Obviously, users that are currently up/downloading content are online. Obviously, users that logged in, but later logged out are offline. Users that are currently logged in but didn't do anything for X hours, hmm, what about them?
So, the point is: there are multiple approaches to go about this. When users need to login to use your service, the server can keep track of that information. You can also store time stamps each time a user interacts with a system, and assume "when a user is inactive for 1 hour, he is considered offline".
So, in the real world, such a service has plenty of ways to determine who is "currently online", some being heuristics. What you do in your homework assignment depends on the broader context of it.
I'm using the Play Billing Library in order to trigger and manage purchases which in turn unlocked extra functionality within an app. This part is working.
However, what is the best way to 'restore' purchases. Say for example someone who has bought the app buys a new phone. Logs in to the Play Store, downloads my app and then finds that the payment screen to 'upgrade' is being displayed. iOS has a specific method for this but I'm not aware of one for Android.
My thoughts are to query the Play Store and confirm whether the account has previously SUCCESSFULLY purchased the item, if so then I will call the local upgrade function within the app.
It appears there are two similar methods. But which one should I used in this scenario? Where a user has either wiped their phone or bought a new one?
queryPurchases()? Or queryPurchaseHistoryAsync()?
You should use queryPurchases. That gives you all the current active (non-consumed, non-cancelled, non-expired) purchases for each SKU.
queryPurchaseHistoryAsync won't do what you need because it will only give you a list of the most recent purchases for each SKU. They may have expired, been cancelled or been consumed, and there's no way to tell. Therefore this response can't be used to tell what purchases to apply in your app.
So far as I can see, the only valid use for queryPurchaseHistoryAsync is to provide a user with a list of their purchase history. It's a bit of an oddball.
Note also: queryPurchases is synchronous so in most cases it needs to be run in some kind of background worker thread. I run mine in an AsyncTask.
Per documentation queryPurchases uses the Play Store app cache to get the results while queryPurchaseHistoryAsyncactually checks the Purchase AP for the most recent purchases. So, in your case you should check the Asyncmethod.
queryPurchases
Get purchases details for all the items bought within your app. This method uses a cache of Google Play Store app without initiating a network request.
queryPurchaseHistoryAsync
Returns the most recent purchase made by the user for each SKU, even if that purchase is expired, canceled, or consumed.
Also, make sure to check the documentation. It recommends to Cache purchase details on your servers.
https://developer.android.com/google/play/developer-api.html#practices
I know it's a bit late, but I just discovered this myself. Sharing my answer for others to benefit.
So I learned that queryPurchases() is cached locally on your device, but is updated when you call queryPurchaseHistoryAsync()
I discovered from this Stackoverflow answer here
So my solution, is when wanting to restore a purchase on a new device, or a fresh install of my app. Call queryPurchaseHistoryAsync() Then in the callback onPurchaseHistoryResponse() call queryPurchases() and look within the List<Purchase> from the PurchasesResult for the purchase status of any of the user's past purchases.
If there's an expected purchase your app can grant the entitlements of their past purchase.
The documentation has been updated for the latest versions of BillingClient. queryPurchases() is deprecated. Also note that queryPurchases() only ever returned purchases made by the current device, so that method will not inform your scenario of a new wiped phone. To get accurate information use the async calls.
queryPurchasesAsync() will return all active subscription and unconsumed one-time Purchase objects for the sku type provided. It gets the purchases from the local Play Services cache, so there are no guarantees the cache will contain purchases from another device in your "new phone" scenario, and no guarantees the cache will yet be current in your "wiped phone" scenario.
queryPurchaseHistoryAsync() will make a network request and return the most recent PurchaseHistory object for each sku matching the provided sku type, even if cancelled or consumed.
Also, to perform the upgrade call launchBillingFlow() with the appropriate BillingFlowParams and BillingFlowParams.SubscriptionUpdateParams for the sku you now know to be purchased.
I'm new to the Android+Braintree world. At the moment I'm using the Drop-In interface.
What I want to do is the following
"If the user is creating/adding a new card, ask him if he wants to save
credit card information".
I need this info because later I will set the storeInVaultOnSuccess option in the transaction's params accordingly.
Now, it seems that there is no way to insert an element in the drop-in GUI to understand if the user wants to save these data or not.
Fine, so I'm going to add an additional step just after the drop-in interface in which I'm only going to ask the user if he wants to save the credit card data or not.
But the problem is that I don't want to ask this question if he choose an already existent credit card, so I need to know if he created a new card or if he selected an existent one.
Is there a way to perform this task (or is there a better alternative)?
WHAT I'VE ALREADY TRIED:
I've tried to see all the information given in the onActivityResult method, more specifically the content of the Intent given as the 3rd parameter.
What I have is, of course, the EXTRA_PAYMENT_METHOD_NONCE, and then the EXTRA_PAYMENT_METHOD (type com.braintreepayments.api.models.Card), but looking at the code of Card.java I'm not able to understand how to retrieve (if possible) this kind of information.
Thanks in advance.
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
The Drop-In UI doesn't support that workflow because at the time of entry the Drop-In automatically vaults the credit card and just provides the nonce (which doesn't contain any information about the card to the client for PCI reasons). In other words, storeInVaultOnSuccess won't apply since it's already there.
As you say, the way to get around this - while still using the Drop-In - would be to keep a reference to the payment method used in the transaction and ask after the transaction goes through. You can get this by examining the response object:
String payment_method_token = "";
TransactionRequest request = new TransactionRequest()
.amount(new BigDecimal("100.00"));
.paymentMethodNonce(nonceFromTheClient);
Result<Transaction> result = gateway.transaction().sale(request);
Transaction transaction = result.getTarget();
if (transaction.getPaymentInstrumentType().equals(PaymentInstrumentType.CREDIT_CARD){
payment_method_token = transaction.getCreditCard.getToken();
}
// ... other payment method types that you support
However, as you say, this is more complicated. You would have to make some selection based on:
a) when the payment method was created (using createdAt), or
a) comparing the arrays of payment methods before and after the checkout experience
This sort of flow really pushes the limits of the Drop-In, and these sorts of constraints often move developers to switch to a custom integration. In that case you would collect their preference - whether they want it stored - as they enter their credit card information.
I did oauth2 authorisation on some site. This is classical way with WebView and page there, where user adds password and login, presses Allow button etc. Then it gets refresh_token and by another POST message gets auth_token, which I have to store (in AccountManager) and user later.
Can I do this with the help of AccountManager? How can I do this?
I wonder if user should enter a login and password twice - one for account manager (when I should create it), and other in WebView form?
I just need to use AccountManager in order to sync data lately.
Don't know if you still looking for a solution on this.
Short answer it's yes u can this example may give you the inspiration you need : https://github.com/learning-layers/android-openid-connect It goes a little futher supporting OIDC workflow.
The author is working on a lib maybe it's worth looking for this release.