We noticed that using the ContentSharer on Android to share exactly one file did not give us the list of expected apps that can receive the file. For example, when sharing an audio file (wav, ogg or flac), we did not see any audio apps in the share target list, only the typical generic file sharing apps.
I tracked this down to ContentSharer::ContentSharerNativeImpl::filesPrepared() in juce_android_ContentSharer.cpp. We are using JUCE 6 and JUCE 7 in our projects. JUCE 8 has refactored content sharing, but the same issue still exists.
filesPrepared() uses “android.intent.action.SEND_MULTIPLE” and AndroidIntent.putParcelableArrayListExtra to send an array of Uris, even if only 1 file is being shared. On some devices (Samsung phones), the name of the file isn’t even displayed, just the text “1 item” instead of a file name.
I made an alternate version filePrepared() that takes a single Uri and then uses “android.intent.action.SEND” and AndroidIntent.putExtraParcelable. This now correctly shows a list of apps that accept audio files when we share one.
void filePrepared (jobject fileUri, const StringArray& mimeTypes)
{
auto* env = getEnv();
auto intent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructor));
env->CallObjectMethod (intent, AndroidIntent.setAction,
javaString ("android.intent.action.SEND").get());
env->CallObjectMethod (intent, AndroidIntent.setType,
javaString (getCommonMimeType (mimeTypes)).get());
constexpr int grantReadPermission = 1;
constexpr int grantPrefixUriPermission = 128;
env->CallObjectMethod (intent, AndroidIntent.setFlags, grantReadPermission);
env->CallObjectMethod (intent, AndroidIntent.setFlags, grantPrefixUriPermission);
env->CallObjectMethod (intent, AndroidIntent.putExtraParcelable,
javaString ("android.intent.extra.STREAM").get(),
fileUri);
auto chooserIntent = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidIntent,
AndroidIntent.createChooser,
intent.get(),
javaString ("Choose share target").get()));
startAndroidActivityForResult (chooserIntent, 1003,
[weakRef = WeakReference<ContentSharerNativeImpl> { this }] (int /*requestCode*/,
int resultCode,
LocalRef<jobject> /*intentData*/) mutable
{
if (weakRef != nullptr)
weakRef->sharingFinished (resultCode);
});
}
