Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Android Auto #9592

Open
wants to merge 23 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7ed7106
Keep MediaSessionCompat and MediaSessionConnector in a separate class
haggaie Jan 2, 2023
a8af4a6
Simple playback status and controls in Android Auto
haggaie Dec 25, 2022
b587213
Manifest and metadata for Android Auto
haggaie Dec 25, 2022
3d125d2
player: seek to new index when given a new playqueue with a different…
haggaie Feb 4, 2023
00d6311
Media browser interface to show playlists on Android Auto
haggaie Jan 14, 2023
4520f59
StreamHistoryEntry: convert to StreamInfoItem
haggaie Feb 4, 2023
9f5895d
MediaBrowser: expose search history
haggaie Feb 4, 2023
6e5edbf
Pass media browser error as ErrorInfo
haggaie Jun 2, 2023
2522c27
Improve code formatting, annotate more fields and methods
AudricV Aug 11, 2023
0ce1fba
Add icons to root media items
AudricV Aug 11, 2023
2642a92
Add uploader name of streams as subtitle of MediaItems
AudricV Aug 20, 2023
93c85d0
Update media browsers when the list of local playlist changes
haggaie Aug 22, 2023
282141d
android auto: fix navigation tab colors and cut text
haggaie Jul 24, 2024
8599315
PlaylistMetadataEntry: add interface method to get the thumbnail Url
haggaie Aug 2, 2024
6bcf3dc
RemotePlaylistManager: add helper method to get a playlist by its uid
haggaie Aug 2, 2024
662f3ee
media browser: expose remote playlists together with local playlists
haggaie Aug 2, 2024
5d56dce
media browser: support searching
haggaie Aug 4, 2024
17f8fb5
media browser: clean up Uri.parse() null checks
haggaie Aug 16, 2024
1498cc0
Convert new and important files to Kotlin and optimize
snaik20 Sep 2, 2024
ae071ba
media browser: kotlin fixes
haggaie Sep 5, 2024
81f97c1
media browser: remove leftover Java comments
haggaie Sep 17, 2024
cce81bd
media browser: rename remote -> isRemote
haggaie Sep 17, 2024
c91c9f9
media browser: pass media ID to parsing error exceptions
haggaie Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>

<activity
Expand Down Expand Up @@ -423,5 +426,10 @@
<meta-data
android:name="com.samsung.android.multidisplay.keep_process_alive"
android:value="true" />
<!-- Android Auto -->
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
android:resource="@mipmap/ic_launcher" />
</application>
</manifest>
13 changes: 0 additions & 13 deletions app/src/main/java/org/schabi/newpipe/database/LocalItem.java

This file was deleted.

18 changes: 18 additions & 0 deletions app/src/main/java/org/schabi/newpipe/database/LocalItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.schabi.newpipe.database

