From 6e125563dba459972d3d99ef7bac73e4332be783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Mon, 21 Aug 2023 23:33:48 +0100 Subject: [PATCH] parse music files --- .../activities/MusicFilesActivity.java | 62 ++++++++++++++++--- .../gadgetbridge/util/FileUtils.java | 34 +++++++++- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/MusicFilesActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/MusicFilesActivity.java index 2ef9cb662..746552dd8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/MusicFilesActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/MusicFilesActivity.java @@ -16,26 +16,30 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.activities; -import android.app.Activity; -import android.content.Intent; +import android.content.res.AssetFileDescriptor; +import android.media.MediaMetadataRetriever; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.view.MenuItem; -import androidx.activity.result.ActivityResult; -import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import com.google.android.material.floatingactionbutton.FloatingActionButton; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.List; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; public class MusicFilesActivity extends AbstractGBActivity { private static final Logger LOG = LoggerFactory.getLogger(MusicFilesActivity.class); @@ -50,15 +54,53 @@ public class MusicFilesActivity extends AbstractGBActivity { final ActivityResultLauncher activityResultLauncher = this.registerForActivityResult( new ActivityResultContracts.GetMultipleContents(), - urilist -> LOG.info("got {}", urilist) + urilist -> { + final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); + + LOG.info("Got {}", urilist); + + for (final Uri uri : urilist) { + mediaMetadataRetriever.setDataSource(MusicFilesActivity.this, uri); + + final String title = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); + final String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); + final String album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM); + + long fileSize; + try (AssetFileDescriptor fileDescriptor = getApplicationContext().getContentResolver().openAssetFileDescriptor(uri , "r")){ + fileSize = fileDescriptor.getLength(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + final JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("title", title); + jsonObject.put("album", album); + jsonObject.put("artist", artist); + jsonObject.put("size", fileSize); + } catch (final JSONException e) { + throw new RuntimeException(e); + } + + final String md5; + try (InputStream inputStream = getContentResolver().openInputStream(uri)) { + md5 = FileUtils.md5sum(inputStream); + } catch (final IOException e) { + throw new RuntimeException(e); + } + + LOG.info("{}: {} {}", uri, md5, jsonObject); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + mediaMetadataRetriever.close(); + } + } ); final FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(v -> { - final Intent intent = new Intent(); - intent.setType("audio/*"); - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); - intent.setAction(Intent.ACTION_GET_CONTENT); activityResultLauncher.launch("audio/*"); }); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/FileUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/FileUtils.java index 93b05e573..035aa407b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/FileUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/FileUtils.java @@ -21,6 +21,7 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.os.Environment; +import android.util.Log; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -34,12 +35,20 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.math.BigInteger; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBEnvironment; @@ -349,4 +358,27 @@ public class FileUtils { } return extension; } -} \ No newline at end of file + + @Nullable + public static String md5sum(final InputStream is) { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (final NoSuchAlgorithmException e) { + Log.e(TAG, "Failed to get MD5 digest instance", e); + return null; + } + + try { + final byte[] buffer = new byte[8192]; + int read; + while ((read = is.read(buffer)) > 0) { + digest.update(buffer, 0, read); + } + return String.format("%1$32s", GB.hexdump(digest.digest())).replace(' ', '0').toLowerCase(Locale.ROOT); + } catch (final IOException e) { + Log.e(TAG, "Error reading file", e); + return null; + } + } +}