Skip to content

Commit 196c277

Browse files
authored
Merge pull request #12044 from TeamNewPipe/android-auto
Add support for Android Auto *(season 2)*
2 parents b378931 + 49b7194 commit 196c277

27 files changed

+1199
-114
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
<intent-filter>
6565
<action android:name="android.intent.action.MEDIA_BUTTON" />
6666
</intent-filter>
67+
<intent-filter>
68+
<action android:name="android.media.browse.MediaBrowserService"/>
69+
</intent-filter>
6770
</service>
6871

6972
<activity
@@ -424,5 +427,10 @@
424427
<meta-data
425428
android:name="com.samsung.android.multidisplay.keep_process_alive"
426429
android:value="true" />
430+
<!-- Android Auto -->
431+
<meta-data android:name="com.google.android.gms.car.application"
432+
android:resource="@xml/automotive_app_desc" />
433+
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
434+
android:resource="@mipmap/ic_launcher" />
427435
</application>
428436
</manifest>

app/src/main/java/org/schabi/newpipe/MainActivity.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,8 @@ private void openMiniPlayerUponPlayerStarted() {
862862
@Override
863863
public void onReceive(final Context context, final Intent intent) {
864864
if (Objects.equals(intent.getAction(),
865-
VideoDetailFragment.ACTION_PLAYER_STARTED)) {
865+
VideoDetailFragment.ACTION_PLAYER_STARTED)
866+
&& PlayerHolder.getInstance().isPlayerOpen()) {
866867
openMiniPlayerIfMissing();
867868
// At this point the player is added 100%, we can unregister. Other actions
868869
// are useless since the fragment will not be removed after that.
@@ -874,6 +875,10 @@ public void onReceive(final Context context, final Intent intent) {
874875
final IntentFilter intentFilter = new IntentFilter();
875876
intentFilter.addAction(VideoDetailFragment.ACTION_PLAYER_STARTED);
876877
registerReceiver(broadcastReceiver, intentFilter);
878+
879+
// If the PlayerHolder is not bound yet, but the service is running, try to bind to it.
880+
// Once the connection is established, the ACTION_PLAYER_STARTED will be sent.
881+
PlayerHolder.getInstance().tryBindIfNeeded(this);
877882
}
878883
}
879884

app/src/main/java/org/schabi/newpipe/database/history/model/StreamHistoryEntry.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package org.schabi.newpipe.database.history.model
33
import androidx.room.ColumnInfo
44
import androidx.room.Embedded
55
import org.schabi.newpipe.database.stream.model.StreamEntity
6+
import org.schabi.newpipe.extractor.stream.StreamInfoItem
7+
import org.schabi.newpipe.util.image.ImageStrategy
68
import java.time.OffsetDateTime
79

810
data class StreamHistoryEntry(
@@ -27,4 +29,17 @@ data class StreamHistoryEntry(
2729
return this.streamEntity.uid == other.streamEntity.uid && streamId == other.streamId &&
2830
accessDate.isEqual(other.accessDate)
2931
}
32+
33+
fun toStreamInfoItem(): StreamInfoItem =
34+
StreamInfoItem(
35+
streamEntity.serviceId,
36+
streamEntity.url,
37+
streamEntity.title,
38+
streamEntity.streamType,
39+
).apply {
40+
duration = streamEntity.duration
41+
uploaderName = streamEntity.uploader
42+
uploaderUrl = streamEntity.uploaderUrl
43+
thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
44+
}
3045
}

app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.schabi.newpipe.database.playlist;
22

3+
import androidx.annotation.Nullable;
4+
35
import org.schabi.newpipe.database.LocalItem;
46

57
public interface PlaylistLocalItem extends LocalItem {
@@ -10,4 +12,7 @@ public interface PlaylistLocalItem extends LocalItem {
1012
long getUid();
1113

1214
void setDisplayIndex(long displayIndex);
15+
16+
@Nullable
17+
String getThumbnailUrl();
1318
}

app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistMetadataEntry.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID;
1010
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_URL;
1111

12+
import androidx.annotation.Nullable;
13+
1214
public class PlaylistMetadataEntry implements PlaylistLocalItem {
1315
public static final String PLAYLIST_STREAM_COUNT = "streamCount";
1416

@@ -71,4 +73,10 @@ public long getUid() {
7173
public void setDisplayIndex(final long displayIndex) {
7274
this.displayIndex = displayIndex;
7375
}
76+
77+
@Nullable
78+
@Override
79+
public String getThumbnailUrl() {
80+
return thumbnailUrl;
81+
}
7482
}

app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistRemoteDAO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public interface PlaylistRemoteDAO extends BasicDAO<PlaylistRemoteEntity> {
3434

3535
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
3636
+ REMOTE_PLAYLIST_ID + " = :playlistId")
37-
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long playlistId);
37+
Flowable<PlaylistRemoteEntity> getPlaylist(long playlistId);
3838

3939
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
4040
+ REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")

app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.text.TextUtils;
44

5+
import androidx.annotation.Nullable;
56
import androidx.room.ColumnInfo;
67
import androidx.room.Entity;
78
import androidx.room.Ignore;
@@ -134,6 +135,8 @@ public void setName(final String name) {
134135
this.name = name;
135136
}
136137

138+
@Nullable
139+
@Override
137140
public String getThumbnailUrl() {
138141
return thumbnailUrl;
139142
}

app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,14 @@ public final class VideoDetailFragment
236236
// Service management
237237
//////////////////////////////////////////////////////////////////////////*/
238238
@Override
239-
public void onServiceConnected(final Player connectedPlayer,
240-
final PlayerService connectedPlayerService,
241-
final boolean playAfterConnect) {
242-
player = connectedPlayer;
239+
public void onServiceConnected(@NonNull final PlayerService connectedPlayerService) {
243240
playerService = connectedPlayerService;
241+
}
242+
243+
@Override
244+
public void onPlayerConnected(@NonNull final Player connectedPlayer,
245+
final boolean playAfterConnect) {
246+
player = connectedPlayer;
244247

245248
// It will do nothing if the player is not in fullscreen mode
246249
hideSystemUiIfNeeded();
@@ -272,11 +275,18 @@ && isAutoplayEnabled()
272275
updateOverlayPlayQueueButtonVisibility();
273276
}
274277

278+
@Override
279+
public void onPlayerDisconnected() {
280+
player = null;
281+
// the binding could be null at this point, if the app is finishing
282+
if (binding != null) {
283+
restoreDefaultBrightness();
284+
}
285+
}
286+
275287
@Override
276288
public void onServiceDisconnected() {
277289
playerService = null;
278-
player = null;
279-
restoreDefaultBrightness();
280290
}
281291

282292

@@ -1848,13 +1858,16 @@ public void onPlayerError(final PlaybackException error, final boolean isCatchab
18481858

18491859
@Override
18501860
public void onServiceStopped() {
1851-
setOverlayPlayPauseImage(false);
1852-
if (currentInfo != null) {
1853-
updateOverlayData(currentInfo.getName(),
1854-
currentInfo.getUploaderName(),
1855-
currentInfo.getThumbnails());
1861+
// the binding could be null at this point, if the app is finishing
1862+
if (binding != null) {
1863+
setOverlayPlayPauseImage(false);
1864+
if (currentInfo != null) {
1865+
updateOverlayData(currentInfo.getName(),
1866+
currentInfo.getUploaderName(),
1867+
currentInfo.getThumbnails());
1868+
}
1869+
updateOverlayPlayQueueButtonVisibility();
18561870
}
1857-
updateOverlayPlayQueueButtonVisibility();
18581871
}
18591872

18601873
@Override

app/src/main/java/org/schabi/newpipe/ktx/Bundle.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,16 @@ import androidx.core.os.BundleCompat
77
inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String?): ArrayList<T>? {
88
return BundleCompat.getParcelableArrayList(this, key, T::class.java)
99
}
10+
11+
fun Bundle?.toDebugString(): String {
12+
if (this == null) {
13+
return "null"
14+
}
15+
val string = StringBuilder("Bundle{")
16+
for (key in this.keySet()) {
17+
@Suppress("DEPRECATION") // we want this[key] to return items of any type
18+
string.append(" ").append(key).append(" => ").append(this[key]).append(";")
19+
}
20+
string.append(" }")
21+
return string.toString()
22+
}

app/src/main/java/org/schabi/newpipe/local/playlist/RemotePlaylistManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public Flowable<List<PlaylistRemoteEntity>> getPlaylists() {
2626
return playlistRemoteTable.getPlaylists().subscribeOn(Schedulers.io());
2727
}
2828

29+
public Flowable<PlaylistRemoteEntity> getPlaylist(final long playlistId) {
30+
return playlistRemoteTable.getPlaylist(playlistId).subscribeOn(Schedulers.io());
31+
}
32+
2933
public Flowable<List<PlaylistRemoteEntity>> getPlaylist(final PlaylistInfo info) {
3034
return playlistRemoteTable.getPlaylist(info.getServiceId(), info.getUrl())
3135
.subscribeOn(Schedulers.io());

0 commit comments

Comments
 (0)