/**
* Represents a generic item that can be stored locally. This can be a playlist, a stream, etc.
*/
interface LocalItem {
/**
* The type of local item. Can be null if the type is unknown or not applicable.
*/
val localItemType: LocalItemType?

enum class LocalItemType {
PLAYLIST_LOCAL_ITEM,
PLAYLIST_REMOTE_ITEM,
PLAYLIST_STREAM_ITEM,
STATISTIC_STREAM_ITEM,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package org.schabi.newpipe.database.history.model
import androidx.room.ColumnInfo
import androidx.room.Embedded
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.util.image.ImageStrategy
import java.time.OffsetDateTime

data class StreamHistoryEntry(
Expand All @@ -27,4 +29,17 @@ data class StreamHistoryEntry(
return this.streamEntity.uid == other.streamEntity.uid && streamId == other.streamId &&
accessDate.isEqual(other.accessDate)
}

fun toStreamInfoItem(): StreamInfoItem =
StreamInfoItem(
streamEntity.serviceId,
streamEntity.url,
streamEntity.title,
streamEntity.streamType,
).apply {
duration = streamEntity.duration
uploaderName = streamEntity.uploader
uploaderUrl = streamEntity.uploaderUrl
thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.schabi.newpipe.database.playlist

import org.schabi.newpipe.database.LocalItem

/**
* Represents a playlist item stored locally.
*/
interface PlaylistLocalItem : LocalItem {
/**
* The name used for ordering this item within the playlist. Can be null.
*/
val orderingName: String?

/**
* The index used to display this item within the playlist.
*/
var displayIndex: Long

/**
* The unique identifier for this playlist item.
*/
val uid: Long

/**
* The URL of the thumbnail image for this playlist item. Can be null.
*/
val thumbnailUrl: String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ public long getUid() {
public void setDisplayIndex(final long displayIndex) {
this.displayIndex = displayIndex;
}

@Override
public String getThumbnailUrl() {
return thumbnailUrl;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ data class PlaylistStreamEntry(
@ColumnInfo(name = PlaylistStreamEntity.JOIN_INDEX)
val joinIndex: Int
) : LocalItem {

@Throws(IllegalArgumentException::class)
fun toStreamInfoItem(): StreamInfoItem {
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
item.thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)

return item
}

override fun getLocalItemType(): LocalItem.LocalItemType {
return LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM
}
fun toStreamInfoItem() =
StreamInfoItem(
streamEntity.serviceId,
streamEntity.url,
streamEntity.title,
streamEntity.streamType,
).apply {
duration = streamEntity.duration
uploaderName = streamEntity.uploader
uploaderUrl = streamEntity.uploaderUrl
thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
}

override val localItemType: LocalItem.LocalItemType
get() = LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ class StreamStatisticsEntry(
@ColumnInfo(name = STREAM_WATCH_COUNT)
val watchCount: Long
) : LocalItem {
fun toStreamInfoItem(): StreamInfoItem {
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
item.thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)

return item
}

override fun getLocalItemType(): LocalItem.LocalItemType {
return LocalItem.LocalItemType.STATISTIC_STREAM_ITEM
}
fun toStreamInfoItem() =
StreamInfoItem(
streamEntity.serviceId,
streamEntity.url,
streamEntity.title,
streamEntity.streamType,
).apply {
duration = streamEntity.duration
uploaderName = streamEntity.uploader
uploaderUrl = streamEntity.uploaderUrl
thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
}

override val localItemType: LocalItem.LocalItemType
get() = LocalItem.LocalItemType.STATISTIC_STREAM_ITEM

companion object {
const val STREAM_LATEST_DATE = "latestAccess"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ public Flowable<List<PlaylistRemoteEntity>> getPlaylists() {
return playlistRemoteTable.getPlaylists().subscribeOn(Schedulers.io());
}

public Flowable<List<PlaylistRemoteEntity>> getPlaylist(final long playlistId) {
return playlistRemoteTable.getPlaylist(playlistId).subscribeOn(Schedulers.io());
}

public Flowable<List<PlaylistRemoteEntity>> getPlaylist(final PlaylistInfo info) {
return playlistRemoteTable.getPlaylist(info.getServiceId(), info.getUrl())
.subscribeOn(Schedulers.io());
Expand Down
7 changes: 6 additions & 1 deletion app/src/main/java/org/schabi/newpipe/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex;
import static org.schabi.newpipe.util.ListHelper.getResolutionIndex;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import android.content.BroadcastReceiver;
Expand Down Expand Up @@ -302,7 +303,7 @@ public Player(@NonNull final PlayerService service) {
// notification ui in the UIs list, since the notification depends on the media session in
// PlayerUi#initPlayer(), and UIs.call() guarantees UI order is preserved.
UIs = new PlayerUiList(
new MediaSessionPlayerUi(this),
new MediaSessionPlayerUi(this, service.getSessionConnector()),
new NotificationPlayerUi(this)
);
}
Expand Down Expand Up @@ -415,6 +416,10 @@ public void handleIntent(@NonNull final Intent intent) {
== com.google.android.exoplayer2.Player.STATE_IDLE) {
simpleExoPlayer.prepare();
}
if (playQueue.getIndex() != newQueue.getIndex()) {
simpleExoPlayer.seekTo(newQueue.getIndex(),
requireNonNull(newQueue.getItem()).getRecoveryPosition());
}
simpleExoPlayer.setPlayWhenReady(playWhenReady);

} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false)
Expand Down
Loading
Loading