My app has the option to share a generated GPX file (a hiking route) with other applications. I'm using the ACTION_SEND intent for this. It works well, and users can share the GPX files with other apps and with other people via email etc.
However, some apps do not seem to accept receiving this data via intents. Garmin Connect does not show up in the list of apps when I'm sharing a GPX file, using the content type "application/gpx+xml".
If I download the GPX file manually and then open it, then Garmin Connect is listed as an app that can open it.
Is there any way to add a "Download file" to the share chooser intent that pops up when sharing a file?
Here is the client code I'm using:
private final WeakReference<MainActivity> mainActivityWeakReference; public FileExportTask(MainActivity mainActivity) { this.mainActivityWeakReference = new WeakReference<>(mainActivity); } @Override public void run() { MainActivity mainActivity = mainActivityWeakReference.get(); if (mainActivity == null) { // TODO: handle that mainActivity doesn't exist return; } try { Uri uri = getUriForSelectedRoute(); mainActivity.runOnUiThread(() -> { Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, uri); shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); shareIntent.setType("application/gpx+xml"); Intent chooser = Intent.createChooser(shareIntent, mainActivity.getString(R.string.share_route)); List<ResolveInfo> resInfoList = mainActivity.getPackageManager().queryIntentActivities(chooser, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; mainActivity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } mainActivity.startActivity(chooser); }); } catch (Exception ioe) { mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, R.string.failed_route_share, Toast.LENGTH_SHORT).show()); } } private Uri getUriForSelectedRoute() throws Exception { Route selectedRoute = RouteResponseProvider.getInstance().getSelectedRoute(); return downloadRoute(selectedRoute.toGpxUrl()); } private Uri downloadRoute(String url) throws IOException { String filename = "route_"+System.currentTimeMillis()+".gpx"; OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new UserAgentInterceptor()) .build(); Request httpRequest = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(httpRequest).execute()) { File downloadedFile = new File(getFilesDirectory(), filename); BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile)); sink.writeAll(response.body().source()); sink.close(); return getContentUri(downloadedFile); } } private File getFilesDirectory() { MainActivity mainActivity = mainActivityWeakReference.get(); File dir = mainActivity.getFilesDir(); if (dir != null && !dir.exists()) { dir.mkdirs(); } return dir; } private Uri getContentUri(File file) { MainActivity mainActivity = mainActivityWeakReference.get(); return FileProvider.getUriForFile(mainActivity, "com.myapp.fileprovider", file); }
And this is in my AndroidManifest.xml:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.myapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>