diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1932e55..7c35cd5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,9 @@
+
+
+
-
+
+
+
+
+
+
diff --git a/app/src/main/java/at/lockstep/app/MainActivity.java b/app/src/main/java/at/lockstep/app/MainActivity.java
index a219cc3..d47abcc 100644
--- a/app/src/main/java/at/lockstep/app/MainActivity.java
+++ b/app/src/main/java/at/lockstep/app/MainActivity.java
@@ -1,6 +1,7 @@
package at.lockstep.app;
import android.app.Activity;
+import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
@@ -12,6 +13,7 @@ import at.lockstep.pb.PlaybackEngine;
public class MainActivity extends Activity {
private Button btnStart;
private Button btnStop;
+ private Button btnMediaStoreBenchmark;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -20,6 +22,7 @@ public class MainActivity extends Activity {
btnStart = findViewById(R.id.btnStart);
btnStop = findViewById(R.id.btnStop);
+ btnMediaStoreBenchmark = findViewById(R.id.btnMediaStoreBenchmark);
// TODO: handle clicking START button twice
btnStart.setOnClickListener(v ->
@@ -39,5 +42,10 @@ public class MainActivity extends Activity {
btnStop.setOnClickListener(v ->
startService(LstForegroundService.stopIntent(MainActivity.this))
);
+
+ btnMediaStoreBenchmark.setOnClickListener(v -> {
+ Intent intent = new Intent(MainActivity.this, MediaStoreBenchmarkActivity.class);
+ startActivity(intent);
+ });
}
}
diff --git a/app/src/main/java/at/lockstep/app/MediaStoreBenchmarkActivity.java b/app/src/main/java/at/lockstep/app/MediaStoreBenchmarkActivity.java
new file mode 100644
index 0000000..9331d06
--- /dev/null
+++ b/app/src/main/java/at/lockstep/app/MediaStoreBenchmarkActivity.java
@@ -0,0 +1,141 @@
+package at.lockstep.app;
+
+import static androidx.activity.result.ActivityResultCallerKt.registerForActivityResult;
+
+import android.app.Activity;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.provider.MediaStore;
+import android.widget.TextView;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.core.content.ContextCompat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import at.lockstep.R;
+
+public class MediaStoreBenchmarkActivity extends Activity {
+
+ private TextView resultTextView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_media_store_benchmark);
+
+ resultTextView = findViewById(R.id.resultTextView);
+
+ if (hasReadPermission()) {
+ loadMusic();
+ } else {
+ requestReadPermission();
+ }
+ }
+
+ private static final int REQUEST_READ_PERMISSION = 1001;
+
+ @Override
+ public void onRequestPermissionsResult(
+ int requestCode,
+ String[] permissions,
+ int[] grantResults
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (requestCode == REQUEST_READ_PERMISSION) {
+ boolean granted = grantResults.length > 0
+ && grantResults[0] == PackageManager.PERMISSION_GRANTED;
+
+ if (granted) {
+ loadMusic();
+ } else {
+ resultTextView.setText("Permission denied.");
+ }
+ }
+ }
+
+ private boolean hasReadPermission() {
+ String permission;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ permission = Manifest.permission.READ_MEDIA_AUDIO;
+ } else {
+ permission = Manifest.permission.READ_EXTERNAL_STORAGE;
+ }
+
+ return ContextCompat.checkSelfPermission(this, permission)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private void requestReadPermission() {
+ String permission;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ permission = Manifest.permission.READ_MEDIA_AUDIO;
+ } else {
+ permission = Manifest.permission.READ_EXTERNAL_STORAGE;
+ }
+
+ //permissionLauncher.launch(permission);
+ requestPermissions(
+ new String[]{ permission },
+ REQUEST_READ_PERMISSION
+ );
+ }
+
+ private void loadMusic() {
+ List musicList = new ArrayList<>();
+
+ android.net.Uri collection = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+
+ String[] projection = new String[] {
+ MediaStore.Audio.Media._ID,
+ MediaStore.Audio.Media.TITLE,
+ MediaStore.Audio.Media.DATA
+ };
+
+ String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
+
+ long start = SystemClock.elapsedRealtime();
+
+ try (android.database.Cursor cursor = getContentResolver().query(
+ collection,
+ projection,
+ selection,
+ null,
+ MediaStore.Audio.Media.TITLE + " ASC"
+ )) {
+ if (cursor != null) {
+ int titleColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE);
+ int dataColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
+
+ while (cursor.moveToNext()) {
+ String title = cursor.getString(titleColumn);
+ String path = dataColumn != -1 ? cursor.getString(dataColumn) : null;
+
+ if (path != null) {
+ musicList.add(title + "\n" + path);
+ } else {
+ musicList.add(title + "\n[path unavailable]");
+ }
+ }
+ }
+ }
+
+ long elapsedMs = SystemClock.elapsedRealtime() - start;
+
+ StringBuilder header = new StringBuilder();
+ header.append("Found ").append(musicList.size()).append(" music files\n");
+ header.append("Query time: ").append(elapsedMs).append(" ms\n\n");
+
+ resultTextView.setText(header.toString() + String.join("\n\n", musicList));
+
+ // 200 music files in 32 ms
+ // paths like "/storage/emulated/0/Download/...mp3"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index e946fd5..f8cc49a 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -18,4 +18,10 @@
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Stop collection" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_media_store_benchmark.xml b/app/src/main/res/layout/activity_media_store_benchmark.xml
new file mode 100644
index 0000000..71a723c
--- /dev/null
+++ b/app/src/main/res/layout/activity_media_store_benchmark.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file