I'm having problems with Android Google Places API - auto complete feature.
I'm trying to use Places.GeoDataApi.getAutocompletePredictions() method to get the placeId, however, it doesn't work.(The output doesn't even show "can't get the value")
Could anyone help me?
Here is my Java code:
PendingResult<AutocompletePredictionBuffer> result =
Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, query,
mLatLonBounds, null);
result.setResultCallback(new ResultCallback<AutocompletePredictionBuffer>() {
#Override
public void onResult(#NonNull AutocompletePredictionBuffer autocompletePredictions) {
if (autocompletePredictions.getStatus().isSuccess()) { //如果回傳SUCCESS
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
resultList.add(prediction.getPlaceId().toString());
}
}
else {
resultList.add("can't get the vaule");
}
autocompletePredictions.release();
}
});
textView.setText(resultList.get(0).toString());
Thanks.
I had the same issue and I got it worked by following the below steps
Enable the Google Places API for Android in developers console and
check on the credentials page that your key is still present.
Add the required library to your module (play-services-places:11.2.0+).
Use the below code to get the predictions
Task<AutocompletePredictionBufferResponse> results = mGeoDataClient.getAutocompletePredictions(yourInputString, yourLatLngBounds, yourTypeFilter);
Add on success listener for the predictions as below
results.addOnSuccessListener(new OnSuccessListener<AutocompletePredictionBufferResponse>() {
#Override
public void onSuccess(AutocompletePredictionBufferResponse autocompletePredictions) {
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
suggesstions = new ArrayList<String>(autocompletePredictions.getCount());
if (iterator.hasNext()) {
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
//do your stuff with prediction here
}
}else {
//Nothing matches...
}
autocompletePredictions.release();
}
});
Add on failure listener for the predictions as below
results.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MapsActivity.this,"Error while fetching suggessions : "+e.getLocalizedMessage(),Toast.LENGTH_SHORT).show();
}
});
If all the above code snippet is placed properly, then you probably check your internet connectivity.
Hope the above code will be helpful.
Thanks.
Related
I have an Android project where I want to use com.android.billingclient.api version 4.0.0, which would replace an old billing library that google doesn't allow any more (com.anjlab.android.iab.v3). I've implemented the methods for a one-time purchase, but when querying the SKU Details with billingClient.querySkuDetailsAsync using the SKU string for the product, I get an empty result set. I've been assured that the SKU is correct, so I don't know where the error might be.
Also, the old implementation required to provide a license key, which isn't the case with the new library. Do I need to define it somewhere else in the app?
Here's the code where it fails:
List<String> skuList = new ArrayList<>();
skuList.add(SKU_ID);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(SkuType.INAPP);
final Activity v = this;
billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
Has anyone a suggestion what to do?
This is how I query the SKU details within my app.
You can try to use this example and see if this works for you.
billingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#NonNull BillingResult billingResult) {
Log.d(TAG, "Connection finished");
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
List<String> skuList = new ArrayList<> ();
skuList.add(ITEM_SKU_ADREMOVAL);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
(billingResult1, skuDetailsList) -> {
// Process the result.
if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
for (Object skuDetailsObject : skuDetailsList) {
skuDetails = (SkuDetails) skuDetailsObject;
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
if (ITEM_SKU_ADREMOVAL.equals(sku)) {
removeadsPrice = price;
}
else {
Log.d(TAG,"Sku is null");
}
}
Log.d(TAG, "i got response");
Log.d(TAG, String.valueOf(billingResult1.getResponseCode()));
Log.d(TAG, billingResult1.getDebugMessage());
}
else if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.ERROR) {
Toast.makeText(MainActivity.this, "Error in completing the purchase!", Toast.LENGTH_SHORT).show();
}
});
}
else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_TIMEOUT) {
Toast.makeText(MainActivity.this, "Service timeout!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(MainActivity.this, "Failed to connect to the billing client!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBillingServiceDisconnected() {
restartConnection();
}
});
Getting this one working properly depends on several different factors
Have you published your app to Play Console or at least to an
internal track or something?
Do you have active products or subscriptions on your Google Play
Console?
Have you configured your licensed testers?
Please see the documentation for more info.
Am trying to implement Braintree Vault PayPal payment, the problem am facing here is getting the paymentMethodNonce my event listener createdListener to capture nonce doesn't get called using vault, but everything works fine using checkout. I can't charge customer without a paymentMethodNonce, please can anyone assist me.
mBraintreeFragment = BraintreeFragment.newInstance(this,"TOKEN_FROM_SERVER");
PayPalRequest request = new PayPalRequest().localeCode("US").billingAgreementDescription("Your agreement description");
PayPal.requestBillingAgreement(mBraintreeFragment, request);
mBraintreeFragment.addListener(createdListener);
mBraintreeFragment.addListener(cancelListener);
mBraintreeFragment.addListener(errorListener);
DataCollector.collectDeviceData(mBraintreeFragment, new BraintreeResponseListener<String>() {
#Override
public void onResponse(String deviceData) {
Log.e("PayPal", deviceData);
try {
JSONObject json = new JSONObject(deviceData);
deviceDataInfo = json.getString("correlation_id");
Log.e("PayPal", deviceDataInfo);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
My Listeners
PaymentMethodNonceCreatedListener createdListener = new PaymentMethodNonceCreatedListener() {
#Override
public void onPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce) {
String nonce = paymentMethodNonce.getNonce();
Log.d("PayPal", "nonce id " + nonce);
}
};
BraintreeCancelListener cancelListener = new BraintreeCancelListener() {
#Override
public void onCancel(int requestCode) {
Log.d("CreditCard", "Braintree Error Code " + requestCode);
}
};
BraintreeErrorListener errorListener = new BraintreeErrorListener() {
#Override
public void onError(Exception error) {
if (error instanceof ErrorWithResponse) {
ErrorWithResponse errorWithResponse = (ErrorWithResponse) error;
BraintreeError cardErrors = errorWithResponse.errorFor("creditCard");
if (cardErrors != null) {
List<BraintreeError> errors = cardErrors.getFieldErrors();
String err = Objects.requireNonNull(errors.get(0).getMessage());
Log.d("CreditCard", errors.toString());
}
}
}
};
Instead of adding manually your listeners to that request, it's better to just implement the interface from braintree.
For example, if you want to use the onPaymentMethodNonceCreated() just add "implements PaymentMethodNonceCreatedListener" after your class name.
public class "YourClass" implements PaymentMethodNonceCreatedListener {
//...
}
And then override the method that now the Android Studio is warning you:
#Override
public void onPaymentMethodNonceCreated(PaymentMethodNonce paymentMethodNonce) {
String nonce = paymentMethodNonce.getNonce();
//...
}
This way you can go for everyone of your listeners! Good luck!
Due to the recent changes in the Google Play Games Service API I'm forced to replace all the deprecated code in my Android app. I'm following the Google guide in https://developers.google.com/games/services/android/savedgames and it's not clear for me how to pass the snapshot to this function that writes the data to be saved.
private Task writeSnapshot(Snapshot snapshot, byte[] data, Bitmap coverImage, String desc) {
// Set the data payload for the snapshot
snapshot.getSnapshotContents().writeBytes(data);
// Create the change operation
SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
.setCoverImage(coverImage)
.setDescription(desc)
.build();
SnapshotsClient snapshotsClient =
Games.getSnapshotsClient(this, GoogleSignIn.getLastSignedInAccount(this));
// Commit the operation
return snapshotsClient.commitAndClose(snapshot, metadataChange);
}
Can you help me? I think an example of use of this function should be added to the documentation to make everything clearer and to help developers who need to learn this from scratch.
Ok, I realized how to do it. Basically, when you open the snapshot client, you must use continueWith and obtain the snapshot from the task.
Considering you have a proper cover image and description and a Google account where you signed in
mAccount = GoogleSignIn.getLastSignedInAccount(activity);
this is the code:
SnapshotsClient snapshotsClient = Games.getSnapshotsClient(activity, mAccount);
int conflictResolutionPolicy = SnapshotsClient.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED;
snapshotsClient.open(getSaveFileName(), true, conflictResolutionPolicy)
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Error", e);
}
}).continueWith(new Continuation<SnapshotsClient.DataOrConflict<Snapshot>, byte[]>() {
#Override
public byte[] then(#NonNull Task<SnapshotsClient.DataOrConflict<Snapshot>> task)
throws Exception {
Snapshot snapshot = task.getResult().getData();
snapshot.getSnapshotContents().writeBytes(getSaveGameData());
SnapshotMetadataChange metadataChange = new SnapshotMetadataChange.Builder()
.setCoverImage(coverImage)
.setDescription(desc)
.build();
SnapshotsClient snapshotsClient = Games.getSnapshotsClient(activity, mAccount);
snapshotsClient.commitAndClose(snapshot, metadataChange);
return null;
}
});
I am trying to authenticate client token created by Firebase authentication library in Android in GCE endpoint.
The guide of how to do this can be found here
Basically I need to call this code snippet from the end point (i.e. server backend code not android code).
FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
// ...
}
});
Let say I want to execute that code and return the user to android client code. How should I do that?
This is my sample code that does not make sense. But it demonstrate what I want to do!
#ApiMethod(name = "serverAuth")
public MyUser serverAuth(#Named("token") String token) {
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
String email = decodedToken.getEmail();
String name = decodedToken.getName();
Map<String, Object> claims = decodedToken.getClaims();
String claimString = "";
for (Object claim : claims.values()) {
claimString += claims.toString();
}
MyUser user = new MyUser(uid, email, name, claimString);
//How to return this user?
}
});
//This is compile error since user varriable does not exist here
return user;
}
I have google search how to execute async code in GCE endpoints. But getting nowhere with that. What I get is something about code execution that is blocking until done and then return the user. But how to code so that async code as above become blocking?
CountDownLatch is the magic class you need. It will let you wait till the OnSuccessListener is actually completed.
Adapt your method this way: (I removed the steps that lead to MyUser's creation in order to focus on important points.)
#ApiMethod(name = "serverAuth")
public MyUser serverAuth(#Named("token") String token) {
final List<MyUser> users = new ArrayList<>();
final CountDownLatch cdl = new CountDownLatch(1);
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
// ... init uid, email, name and claimString
users.add(new MyUser(uid, email, name, claimString));
cdl.countDown();
}
});
try {
cdl.await(); // This line blocks execution till count down latch is 0
} catch (InterruptedException ie) {
}
if (users.size() > 0) {
return users.get(0);
} else {
return null ;
}
}
This is the basic version of what you need. IMHO, it requires 2 more improvements :
You should also take the possibility of failure into account :
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
cdl.countDown();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// log error, ...
cdl.countDown();
}
});
You should also take the possibility that none of the listeners are called. In this situation your method will never return. To avoid that, you can set a timeout on the await() method :
try {
// This line blocks execution till count down latch is 0
// or after 30 seconds.
cdl.await(30l, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
}
That's it. Hope this may help.
I have a single incident where a complete duplicate of a entry was made into the database (the same user comment appeared twice). They had different object IDs but were otherwise the exact same. It was slower than usual to finish the posting and only happened once out of dozens of comments, so I want to say it was a Parse issue during the saveInBackground call. Even so, I expect a service like Parse to be a little more robust. As my first time working with Android though, I also can't be sure nothing is wrong on my end. Any help? Also just any criticisms? This is the method called when the user hits a comment submission button:
private void submitComment() {
String text = commentText.getText().toString().trim();
Intent intent = getIntent();
String ID = intent.getStringExtra("imageID");
String parentID = intent.getStringExtra("parent");
// Set up a progress dialog
final ProgressDialog loadingDialog = new ProgressDialog(CommentSubmitActivity.this);
loadingDialog.setMessage(getString(R.string.publishing_comment));
loadingDialog.show();
Comment comment = new Comment();
comment.setText(text);
comment.setUser((ParseUser.getCurrentUser()));
if (ID.equals("#child")) {
comment.setParent(parentID);
comment.setImage("#child");
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment");
query.getInBackground(parentID, new GetCallback<ParseObject>() {
public void done(ParseObject parentComment, ParseException e) {
if (e == null) {
int numChild = parentComment.getInt("numChild");
parentComment.put("numChild", ++numChild);
parentComment.saveInBackground();
} else {
Log.d("numChild: ", "error");
}
}
});
} else {
comment.setImage(ID);
comment.put("numChild", 0);
ParseQuery<ParseObject> query = ParseQuery.getQuery("ImageUpload");
query.getInBackground(ID, new GetCallback<ParseObject>() {
public void done(ParseObject image, ParseException e) {
if (e == null) {
int numComments = image.getInt("numComments");
image.put("numComments", ++numComments);
image.saveInBackground();
} else {
Log.d("numComments: ", "error");
}
}
});
}
comment.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
loadingDialog.dismiss();
finish();
}
}
});
}
I encountered similar problem like yours.
I created an app where user can create account and add photo to it and list of objects (friends in my case).
Once when I was testing it user was created twice.
I went through my code and my my suspicions are connected with async calls.
I see that you use asynchronous parse api in you application so no fragment of code is waiting for response and blocking the rest of operations.
You cannot control when parse server will response.
What I did I just put all synchronous requests in my custom async code (AsyncTask in Android).
Hope that my answer somehow meeets your expectations.