Recently we tried to update the AppAuth-Android version used on our project from version 0.5.1.5 to 0.11.1.
When successfully login from the browser and come back to the app, there is error data and we can't continue the process.
This is how we request:
AuthorizationServiceConfiguration configuration = new AuthorizationServiceConfiguration(Uri.parse(getAuthorizationRequestUrlWithParams(getBaseUrl(), getAuthorizationUrlParameters())), Uri.parse(getAccessTokenUrl()), null);
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
configuration,
mClientId,
"code token id_token",
Uri.parse(getCallbackURI()))
.setScope(getHybridScope());
Intent completionIntent = new Intent(context, tokenActivity);
Intent cancelIntent = getCancelIntent(context, cancelActivity);
CustomTabColorSchemeParams colorSchemeParams = new CustomTabColorSchemeParams.Builder()
.setToolbarColor(ContextCompat.getColor(context,R.color.grey120))
.setSecondaryToolbarColor(ContextCompat.getColor(context,R.color.black))
.build();
int flags = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags |= PendingIntent.FLAG_MUTABLE;
}
mAuthService.performAuthorizationRequest(
authRequestBuilder.build(),
PendingIntent.getActivity(context, 0, completionIntent, flags),
PendingIntent.getActivity(context, 0, cancelIntent, flags),
mAuthService.createCustomTabsIntentBuilder()
.setDefaultColorSchemeParams(colorSchemeParams)
.build());
On authorization completed, the responseData has error data with description Response state param did not match request state.
After some debugging, we found out that on AuthorizationResponse.java there is a builder function that failed to get the query parameters from Uri which result in null value although the Uri string already contains all the data.
We also tried to setResponseMode to "form_post" on authRequestBuilder when requesting but it looks like it's still not supported.
Does anyone happen to solved this before?
Thanks in advance.
Related
i'm actually trying to use Dialogflow v2 with java sdk in android.
I can already make queries to dialogflow but I wanted to send some payload with my query.
Because of this, I discovered the QueryParameters object and I already set it with my desired payload.
The problem is, I have both QueryInput and QueryParameters defined but there is no documentation (or code references in the source code) about how to apply the parameters to the input before trying to detect the intent.
SessionsClient.create().use { sessionsClient ->
// Set the session name using the sessionId (UUID) and projectID
val session = SessionName.of(PROJECT_ID, UUID)
System.out.println("Session Path: $session")
// Set the text (input) and language code (en) for the query
val textInput = TextInput.newBuilder().setText(text).setLanguageCode(LANGUAGE_CODE)
// Build the query with the TextInput
val queryInput = QueryInput.newBuilder().setText(textInput).build()
// Set payload
val payload = "{someid: $someid}"
val queryParameters = QueryParameters.newBuilder().setPayload(Struct.parseFrom(payload.toByteArray())).build()
// (HERE I NEED TO ADD THE PARAMETERS TO INPUT)
// Performs the detect intent request
val response = sessionsClient.detectIntent(session, queryInput)
// returns the query result
return response.queryResult
}
After hours of deep searching, I managed to find the DetectIntentRequest class.
//Build the request
val request = DetectIntentRequest.newBuilder()
.setSession(session.toString())
.setQueryInput(queryInput)
.setQueryParams(queryParameters)
.build()
// Performs the detect intent request
val response = sessionsClient.detectIntent(request)
Note: if you are using other languages probably you 'll have a third
parameter in detectIntent function to place your queryParameters
For Kotlin ,
val queryInput1211 = QueryInput.newBuilder()
.setText(TextInput.newBuilder().setText(msg).setLanguageCode("en-US"))
.setEvent(com.google.cloud.dialogflow.v2beta1.EventInput.newBuilder()
.setName("Welcome")
.setLanguageCode("en-US")
.setParameters(
Struct.newBuilder().putFields("user_id",
Value.newBuilder().setStringValue("1234").build())
.build())
.build())
.build()
For java
QueryInput queryInput1211 = QueryInput.newBuilder()
.setText(TextInput.newBuilder().setText(msg).setLanguageCode("en-US"))
.setEvent(com.google.cloud.dialogflow.v2beta1.EventInput.newBuilder()
.setName("Welcome")
.setLanguageCode("en-US")
.setParameters(
Struct.newBuilder().putFields("user_id",
Value.newBuilder().setStringValue("1234").build())
.build())
.build())
.build();
Where Welcome is intent event name and user_id as parameter name
I would like my notifications to include the contact's image.
I am using NotificationCompat and MessagingStyle do display chat messages for contacts.
This works when using the .setIcon on the person, but the image is square, so I would like to use the setUri but it doesn't display the image, instead I see the contact's first initial in a circle.
Here is the code I'm using for the notification.
Person person = new Person.Builder()
// .setIcon(contactIcon)
.setName(displayName)
.setUri(contentLookupURI)
.setKey(contactDetail)
.build();
NotificationCompat.MessagingStyle chatMessageStyle = new NotificationCompat.MessagingStyle(person);
NotificationCompat.MessagingStyle.Message notificationMessage = new
NotificationCompat.MessagingStyle.Message(
contentText,
System.currentTimeMillis(),
person
);
chatMessageStyle.addMessage(notificationMessage);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, NOTIFICATION_MESSAGES_CHANNEL_ID)
.setSmallIcon(icon) // notification icon
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setStyle(chatMessageStyle)
.setOnlyAlertOnce(true)
.setContentTitle(displayName);
And for the contact URI used in the .setUri I'm using a library to obtain the contact id and lookupkey then use the method:
contactLookupURI =
ContactsContract.Contacts.getLookupUri(contactsList.get(0).getId(),
contactsList.get(0).getLookupKey());
Which produces this: content://com.android.contacts/contacts/lookup/3118r4-2F294339313F5B16.3789r5-2F294339313F5B16/6 which looks correct to me.
I'm not sure how new this form of the MessagingStyle method is as I can't find many examples of it's usage with a Person object.
Here is a solution for those using Remote URL with Glide
Step 1: Get Bitmap from Remote URL
private fun getAvatarFromUrl(photoUrl: String): Bitmap? {
return try {
val futureTarget = Glide.with(this)
.asBitmap()
.load(photoUrl)
.submit()
futureTarget.get()
} catch (e: Exception) {
Timber.e(e)
null
}
}
Step 2: Set Bitmap as Person.Icon
val avatar = getAvatarFromUrl(user.avatar)
val sender = Person.Builder()
.setName(msg.from?.name)
.setIcon(IconCompat.createWithBitmap(avatar))
.setImportant(true)
.build()
If you want to use resource id instead of bitmap:
val person = Person.Builder()
.setName("Name")
.setKey("Key")
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_resource)).build()
I am trying to play a custom sound on the Android platform when a local notification is being displayed, the code below is based on the Xamarin Local Notification Documentation, but some fields I'm being nagged are obsolete/deprecated.
In particular, SetSound 😢
I have however tried using SetSound in the hope that it could still work, even if deprecated. But I am not sure how to reference either the mp3 files in the Android / Xamarin 'Asset' folder or the copy that I have in Android / Xamarin 'Resources/raw' folder.
/Asset contents has build action AndroidAsset
/Resources/raw contents has build action AndroidResource
This line is what is causing me the headaches ...
.SetSound(Android.Net.Uri.Parse("android.resource://MyAssemblyName.Droid/Assets/filename"));
also tried
.SetSound(Android.Net.Uri.Parse("android.resource://MyAssemblyName.Resources/raw/filename"));
Q1) What do I need to do to correctly play a custom notification sound using either the Assets or Resources folder?
Q2) Because SetSound deprecated, what am I meant to do instead?
I have cheated, partially successfully, I have a Xamarin Plugin that plays sounds, which references the same files in the portable class library (PCL) and that mechanism works (when un-commented), but only if the app is in the foreground.
It seems that my scheduled local notifications do not trigger if I swipe to 'kill' the app, even though the app will not die because I have a persistent notification that prevents the app closing (until a certain time in the future that releases the persistent notification which could be minutes later).
Q3) Why don't the scheduled local notifications trigger once the user swipes the app, even though a persistent system notification keeps the app running? Here's how that persistent notification is set up. If it wasn't for this issue I could probably get by with the hack detailed above to play the sound from the PCL.
var activity = new Intent(Android.App.Application.Context, typeof(MainActivity));
var pIntent = PendingIntent.GetActivity(this, 0, activity, 0);
var notification = new Notification.Builder(this)
.SetContentTitle("Persistent Notification Test")
.SetContentText("This is always running to ensure that you are safe.")
.SetSmallIcon(Resource.Drawable.icon)
.SetOngoing(true)
.SetDefaults(0) // no sounds
.SetContentIntent(pIntent)
.Build();
// Enlist this instance of the service as a foreground service
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
For those interested, the commented out line
// PlatformDifferences.PlaySound(soundFilename, Logger);
calls through to this method that uses the SimpleAudioPlayer plugin
public virtual void PlaySound(string soundFilenameExcludingPath, Logger logger) {
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
Stream audioStream = assembly.GetManifestResourceStream("<my-pcl-assembly-name>.Sounds." + soundFilenameExcludingPath);
if (audioStream != null)
{
logger.Log(this, "playing sound:" + soundFilenameExcludingPath);
var player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
player.Load(audioStream);
player.Play();
}
else
{
logger.Log(this, "failed - playing sound:" + soundFilenameExcludingPath);
}
}
Here's a screenshot that shows my project structure
And here's the method that I invoke whenever I want to display a notification, whether because I wanted a scheduled local notification, or because I've received a push notification and wish to show the details to the user.
private async Task DisplayLocalNotification(String title, String message, String soundFilename)
{
Logger.Log(this, "DisplayLocalNotification title:" + title + " message:" + message);
// Ensure the main activity is lauched when the app is started.
Intent secondIntent = new Intent(Android.App.Application.Context, typeof(MainActivity));
Notification.BigTextStyle textStyle = new Notification.BigTextStyle();
textStyle.BigText(message);
int length = message.Length;
if (length > 80)
{
length = 80;
}
textStyle.SetSummaryText(message.Substring(0, length));
const int pendingIntentId = 0;
PendingIntent pendingEventForMainActivity =
PendingIntent.GetActivity(Android.App.Application.Context, pendingIntentId, secondIntent, PendingIntentFlags.OneShot);
Notification.Builder builder = new Notification.Builder(Android.App.Application.Context)
.SetContentTitle(title)
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingEventForMainActivity)
//.SetWhen () // - Now
.SetSmallIcon(Resource.Drawable.icon)
.SetVisibility(NotificationVisibility.Public)
.SetCategory(Notification.CategoryEvent)
.SetStyle(textStyle)
//.SetSound(Asset);?? What import?
//.SetSound(RingtoneManager.) ?? Looks like it's a fixed list of alert sounds
.SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate) // << DEPRECATD
.SetSound(Android.Net.Uri.Parse("android.resource://My-Assembly.Droid/Assets/" + soundFilename)); // << DEPECATD
// Hack - Works (if in foreground, but no if swipe-to-kill)...
// PlatformDifferences.PlaySound(soundFilename, Logger);
// Example: .SetSound(Uri.Parse("android.resource://" + this.PackageName + "/Raw/" + Resource.Raw.woop));
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
builder.SetSmallIcon(Resource.Drawable.icon);// Resource.Drawable.icon_transparent);
}
else
{
builder.SetSmallIcon(Resource.Drawable.icon);
}
// Create a task stack builder to manage the back stack:
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(Android.App.Application.Context);
// Add all parents of SecondActivity to the stack:
stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));
// Push the intent that starts SecondActivity onto the stack:
stackBuilder.AddNextIntent(secondIntent);
// Build the notification:
Notification androidNotification = builder.Build();
NotificationManager notificationManager =
Android.App.Application.Context.GetSystemService(Android.Content.Context.NotificationService) as NotificationManager;
// Publish the notification:
int notificationId = await StorageService.increment(Constants.STORAGE_KEY_NOTIFICATION_COUNTER);
notificationManager.Notify(notificationId, androidNotification);
Console.Out.WriteLine("DisplayLocalNotification title:" + title + " message:" + message + " published as id:" + notificationId + "?");
}
Please refer to the comments from #SushiHangover
Your screen shot is showing a API-27 device and if targetSdkVersion
was set, you would be required to use NotificationChannels (you would
need to if/else test the API levels as in my linked example). I have
seen a lot of different type of notification failures on different
(API-26+) devices, even notifications in the emulators behave
different when not using NotificationChannels.
I have implemented an Android Autofill Service for my password manager app. Users have reported issues with the Paypal app, where the service does not seem to work.
I have investigated this and found that the following code (Xamarin) in onFillRequest does work: ("does work" means the fields are filled after clicking the autofill popup)
var responseBuilder = new FillResponse.Builder();
var autofillIds = FindAutoFillIds(); //gets the autofill ids for each EditText
RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, "fill data from onFillRequest", AppNames.LauncherIcon);
var datasetBuilder = new Dataset.Builder(presentation);
foreach (AutofillId autofillId in autofillIds)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("some data"));
}
responseBuilder.AddDataset(datasetBuilder.Build());
callback.OnSuccess(responseBuilder.Build());
It basically creates a fill response with a single dataset which has values set for each autofill field.
Now I need to add an authentication activity:
var responseBuilder = new FillResponse.Builder();
var autofillIds = FindAutoFillIds(); //gets the autofill ids for each EditText
Intent intent = new Intent(this, typeof(MyAuthActivity));
var sender = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender;
RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, "fill data after auth", AppNames.LauncherIcon);
var datasetBuilder = new Dataset.Builder(presentation);
//Main difference here:
datasetBuilder.SetAuthentication(sender);
foreach (AutofillId autofillId in autofillIds)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("some placeholder data"));
}
responseBuilder.AddDataset(datasetBuilder.Build());
callback.OnSuccess(responseBuilder.Build());
where MyAuthActivity.OnCreate is like this:
RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, "dataset from auth activity", AppNames.LauncherIcon);
var datasetBuilder = new Dataset.Builder(presentation);
var autofillIds = GetAutofillIds(...); //returns the same autofillIds as in the onFillRequest
foreach (AutofillId autofillId in autofillIds)
{
datasetBuilder.SetValue(autofillId, AutofillValue.ForText("some other data"));
}
var ReplyIntent = new Intent();
bool returnDataset = true; //tried both true and false, neither works
if (returnDataset)
{
ReplyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, datasetBuilder.Build());
}
else
{
var responseBuilder = new FillResponse.Builder();
responseBuilder.AddDataset(datasetBuilder.Build());
ReplyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, responseBuilder.Build());
}
SetResult(Result.Ok, ReplyIntent);
Finish();
which basically creates another dataset using the same autofill ids, but neither returning them with a FillResponse nor a Dataset response works: The input fields on the target app remain empty.
I noticed that the same behavior appears in Bitwarden's implementation of their autofill service.
My questions are: Is there anything wrong with the code of the authentication activity? Or does this show an issue with Paypal's app? And is there anything I can do to debug this further?
This is a known WebView issue, which is fixed on Chrome M64.
You can verify it's fixed by installing a newer Chrome and changing the default WebView implementation through Settings -> Developer Options.
I'm tring to create a library for phonegap that give me control about remote control client. All phonegap side plus structure of new class is made but i don't know how change metadata.
I've made this function:
public void setMetadata() {
RemoteControlClient.MetadataEditor editor = remoteControlClient.editMetadata(true)
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, "CIAO");
}
but i'm sure that i've missed something like a register function.
Someone can give me an help?
Thanks!
For registering
// register a remote client ===========================================
final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(RemoteControlReceiver);
final PendingIntent mediaPendingIntent = PendingIntent.getBroadcast( getApplicationContext(), 0, mediaButtonIntent, 0);
// create and register the remote control client
myRemoteControlClient = new RemoteControlClient(mediaPendingIntent);
audioManager.registerRemoteControlClient(myRemoteControlClient);
And dont forget to apply the editor after you made your changes.
editor.apply();