I am trying to complete an OAuth2 authentication in a Delphi fmx Android app. I am using Delphi 11.0. When I created the app's credentails in the Google console I selected Android as the app type. As a result there is no client secret and I use the reverse DNS of my client ID, with a path of '/oauth2redirect', as the redirection endpoint in my requests to Google's OAuth2 server. My question is how to capture the OAuth2 server's response. There are many SO posts related to this but none that I could find addresses this question.
I have created an intent-filter in my Android manifest:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="com.googleusercontent.apps.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
</intent-filter>
There are other intent filters of type VIEW to get the app to respond to certain file types:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="content"
android:mimeType="application/vnd.xxxxxxxxxx"
android:pathPattern=".*\\.xxx" />
<data
android:scheme="content"
android:mimeType="application/xxxxxxxxxx"
android:pathPattern=".*\\.xxx" />
<data
android:scheme="content"
android:mimeType="application/octet-stream"
android:pathPattern=".*\\.xxx" />
</intent-filter>
In the app I try to capture the intent:
function TViewMasterDetail.HandleIntentAction(const aIntent: JIntent): Boolean;
var
lURI: JNet_Uri;
// lMimeType: string;
lNameSize: TNameSizeRecord;
lSourceFilePath: String;
lDestFilePath: string;
lInput: JInputStream;
lOutput: TFileStream;
lData: Integer;
lBuffer: TBytes;
i: Integer;
begin
Result := False;
if aIntent <> nil then
begin
TUtils.Log('Action: ' + JStringToString(aIntent.getAction)); //always empty string
if TJIntent.JavaClass.ACTION_VIEW.equals(aIntent.getAction) then
begin
// lMimeType := JStringToString(aIntent.getType);
lURI := aIntent.getData;
if assigned(lURI) then
begin
TUtils.Log('Scheme: ' + JStringToString(lURI.getScheme));
if JStringToString(lURI.getScheme) = RedirectionEndpoint then
begin
TUtils.Log('Path: ' + JStringToString(lURI.getPath)); //never get here
end
else
begin
lSourceFilePath := JStringToString(lURI.getPath);
lNameSize := ExtractNameSize(lURI);
lDestFilePath := TPath.Combine(TPath.GetTempPath, lNameSize.name);
//https://jenkov.com/tutorials/java-io/inputstream.html
SetLength(lBuffer, lNameSize.size);
lInput := SharedActivity.getContentResolver.openInputStream(lURI);
i := 0;
lData := lInput.read;
while lData <> -1 do
begin
lBuffer[i] := lData;
i := i + 1;
lData := lInput.read;
end;
lOutput := TFileStream.Create(lDestFilePath, fmCreate);
lOutput.WriteBuffer(lBuffer, lNameSize.size);
Viewmodel.HandleExternalFile(lDestFilePath);
// TFile.Delete(lDestFilePath);
lOutput.Free;
end;
end;
end;
end;
end;
This code is called when I switch back to the app after completing Google's login screen. Breakpoints tell me that there is an intent in the call, but its action type is not VIEW. Trying to print the action type to the console always results in an empty string.
Is this the approach for capturing the authentication server's response in the case of an Android app using a custom URI scheme? What do I need to do?
Thanks
EDIT
This is how HandleIntentAction is called:
procedure TViewMasterDetail.FormCreate(Sender: TObject);
var
lAppEventService: IFMXApplicationEventService;
...
//C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Mobile Snippets\AndroidIntents
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService,
lAppEventService) then
lAppEventService.SetApplicationEventHandler(HandleAppEvent);
// Register the type of intent action that we want to be able to receive.
// Note: A corresponding <action> tag must also exist in the <intent-filter> section of AndroidManifest.template.xml.
MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_VIEW);
TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage);
...
end;
procedure TViewMasterDetail.HandleActivityMessage(const Sender: TObject; const
aMessage: TMessage);
begin
if aMessage is TMessageReceivedNotification then
HandleIntentAction(TMessageReceivedNotification(aMessage).Value);
end;
function TViewMasterDetail.HandleAppEvent(aAppEvent: TApplicationEvent;
aContext: TObject): Boolean;
var
lStartupIntent: JIntent;
begin
Result := False;
if aAppEvent = TApplicationEvent.BecameActive then
begin
lStartupIntent := MainActivity.getIntent;
if lStartupIntent <> nil then
HandleIntentAction(lStartupIntent);
end;
end;
EDIT 2
In the last comment to the answer to this SO question there is information that should be relevant to my question. But I can't figure out how to turn that comment into code. Unfortunately, people at Google often shy away from Delphi questions, otherwise I would try and get a fuller explanation from the poster. Perhaps the meaning of the comment is clear to someone???