├── .eslintrc.js ├── .gitignore ├── .npmignore ├── README.md ├── android ├── .gitignore ├── .idea │ └── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── expo │ └── community │ └── modules │ └── musicpicker │ ├── Models.kt │ ├── MusicMetadataResolver.kt │ ├── MusicPickerExceptions.kt │ ├── MusicPickerModule.kt │ ├── MusicPickerOptions.kt │ ├── PermissionsCompat.kt │ └── Utilities.kt ├── app.plugin.js ├── babel.config.js ├── build ├── ExpoMusicPicker.d.ts ├── ExpoMusicPicker.js ├── ExpoMusicPicker.js.map ├── ExpoMusicPicker.types.d.ts ├── ExpoMusicPicker.types.js ├── ExpoMusicPicker.types.js.map ├── MusicPickerModule.d.ts ├── MusicPickerModule.js ├── MusicPickerModule.js.map ├── MusicPickerModule.web.d.ts ├── MusicPickerModule.web.js └── MusicPickerModule.web.js.map ├── example ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.tsx ├── android │ ├── .gitignore │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── expo │ │ │ │ └── community │ │ │ │ └── modules │ │ │ │ └── musicpicker │ │ │ │ └── example │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── expo │ │ │ │ └── community │ │ │ │ └── modules │ │ │ │ └── musicpicker │ │ │ │ └── example │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MainApplication.java │ │ │ │ └── newarchitecture │ │ │ │ ├── MainApplicationReactNativeHost.java │ │ │ │ ├── components │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ └── modules │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ ├── jni │ │ │ ├── Android.mk │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ ├── MainApplicationModuleProvider.h │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ ├── MainComponentsRegistry.cpp │ │ │ ├── MainComponentsRegistry.h │ │ │ └── OnLoad.cpp │ │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-mdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xxhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable-xxxhdpi │ │ │ └── splashscreen_image.png │ │ │ ├── drawable │ │ │ ├── rn_edit_text_material.xml │ │ │ └── splashscreen.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-night │ │ │ └── colors.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── assets │ ├── adaptive-icon.png │ ├── album-placeholder.png │ ├── favicon.png │ ├── icon.png │ └── splash.png ├── babel.config.js ├── index.js ├── ios │ ├── .gitignore │ ├── Podfile │ ├── Podfile.lock │ ├── Podfile.properties.json │ ├── expomusicpickerexample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── expomusicpickerexample.xcscheme │ ├── expomusicpickerexample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── expomusicpickerexample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── App-Icon-20x20@1x.png │ │ │ ├── App-Icon-20x20@2x.png │ │ │ ├── App-Icon-20x20@3x.png │ │ │ ├── App-Icon-29x29@1x.png │ │ │ ├── App-Icon-29x29@2x.png │ │ │ ├── App-Icon-29x29@3x.png │ │ │ ├── App-Icon-40x40@1x.png │ │ │ ├── App-Icon-40x40@2x.png │ │ │ ├── App-Icon-40x40@3x.png │ │ │ ├── App-Icon-60x60@2x.png │ │ │ ├── App-Icon-60x60@3x.png │ │ │ ├── App-Icon-76x76@1x.png │ │ │ ├── App-Icon-76x76@2x.png │ │ │ ├── App-Icon-83.5x83.5@2x.png │ │ │ ├── Contents.json │ │ │ └── ItunesArtwork@2x.png │ │ ├── Contents.json │ │ ├── SplashScreen.imageset │ │ │ ├── Contents.json │ │ │ └── image.png │ │ └── SplashScreenBackground.imageset │ │ │ ├── Contents.json │ │ │ └── image.png │ │ ├── Info.plist │ │ ├── SplashScreen.storyboard │ │ ├── Supporting │ │ └── Expo.plist │ │ ├── expomusicpickerexample.entitlements │ │ ├── main.m │ │ └── noop-file.swift ├── metro.config.js ├── package.json ├── tsconfig.json ├── webpack.config.js └── yarn.lock ├── expo-module.config.json ├── ios ├── ExpoMusicPicker.podspec ├── MusicLibraryPermissionRequester.swift ├── MusicPickerDelegate.swift ├── MusicPickerExceptions.swift ├── MusicPickerModule.swift └── MusicPickerOptions.swift ├── package.json ├── src ├── ExpoMusicPicker.ts ├── ExpoMusicPicker.types.ts ├── MusicPickerModule.ts └── MusicPickerModule.web.ts ├── tsconfig.json └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['universe/native', 'universe/web'], 4 | ignorePatterns: ['build'], 5 | }; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Exclude all top-level hidden directories by convention 2 | /.*/ 3 | 4 | __mocks__ 5 | __tests__ 6 | 7 | example/ 8 | /babel.config.js 9 | /android/src/androidTest/ 10 | /android/src/test/ 11 | 12 | yarn.lock 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Expo Music Picker 3 | 4 | expo-image-picker demo 5 | 6 | A music picker library for React Native. Provides access to the system's UI for selecting songs from the phone's music library. 7 | 8 | ## Supported platforms 9 | 10 | | Android
Device | Android
Emulator | iOS
Device | iOS
Simulator | Web | Expo Go | 11 | | -------------- | ---------------- | ---------- | ------------- | --- | ------- | 12 | | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | 13 | 14 | - ✅ You can use this library with [Expo Development Builds](https://docs.expo.dev/development/introduction/). It includes a config plugin. 15 | - ❌ This library can't be used in the "Expo Go" app because it [requires custom native code](https://docs.expo.dev/workflow/customizing/). 16 | 17 | > This library requires Expo SDK 45 or newer 18 | 19 | ## Installation 20 | 21 | ```sh 22 | npx expo install expo-music-picker 23 | ``` 24 | 25 | Once the library is installed, [create a new Development Build](https://docs.expo.dev/development/build/). 26 | 27 | If you're installing this in a bare React Native app, you will need to have the [`expo` package installed and configured](https://docs.expo.dev/bare/installing-expo-modules/). 28 | 29 | ## Configuration in app.json / app.config.js 30 | 31 | Add `expo-music-picker` to the plugins array of your **app.json** or **app.config.js** and then [create a new Development Build](https://docs.expo.dev/development/build/) to apply the changes. 32 | 33 | ```json 34 | { 35 | "expo": { 36 | "plugins": [ 37 | "expo-music-picker", 38 | { "musicLibraryPermission": "The app accesses your music to play it" } 39 | ] 40 | } 41 | } 42 | ``` 43 | 44 | The config plugin has the following options: 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
NameTypeExplanationRequiredDefault Value
musicLibraryPermissionstring🍏 iOS only A string to set the NSAppleMusicUsageDescription permission message."Allow $(PRODUCT_NAME) to access your music library"
62 | 63 | ## Configuration for iOS 🍏 64 | 65 | > This is only required for usage in bare React Native apps. 66 | 67 | Add `NSAppleMusicUsageDescription` key to your `Info.plist`: 68 | 69 | ```xml 70 | NSAppleMusicUsageDescription 71 | Give $(PRODUCT_NAME) permission to access your music library 72 | ``` 73 | 74 | Run `npx pod-install` after installing the npm package. 75 | 76 | ## Configuration for Android 🤖 77 | 78 | > This is only required for usage in bare React Native apps. 79 | 80 | This package automatically adds the `READ_EXTERNAL_STORAGE` permission. It is used when picking music from the phone's library. 81 | 82 | ```xml 83 | 84 | 85 | ``` 86 | 87 | --- 88 | 89 | ## Usage 90 | 91 | ```ts 92 | import { useState } from "react"; 93 | import { Image, Text, View, Button } from "react-native"; 94 | 95 | import * as MusicPicker from "expo-music-picker"; 96 | 97 | export default function App() { 98 | const [item, setItem] = useState(); 99 | 100 | const pickMediaAsync = async () => { 101 | try { 102 | // Request permissions 103 | const permissionResult = await MusicPicker.requestPermissionsAsync(); 104 | if (!permissionResult.granted) { 105 | console.warn("No permission"); 106 | return; 107 | } 108 | 109 | // Open the music picker 110 | const result = await MusicPicker.openMusicLibraryAsync({ 111 | allowMultipleSelection: true, 112 | includeArtworkImage: true, 113 | }); 114 | 115 | // Process the result 116 | console.log(result); 117 | if (!result.cancelled) { 118 | const [firstItem] = result.items; 119 | setItem(firstItem ?? null); 120 | } 121 | } catch (e) { 122 | console.warn("Exception occurred when picking music:", e); 123 | } 124 | }; 125 | 126 | const artworkData = item?.artworkImage?.base64Data; 127 | 128 | return ( 129 | 130 |