Skip to content

Commit ff030d8

Browse files
committed
feat(android): add configurable notification click behavior
1 parent cad7f4b commit ff030d8

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

android/src/main/java/com/doublesymmetry/trackplayer/service/MusicService.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,19 @@ class MusicService : HeadlessJsMediaService() {
9898
}
9999
})
100100
fakePlayer = ExoPlayer.Builder(this).build()
101+
102+
val notificationClickBehavior = androidOptions?.getBundle(NOTIFICATION_CLICK_BEHAVIOR_KEY)
103+
val enableUriData = notificationClickBehavior?.getBoolean(NOTIFICATION_CLICK_ENABLED_KEY, true) ?: true
104+
101105
val openAppIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
102106
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
103-
// Add the Uri data so apps can identify that it was a notification click
104-
data = Uri.parse("trackplayer://notification.click")
105-
action = Intent.ACTION_VIEW
107+
if (enableUriData) {
108+
val customUri = notificationClickBehavior?.getString(NOTIFICATION_CLICK_CUSTOM_URI_KEY)
109+
data = Uri.parse(customUri ?: "trackplayer://notification.click")
110+
111+
val customAction = notificationClickBehavior?.getString(NOTIFICATION_CLICK_CUSTOM_ACTION_KEY)
112+
action = customAction ?: Intent.ACTION_VIEW
113+
}
106114
}
107115
mediaSession = MediaLibrarySession.Builder(this, fakePlayer,
108116
InnerMediaSessionCallback()
@@ -1022,6 +1030,12 @@ class MusicService : HeadlessJsMediaService() {
10221030
const val IS_FOCUS_LOSS_PERMANENT_KEY = "permanent"
10231031
const val IS_PAUSED_KEY = "paused"
10241032

1033+
// Notification click behavior keys
1034+
const val NOTIFICATION_CLICK_BEHAVIOR_KEY = "notificationClickBehavior"
1035+
const val NOTIFICATION_CLICK_ENABLED_KEY = "enabled"
1036+
const val NOTIFICATION_CLICK_CUSTOM_URI_KEY = "customUri"
1037+
const val NOTIFICATION_CLICK_CUSTOM_ACTION_KEY = "action"
1038+
10251039
const val HANDLE_NOISY = "androidHandleAudioBecomingNoisy"
10261040
const val ALWAYS_SHOW_NEXT = "androidAlwaysShowNext"
10271041
const val SKIP_SILENCE = "androidSkipSilence"

docs/docs/api/objects/android-options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ Options available for the android player. All options are optional.
77
| `appKilledPlaybackBehavior` | [`AppKilledPlaybackBehavior`](../constants/app-killed-playback-behavior.md) | [`ContinuePlayback`](../constants/app-killed-playback-behavior.md#continueplayback-default) | Define how the audio playback should behave after removing the app from recents (killing it). |
88
| `alwaysPauseOnInterruption` | `boolean` | `false` | Whether the `remote-duck` event will be triggered on every interruption |
99
| `stopForegroundGracePeriod` | `number` | `5` | Time in seconds to wait once the player should transition to not considering the service as in the foreground. If playback resumes within this grace period, the service remains in the foreground state. |
10+
| `notificationClickBehavior` | [`NotificationClickBehavior`](./notification-click-behavior.md) | [`Default Value`](./notification-click-behavior.md) | Configuration for notification click behavior |
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# NotificationClickBehavior
2+
3+
Configuration for notification click behavior on Android.
4+
5+
| Param | Type | Default | Description |
6+
|-------|-------|---------|-------------|
7+
| `enabled` | `boolean` | `true` | Whether to add URI data to the notification click intent. When disabled, the app will launch without any URI information. |
8+
| `customUri` | `string` | `"trackplayer://notification.click"` | Custom URI to use instead of the default. Only used when `enabled` is `true`. |
9+
| `action` | `string` | `"android.intent.action.VIEW"` | Custom action to use for the notification click intent. Only used when `enabled` is `true`. |
10+
11+
## Default Value
12+
13+
```typescript
14+
{
15+
enabled: true,
16+
customUri: "trackplayer://notification.click",
17+
action: "android.intent.action.VIEW"
18+
}
19+
```
20+
21+
## Examples
22+
23+
### Disable URI data (launch app without notification click detection)
24+
```typescript
25+
await TrackPlayer.updateOptions({
26+
android: {
27+
notificationClickBehavior: {
28+
enabled: false
29+
}
30+
}
31+
});
32+
```
33+
34+
### Use custom URI
35+
```typescript
36+
await TrackPlayer.updateOptions({
37+
android: {
38+
notificationClickBehavior: {
39+
enabled: true,
40+
customUri: "myapp://notification.click"
41+
}
42+
}
43+
});
44+
```
45+
46+
### Use custom action
47+
```typescript
48+
await TrackPlayer.updateOptions({
49+
android: {
50+
notificationClickBehavior: {
51+
enabled: true,
52+
action: "android.intent.action.MAIN"
53+
}
54+
}
55+
});
56+
```
57+
58+
### Complete configuration
59+
```typescript
60+
await TrackPlayer.updateOptions({
61+
android: {
62+
notificationClickBehavior: {
63+
enabled: true,
64+
customUri: "myapp://player.notification",
65+
action: "android.intent.action.VIEW"
66+
}
67+
}
68+
});
69+
```

example/android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
22

33
<uses-permission android:name="android.permission.INTERNET" />
4+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
45
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
56

67
<application

example/src/services/SetupService.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ export const SetupService = async () => {
2222
await TrackPlayer.updateOptions({
2323
android: {
2424
appKilledPlaybackBehavior: DefaultAudioServiceBehaviour,
25+
// Example: Configure notification click behavior
26+
// You can disable URI data to launch app without notification click detection
27+
// notificationClickBehavior: {
28+
// enabled: false
29+
// },
30+
// Or use custom URI and action
31+
// notificationClickBehavior: {
32+
// enabled: true,
33+
// customUri: "example://notification.click",
34+
// action: "android.intent.action.VIEW"
35+
// }
2536
},
2637
capabilities: [
2738
Capability.Play,

src/interfaces/AndroidOptions.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
import type { AppKilledPlaybackBehavior } from '../constants';
22

3+
export interface NotificationClickBehavior {
4+
/**
5+
* Whether to add URI data to the notification click intent
6+
* @default true
7+
*/
8+
enabled?: boolean;
9+
10+
/**
11+
* Custom URI to use instead of the default "trackplayer://notification.click"
12+
* Only used when enabled is true
13+
*/
14+
customUri?: string;
15+
16+
/**
17+
* Custom action to use for the notification click intent
18+
* @default "android.intent.action.VIEW"
19+
*/
20+
action?: string;
21+
}
22+
323
export interface AndroidOptions {
424
/**
525
* Whether the audio playback notification is also removed when the playback
@@ -21,6 +41,11 @@ export interface AndroidOptions {
2141
*/
2242
stopForegroundGracePeriod?: number;
2343

44+
/**
45+
* Configuration for notification click behavior
46+
*/
47+
notificationClickBehavior?: NotificationClickBehavior;
48+
2449
/**
2550
* https://developer.android.com/media/media3/exoplayer/track-selection#audioOffload
2651
*/

0 commit comments

Comments
 (0)