0

In Delphi 11.3, I'm trying to send a user in my Android app to the device's default mapping app (Google Maps, Waze,...) using an intent. The purpose of the intent is to request directions from the current location to another based on the Lat/Lng coordinates. It worked fine in previous Android & Delphi versions, but this code is not working in Android 13. From what I've read about permissions, it appears as though there are more restrictions beyond Andriod 11.

Anyway, when I click the Navigate button in my app, I keep getting the 'Receiver not found' message.

My AndroidManifest.xml shows these locations permissions:

android:targetSdkVersion="32" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />

Here's my code for the Navigate button click event:

procedure TMainForm.NavigateBtnClick(Sender: TObject);
var
  {$IFDEF ANDROID}
    Intent: JIntent;  //Declares the intent object
  {$ENDIF}
  LGoogleMapsURL: String;
begin
   // Populate a string to send to Mapping app
   LGoogleMapsURL:= 'google.navigation:q=37.422219,-122.08364&mode=d';
  
  {$IFDEF MSWINDOWS}
    WebBrowser1.Navigate(LGoogleMapsURL);
  {$ENDIF}

  {$IFDEF ANDROID}
      Intent := TJIntent.Create;
      Intent.setData(StrToJURI(LGoogleMapsURL));
      Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
      Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(LGoogleMapsURL));
      if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then
        begin          
          MainActivity.startActivity(Intent);
        end
      else
        ShowMessage('Receiver not found');
  {$ENDIF}
end;

Is this no longer valid for use in Android 13 or is something missing?

Hackbrew
  • 349
  • 1
  • 10
  • 23
  • In my case, it opens Google Maps, regardless of whether `queryIntentActivities` returns an empty list, though I needed to add this line: `Intent.setPackage(StringToJString('com.google.android.apps.maps'));` Incidentally, I didn't need to use `putExtra`, either – Dave Nottage Jun 22 '23 at 23:04

1 Answers1

1

In order to make your example work, I needed to:

Modify AndroidManifest.template.xml, to change the <queries> tag to:

    <queries>
<%queries-child-elements%>
        <package android:name="com.google.android.apps.maps" />
    </queries>

(see here)

..and alter the code:

  URI := TJnet_Uri.JavaClass.parse(StringToJString('google.navigation:q=37.422219,-122.08364&mode=d'));
  Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, URI);
  Intent.setPackage(StringToJString('com.google.android.apps.maps'));
  if Intent.resolveActivity(TAndroidHelper.Context.getPackageManager) <> nil then
    TAndroidHelper.Context.startActivity(Intent);

i.e. using queryIntentActivities isn't really necessary, unless you actually want to see which activities can handle the intent. URI is of type: Jnet_Uri

If you want to query other packages, presumably you will need to have corresponding entries for them in the <queries> tag

Dave Nottage
  • 3,411
  • 1
  • 20
  • 57
  • That works great for a specific mapping app, but is there a way to call the user's preferred mapping app or default mapping app on the device? If I add an additional entry for Waze in the `` tag will the device use the default? Also, I changed URI to LURI (referenced in 2nd line) to get it to work. – Hackbrew Jun 23 '23 at 12:16
  • 1
    That is why I said: "If you want to query other packages, presumably you will need to have corresponding entries for them in the tag" – Dave Nottage Jun 23 '23 at 14:14