|
1 | 1 | # react-native-music-library |
2 | 2 |
|
3 | | -[中文版](./README_ZH.md) |
| 3 | +[中文版](./README_ZH.md) | [📖 Documentation](./docs/) |
4 | 4 |
|
5 | 5 | A powerful React Native library for accessing local music files with full metadata support. Built with React Native's New Architecture (TurboModules) for optimal performance. |
6 | 6 |
|
7 | | -> **Note**: Currently only Android is implemented. iOS support is coming soon. |
8 | | -
|
9 | 7 | [](https://badge.fury.io/js/@nodefinity%2Freact-native-music-library) |
10 | 8 | [](https://opensource.org/licenses/MIT) |
11 | 9 |
|
12 | | -## Features & Roadmap |
| 10 | +## ✨ Features |
13 | 11 |
|
14 | | -- [x] 🎵 Access local music library with rich metadata(including lyrics) |
15 | | -- [x] 🚀 Built with TurboModules for maximum performance |
16 | | -- [x] 📄 Pagination support for large music collections |
17 | | -- [x] 🔍 Flexible sorting and filtering options |
18 | | -- [x] 📁 Directory-based filtering |
19 | | -- [x] 🔄 TypeScript support with full type definitions |
20 | | -- [x] 🎨 Base64 album artwork support |
21 | | -- [x] 🤖 Android support |
22 | | -- [ ] 📱 iOS support |
23 | | -- [ ] 📀 Album queries (`getAlbumsAsync`) |
24 | | -- [ ] 👨🎤 Artist queries (`getArtistsAsync`) |
25 | | -- [ ] 🎼 Genre queries (`getGenresAsync`) |
26 | | -- [ ] 🎵 Playlist support |
27 | | -- [ ] 🔍 Search functionality |
28 | | -- [ ] 📡 Real-time library change notifications |
| 12 | +- 🎵 **Rich Metadata** - Access local music with full metadata including lyrics |
| 13 | +- 🚀 **TurboModules** - Built with React Native's New Architecture for maximum performance |
| 14 | +- 📄 **Pagination** - Efficient handling of large music collections |
| 15 | +- 🔍 **Flexible Sorting** - Multiple sorting options for tracks, albums, and artists |
| 16 | +- 📁 **Directory Filtering** - Filter music by specific directories |
| 17 | +- 🔄 **TypeScript** - Full type definitions and type safety |
| 18 | +- 🎨 **Album Artwork** - Support for album artwork and cover images |
| 19 | +- 🤖 **Android Support** - Full native Android implementation |
| 20 | +- 📱 **iOS Support** - Coming soon |
29 | 21 |
|
30 | | -## Installation |
| 22 | +## 🚀 Quick Start |
31 | 23 |
|
32 | | -```sh |
33 | | -npm install @nodefinity/react-native-music-library |
34 | | -``` |
| 24 | +### Installation |
35 | 25 |
|
36 | | -or |
37 | | - |
38 | | -```sh |
| 26 | +```bash |
| 27 | +npm install @nodefinity/react-native-music-library |
| 28 | +# or |
39 | 29 | yarn add @nodefinity/react-native-music-library |
40 | 30 | ``` |
41 | 31 |
|
42 | | -## Platform Support |
43 | | - |
44 | | -This library supports multiple platforms with automatic platform detection: |
45 | | - |
46 | | -- **Android**: Full native music library access |
47 | | -- **iOS**: Full native music library access (coming soon) |
48 | | -- **Web**: Fallback implementation with warnings (for React Native Web projects) |
49 | | - |
50 | | -The library automatically provides the appropriate implementation based on your platform. On web, all methods will return empty results and show development warnings to help with development and testing. |
51 | | - |
52 | | -### Android Setup |
53 | | - |
54 | | -For Android, add the following permission to your `android/app/src/main/AndroidManifest.xml`: |
55 | | - |
56 | | -```xml |
57 | | -<!-- Android 13+ granular permission --> |
58 | | -<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> |
59 | | -<!-- Android 12 and below traditional storage permission --> |
60 | | -<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
61 | | -``` |
62 | | - |
63 | | -### iOS Setup (Coming Soon) |
64 | | - |
65 | | -iOS implementation is not yet available. For now, you can add the permission to your `Info.plist` for future compatibility: |
66 | | - |
67 | | -```xml |
68 | | -<key>NSAppleMusicUsageDescription</key> |
69 | | -<string>This app needs access to your music library to play songs</string> |
70 | | -``` |
71 | | - |
72 | | -## Permissions |
73 | | - |
74 | | -You need to request permission to access the music library before using this library. We recommend using one of these libraries: |
75 | | - |
76 | | -- [react-native-permissions](https://github.com/zoontek/react-native-permissions) |
77 | | -- [expo-media-library](https://docs.expo.dev/versions/latest/sdk/media-library/) (for Expo projects) |
78 | | - |
79 | | -## API Reference |
80 | | - |
81 | | -### getTracksAsync(options?) |
82 | | - |
83 | | -Retrieves music tracks from the device's music library. |
84 | | - |
85 | | -#### Parameters |
86 | | - |
87 | | -- `options` (optional): `AssetsOptions` - Configuration options for the query |
88 | | - |
89 | | -#### Returns |
90 | | - |
91 | | -Promise that resolves to `TrackResult` containing: |
92 | | - |
93 | | -- `items`: Array of `Track` objects |
94 | | -- `hasNextPage`: Boolean indicating if more tracks are available |
95 | | -- `endCursor`: String cursor for pagination |
96 | | -- `totalCount`: Total number of tracks (optional) |
97 | | - |
98 | | -### getTrackMetadataAsync(trackId) |
99 | | - |
100 | | -Retrieves detailed metadata for a specific track, including lyrics and additional metadata from JAudioTagger. |
101 | | - |
102 | | -#### Parameters |
103 | | - |
104 | | -- `trackId`: string - The ID of the track to get metadata for |
105 | | - |
106 | | -#### Returns |
107 | | - |
108 | | -Promise that resolves to `TrackMetadata` containing: |
109 | | - |
110 | | -```typescript |
111 | | -interface TrackMetadata { |
112 | | - id: string; // Track ID |
113 | | - |
114 | | - // audio header |
115 | | - duration: number; // Duration in seconds |
116 | | - bitrate: number; // Bitrate in kbps |
117 | | - sampleRate: number; // Sample rate in Hz |
118 | | - channels: number; // Number of channels |
119 | | - format: string; // Audio format |
120 | | - |
121 | | - // tag info |
122 | | - title: string; // Track title |
123 | | - artist: string; // Artist name |
124 | | - album: string; // Album name |
125 | | - year: number; // Release year |
126 | | - genre: string; // Music genre |
127 | | - track: number; // Track number |
128 | | - disc: number; // Disc number |
129 | | - composer: string; // Composer |
130 | | - lyricist: string; // Lyricist |
131 | | - lyrics: string; // Lyrics content |
132 | | - albumArtist: string; // Album artist |
133 | | - comment: string; // Comment |
134 | | -} |
135 | | -``` |
136 | | - |
137 | | -#### Example |
138 | | - |
139 | | -```js |
140 | | -import { getTrackMetadataAsync } from '@nodefinity/react-native-music-library'; |
141 | | - |
142 | | -// Get metadata for a specific track |
143 | | -const metadata = await getTrackMetadataAsync('track-id-123'); |
144 | | -console.log('Lyrics:', metadata.lyrics); |
145 | | -console.log('Additional metadata:', metadata.additionalMetadata); |
146 | | -``` |
147 | | - |
148 | | -## Type Definitions |
149 | | - |
150 | | -### Track |
151 | | - |
152 | | -```typescript |
153 | | -interface Track { |
154 | | - id: string; |
155 | | - title: string; // Track title |
156 | | - artist: string; // Artist name |
157 | | - artwork: string; // Artwork file URI |
158 | | - album: string; // Album name |
159 | | - duration: number; // Duration in seconds |
160 | | - url: string; // File URL or path |
161 | | - createdAt: number; // Date added (Unix timestamp) |
162 | | - modifiedAt: number; // Date modified (Unix timestamp) |
163 | | - fileSize: number; // File size in bytes |
164 | | -} |
165 | | -``` |
166 | | - |
167 | | -### AssetsOptions |
168 | | - |
169 | | -```typescript |
170 | | -interface AssetsOptions { |
171 | | - after?: string; // Cursor for pagination |
172 | | - first?: number; // Max items to return (default: 20) |
173 | | - sortBy?: SortByValue | SortByValue[]; // Sorting configuration |
174 | | - directory?: string; // Directory path to search |
175 | | -} |
176 | | -``` |
177 | | - |
178 | | -### SortByValue |
179 | | - |
180 | | -```typescript |
181 | | -type SortByValue = SortByKey | [SortByKey, boolean]; |
182 | | - |
183 | | -type SortByKey = |
184 | | - | 'default' |
185 | | - | 'artist' |
186 | | - | 'album' |
187 | | - | 'duration' |
188 | | - | 'createdAt' |
189 | | - | 'modifiedAt' |
190 | | - | 'trackCount'; |
191 | | -``` |
192 | | - |
193 | | -### TrackResult |
194 | | - |
195 | | -```typescript |
196 | | -interface TrackResult { |
197 | | - items: Track[]; // Array of tracks |
198 | | - hasNextPage: boolean; // More items available? |
199 | | - endCursor?: string; // Cursor for next page |
200 | | - totalCount?: number; // Total count (optional) |
201 | | -} |
202 | | -``` |
203 | | - |
204 | | -## Usage Examples |
205 | | - |
206 | 32 | ### Basic Usage |
207 | 33 |
|
208 | 34 | ```js |
209 | | -import { getTracksAsync } from '@nodefinity/react-native-music-library'; |
210 | | - |
211 | | -const loadMusicLibrary = async () => { |
212 | | - try { |
213 | | - const result = await getTracksAsync(); |
214 | | - |
215 | | - result.items.forEach(track => { |
216 | | - console.log(`${track.title} by ${track.artist}`); |
217 | | - console.log(`Duration: ${Math.floor(track.duration / 60)}:${track.duration % 60}`); |
218 | | - console.log(`File: ${track.url}`); |
219 | | - }); |
220 | | - } catch (error) { |
221 | | - console.error('Failed to load music library:', error); |
222 | | - } |
223 | | -}; |
224 | | -``` |
225 | | - |
226 | | -### Pagination |
227 | | - |
228 | | -```js |
229 | | -import { getTracksAsync } from '@nodefinity/react-native-music-library'; |
| 35 | +import { getTracksAsync, getAlbumsAsync, getArtistsAsync } from '@nodefinity/react-native-music-library'; |
230 | 36 |
|
231 | | -const loadAllTracks = async () => { |
232 | | - let allTracks = []; |
233 | | - let hasMore = true; |
234 | | - let cursor; |
235 | | - |
236 | | - while (hasMore) { |
237 | | - const result = await getTracksAsync({ |
238 | | - first: 100, |
239 | | - after: cursor |
240 | | - }); |
241 | | - |
242 | | - allTracks = [...allTracks, ...result.items]; |
243 | | - hasMore = result.hasNextPage; |
244 | | - cursor = result.endCursor; |
245 | | - } |
246 | | - |
247 | | - console.log(`Loaded ${allTracks.length} tracks total`); |
248 | | - return allTracks; |
249 | | -}; |
250 | | -``` |
| 37 | +// Get all tracks |
| 38 | +const tracks = await getTracksAsync(); |
251 | 39 |
|
252 | | -### Sorting |
253 | | - |
254 | | -```js |
255 | | -import { getTracksAsync } from '@nodefinity/react-native-music-library'; |
256 | | - |
257 | | -// Sort by artist name (descending - default) |
258 | | -const tracksByArtist = await getTracksAsync({ |
259 | | - sortBy: 'artist' |
260 | | -}); |
261 | | - |
262 | | -// Sort by artist name ascending |
263 | | -const tracksByArtistAsc = await getTracksAsync({ |
264 | | - sortBy: ['artist', true] |
| 40 | +// Get albums with sorting |
| 41 | +const albums = await getAlbumsAsync({ |
| 42 | + sortBy: ['title', true], // Sort by title ascending |
| 43 | + first: 50 |
265 | 44 | }); |
266 | 45 |
|
267 | | -// Multiple sort criteria |
268 | | -const tracksMultiSort = await getTracksAsync({ |
269 | | - sortBy: [ |
270 | | - ['artist', true], |
271 | | - ['album', true], |
272 | | - 'duration' |
273 | | - ] |
274 | | -}); |
| 46 | +// Get artists |
| 47 | +const artists = await getArtistsAsync(); |
275 | 48 | ``` |
276 | 49 |
|
277 | | -### Directory Filtering |
| 50 | +### Android Permissions |
278 | 51 |
|
279 | | -```js |
280 | | -import { getTracksAsync } from '@nodefinity/react-native-music-library'; |
| 52 | +Add to `android/app/src/main/AndroidManifest.xml`: |
281 | 53 |
|
282 | | -// Get tracks from specific directory |
283 | | -const playlistTracks = await getTracksAsync({ |
284 | | - directory: '/Music/Playlists/Favorites' |
285 | | -}); |
| 54 | +```xml |
| 55 | +<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> |
| 56 | +<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
286 | 57 | ``` |
287 | 58 |
|
288 | | -## Contributing |
| 59 | +## 📖 Documentation |
289 | 60 |
|
290 | | -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. |
| 61 | +- [📚 Full API Documentation](./docs/) |
| 62 | +- [🎯 Getting Started](./docs/getting-started) |
| 63 | +- [🔧 API Reference](./docs/api) |
| 64 | +- [💡 Examples](./docs/examples) |
291 | 65 |
|
292 | | -## License |
| 66 | +## 🤝 Contributing |
293 | 67 |
|
294 | | -MIT |
| 68 | +See [CONTRIBUTING.md](CONTRIBUTING.md) for details. |
295 | 69 |
|
296 | | ---- |
| 70 | +## 📄 License |
297 | 71 |
|
298 | | -Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) |
| 72 | +MIT License - see [LICENSE](LICENSE) for details. |
0 commit comments