modify mime type detection for shared files

add support for audiobooks
This commit is contained in:
Daniel Gultsch 2023-10-06 12:34:07 +02:00
parent 95aea4291e
commit 541c8ba80d
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
9 changed files with 66 additions and 35 deletions

View file

@ -74,6 +74,8 @@ public class MediaAdapter extends RecyclerView.Adapter<MediaAdapter.MediaViewHol
Log.d(Config.LOGTAG, "mime=" + mime); Log.d(Config.LOGTAG, "mime=" + mime);
if (mime == null) { if (mime == null) {
attr = R.attr.media_preview_unknown; attr = R.attr.media_preview_unknown;
} else if (mime.equals("audio/x-m4b")) {
attr = R.attr.media_preview_audiobook;
} else if (mime.startsWith("audio/")) { } else if (mime.startsWith("audio/")) {
attr = R.attr.media_preview_audio; attr = R.attr.media_preview_audio;
} else if (mime.equals("text/calendar") || (mime.equals("text/x-vcalendar"))) { } else if (mime.equals("text/calendar") || (mime.equals("text/x-vcalendar"))) {

View file

@ -151,7 +151,7 @@ public class MediaPreviewAdapter extends RecyclerView.Adapter<MediaPreviewAdapte
this.mediaPreviews.clear(); this.mediaPreviews.clear();
} }
class MediaPreviewViewHolder extends RecyclerView.ViewHolder { static class MediaPreviewViewHolder extends RecyclerView.ViewHolder {
private final MediaPreviewBinding binding; private final MediaPreviewBinding binding;

View file

@ -28,6 +28,8 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -260,7 +262,8 @@ public final class MimeUtils {
add("audio/mpeg", "mpga"); add("audio/mpeg", "mpga");
add("audio/mpeg", "mpega"); add("audio/mpeg", "mpega");
add("audio/mpeg", "mp2"); add("audio/mpeg", "mp2");
add("audio/mpeg", "m4a"); add("audio/mp4", "m4a");
add("audio/x-m4b", "m4b");
add("audio/mpegurl", "m3u"); add("audio/mpegurl", "m3u");
add("audio/ogg", "oga"); add("audio/ogg", "oga");
add("audio/opus", "opus"); add("audio/opus", "opus");
@ -413,6 +416,9 @@ public final class MimeUtils {
applyOverrides(); applyOverrides();
} }
// mime types that are more reliant by path
private static final Collection<String> PATH_PRECEDENCE_MIME_TYPE = Arrays.asList("audio/x-m4b");
private static void add(String mimeType, String extension) { private static void add(String mimeType, String extension) {
// If we have an existing x -> y mapping, we do not want to // If we have an existing x -> y mapping, we do not want to
// override it with another mapping x -> y2. // override it with another mapping x -> y2.
@ -537,44 +543,49 @@ public final class MimeUtils {
} }
public static String guessMimeTypeFromUriAndMime(final Context context, final Uri uri, final String mime) { public static String guessMimeTypeFromUriAndMime(final Context context, final Uri uri, final String mime) {
Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime " + uri + " and mime=" + mime); Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime(" + uri + "," + mime+")");
if (mime == null || mime.equals("application/octet-stream")) { final String mimeFromUri = guessMimeTypeFromUri(context, uri);
final String guess = guessMimeTypeFromUri(context, uri); Log.d(Config.LOGTAG,"mimeFromUri:"+mimeFromUri);
if (guess != null) { if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeFromUri)) {
return guess; return mimeFromUri;
} else { } else if (mime == null || mime.equals("application/octet-stream")) {
return mime; return mimeFromUri;
} } else {
return mime;
} }
return guessMimeTypeFromUri(context, uri);
} }
public static String guessMimeTypeFromUri(Context context, Uri uri) { public static String guessMimeTypeFromUri(final Context context, final Uri uri) {
// try the content resolver final String mimeTypeContentResolver = guessFromContentResolver(context, uri);
String mimeType; final String mimeTypeFromQueryParameter = uri.getQueryParameter("mimeType");
final String name = "content".equals(uri.getScheme()) ? getDisplayName(context, uri) : null;
final String mimeTypeFromName = Strings.isNullOrEmpty(name) ? null : guessFromPath(name);
final String path = uri.getPath();
final String mimeTypeFromPath = Strings.isNullOrEmpty(path) ? null : guessFromPath(path);
if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeTypeFromName)) {
return mimeTypeFromName;
}
if (PATH_PRECEDENCE_MIME_TYPE.contains(mimeTypeFromPath)) {
return mimeTypeFromPath;
}
if (mimeTypeContentResolver != null && !"application/octet-stream".equals(mimeTypeContentResolver)) {
return mimeTypeContentResolver;
}
if (mimeTypeFromName != null) {
return mimeTypeFromName;
}
if (mimeTypeFromQueryParameter != null) {
return mimeTypeFromQueryParameter;
}
return mimeTypeFromPath;
}
private static String guessFromContentResolver(final Context context, final Uri uri) {
try { try {
mimeType = context.getContentResolver().getType(uri); return context.getContentResolver().getType(uri);
} catch (final Throwable throwable) { } catch (final Throwable e) {
mimeType = null; return null;
} }
// try the extension
if (mimeType == null || mimeType.equals("application/octet-stream")) {
final String path = uri.getPath();
if (path != null) {
mimeType = guessFromPath(path);
}
}
if (mimeType == null && "content".equals(uri.getScheme())) {
final String name = getDisplayName(context, uri);
if (name != null) {
mimeType = guessFromPath(name);
}
}
// sometimes this works (as with the commit content api)
if (mimeType == null) {
mimeType = uri.getQueryParameter("mimeType");
}
return mimeType;
} }
private static String getDisplayName(final Context context, final Uri uri) { private static String getDisplayName(final Context context, final Uri uri) {

View file

@ -481,6 +481,8 @@ public class UIHelper {
return context.getString(R.string.file); return context.getString(R.string.file);
} else if (MimeUtils.AMBIGUOUS_CONTAINER_FORMATS.contains(mime)) { } else if (MimeUtils.AMBIGUOUS_CONTAINER_FORMATS.contains(mime)) {
return context.getString(R.string.multimedia_file); return context.getString(R.string.multimedia_file);
} else if (mime.equals("audio/x-m4b")) {
return context.getString(R.string.audiobook);
} else if (mime.startsWith("audio/")) { } else if (mime.startsWith("audio/")) {
return context.getString(R.string.audio); return context.getString(R.string.audio);
} else if (mime.startsWith("video/")) { } else if (mime.startsWith("video/")) {

View file

@ -0,0 +1,6 @@
<vector android:height="48dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,11c0.34,0 0.67,0.03 1,0.08V4c0,-1.1 -0.9,-2 -2,-2H5C3.9,2 3,2.9 3,4v16c0,1.1 0.9,2 2,2h7.26C11.47,20.87 11,19.49 11,18C11,14.13 14.13,11 18,11zM7,11V4h5v7L9.5,9.5L7,11z"/>
<path android:fillColor="@android:color/white" android:pathData="M18,13c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S20.76,13 18,13zM16.75,20.5v-5l4,2.5L16.75,20.5z"/>
</vector>

View file

@ -0,0 +1,6 @@
<vector android:height="48dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M18,11c0.34,0 0.67,0.03 1,0.08V4c0,-1.1 -0.9,-2 -2,-2H5C3.9,2 3,2.9 3,4v16c0,1.1 0.9,2 2,2h7.26C11.47,20.87 11,19.49 11,18C11,14.13 14.13,11 18,11zM7,11V4h5v7L9.5,9.5L7,11z"/>
<path android:fillColor="@android:color/white" android:pathData="M18,13c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S20.76,13 18,13zM16.75,20.5v-5l4,2.5L16.75,20.5z"/>
</vector>

View file

@ -70,6 +70,7 @@
<attr name="media_preview_tour" format="reference" /> <attr name="media_preview_tour" format="reference" />
<attr name="media_preview_contact" format="reference" /> <attr name="media_preview_contact" format="reference" />
<attr name="media_preview_app" format="reference" /> <attr name="media_preview_app" format="reference" />
<attr name="media_preview_audiobook" format="reference" />
<attr name="media_preview_calendar" format="reference" /> <attr name="media_preview_calendar" format="reference" />
<attr name="media_preview_archive" format="reference" /> <attr name="media_preview_archive" format="reference" />
<attr name="media_preview_ebook" format="reference" /> <attr name="media_preview_ebook" format="reference" />

View file

@ -420,6 +420,7 @@
<string name="multimedia_file">multimedia file</string> <string name="multimedia_file">multimedia file</string>
<string name="pdf_document">PDF document</string> <string name="pdf_document">PDF document</string>
<string name="apk">Android App</string> <string name="apk">Android App</string>
<string name="audiobook">Audiobook</string>
<string name="vcard">Contact</string> <string name="vcard">Contact</string>
<string name="avatar_has_been_published">Avatar has been published!</string> <string name="avatar_has_been_published">Avatar has been published!</string>
<string name="sending_x_file">Sending %s</string> <string name="sending_x_file">Sending %s</string>

View file

@ -88,6 +88,7 @@
<item name="media_preview_tour" type="reference">@drawable/baseline_tour_black_48</item> <item name="media_preview_tour" type="reference">@drawable/baseline_tour_black_48</item>
<item name="media_preview_contact" type="reference">@drawable/ic_person_black_48dp</item> <item name="media_preview_contact" type="reference">@drawable/ic_person_black_48dp</item>
<item name="media_preview_app" type="reference">@drawable/ic_android_black_48dp</item> <item name="media_preview_app" type="reference">@drawable/ic_android_black_48dp</item>
<item name="media_preview_audiobook" type="reference">@drawable/ic_play_lesson_black_24</item>
<item name="media_preview_calendar" type="reference">@drawable/ic_event_black_48dp</item> <item name="media_preview_calendar" type="reference">@drawable/ic_event_black_48dp</item>
<item name="media_preview_archive" type="reference">@drawable/ic_archive_black_48dp</item> <item name="media_preview_archive" type="reference">@drawable/ic_archive_black_48dp</item>
<item name="media_preview_ebook" type="reference">@drawable/ic_book_black_48dp</item> <item name="media_preview_ebook" type="reference">@drawable/ic_book_black_48dp</item>
@ -244,6 +245,7 @@
<item name="media_preview_tour" type="reference">@drawable/baseline_tour_white_48</item> <item name="media_preview_tour" type="reference">@drawable/baseline_tour_white_48</item>
<item name="media_preview_contact" type="reference">@drawable/ic_person_white_48dp</item> <item name="media_preview_contact" type="reference">@drawable/ic_person_white_48dp</item>
<item name="media_preview_app" type="reference">@drawable/ic_android_white_48dp</item> <item name="media_preview_app" type="reference">@drawable/ic_android_white_48dp</item>
<item name="media_preview_audiobook" type="reference">@drawable/ic_play_lesson_white_48dp</item>
<item name="media_preview_calendar" type="reference">@drawable/ic_event_white_48dp</item> <item name="media_preview_calendar" type="reference">@drawable/ic_event_white_48dp</item>
<item name="media_preview_archive" type="reference">@drawable/ic_archive_white_48dp</item> <item name="media_preview_archive" type="reference">@drawable/ic_archive_white_48dp</item>
<item name="media_preview_ebook" type="reference">@drawable/ic_book_white_48dp</item> <item name="media_preview_ebook" type="reference">@drawable/ic_book_white_48dp</item>