Skip to content

Commit 0e947ee

Browse files
committed
Upgrade TDLib to tdlib/td@b498497
And something more.
1 parent e1faf0a commit 0e947ee

35 files changed

+1146
-505
lines changed

‎app/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ dependencies {
420420
implementation("androidx.media3:media3-transformer:${LibraryVersions.ANDROIDX_MEDIA}")
421421
implementation("androidx.media3:media3-effect:${LibraryVersions.ANDROIDX_MEDIA}")
422422
implementation("androidx.media3:media3-common:${LibraryVersions.ANDROIDX_MEDIA}")
423+
implementation("androidx.media3:media3-exoplayer-hls:${LibraryVersions.ANDROIDX_MEDIA}")
423424
// 17.x version requires minSdk 19 or higher
424425
implementation("com.google.mlkit:language-id:16.1.1")
425426
// The Checker Framework: https://checkerframework.org/CHANGELOG.md

‎app/src/main/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
android:installLocation="auto">
55

6-
<uses-sdk tools:overrideLibrary="androidx.media3.exoplayer, androidx.media3.common, androidx.media3.transformer, androidx.media3.extractor, androidx.media3.muxer, androidx.media3.decoder, androidx.media3.container, androidx.media3.datasource, androidx.media3.database, androidx.media3.effect, androidx.camera.camera2, androidx.camera.core, androidx.camera.video, androidx.camera.view, androidx.camera.lifecycle, androidx.camera.extensions, com.google.android.play.core.integrity.client, com.otaliastudios.transcoder, com.otaliastudios.opengl, com.google.android.recaptcha, com.google.android.gms.recaptchabase" />
6+
<uses-sdk tools:overrideLibrary="androidx.media3.exoplayer, androidx.media3.exoplayer.hls, androidx.media3.common, androidx.media3.transformer, androidx.media3.extractor, androidx.media3.muxer, androidx.media3.decoder, androidx.media3.container, androidx.media3.datasource, androidx.media3.database, androidx.media3.effect, androidx.camera.camera2, androidx.camera.core, androidx.camera.video, androidx.camera.view, androidx.camera.lifecycle, androidx.camera.extensions, com.google.android.play.core.integrity.client, com.otaliastudios.transcoder, com.otaliastudios.opengl, com.google.android.recaptcha, com.google.android.gms.recaptchabase" />
77

88
<uses-feature
99
android:glEsVersion="0x00020000"

‎app/src/main/java/org/thunderdog/challegram/U.java

+107-10
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,33 @@
8282
import androidx.annotation.Nullable;
8383
import androidx.core.os.EnvironmentCompat;
8484
import androidx.exifinterface.media.ExifInterface;
85+
import androidx.media3.common.C;
86+
import androidx.media3.common.Format;
87+
import androidx.media3.common.MimeTypes;
8588
import androidx.media3.common.PlaybackException;
89+
import androidx.media3.common.util.TimestampAdjuster;
90+
import androidx.media3.datasource.ByteArrayDataSource;
91+
import androidx.media3.datasource.DataSource;
8692
import androidx.media3.datasource.FileDataSource;
8793
import androidx.media3.exoplayer.DefaultLoadControl;
8894
import androidx.media3.exoplayer.DefaultRenderersFactory;
8995
import androidx.media3.exoplayer.ExoPlaybackException;
9096
import androidx.media3.exoplayer.ExoPlayer;
9197
import androidx.media3.exoplayer.RenderersFactory;
98+
import androidx.media3.exoplayer.analytics.PlayerId;
99+
import androidx.media3.exoplayer.hls.BundledHlsMediaChunkExtractor;
100+
import androidx.media3.exoplayer.hls.DefaultHlsExtractorFactory;
101+
import androidx.media3.exoplayer.hls.HlsExtractorFactory;
102+
import androidx.media3.exoplayer.hls.HlsMediaChunkExtractor;
103+
import androidx.media3.exoplayer.hls.HlsMediaSource;
104+
import androidx.media3.exoplayer.hls.playlist.DefaultHlsPlaylistParserFactory;
92105
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
93106
import androidx.media3.exoplayer.source.MediaSource;
94-
import androidx.media3.exoplayer.source.MediaSourceFactory;
95107
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
96108
import androidx.media3.exoplayer.source.UnrecognizedInputFormatException;
97109
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
98110
import androidx.media3.extractor.DefaultExtractorsFactory;
111+
import androidx.media3.extractor.ExtractorInput;
99112
import androidx.recyclerview.widget.RecyclerView;
100113

101114
import com.google.android.gms.common.ConnectionResult;
@@ -161,6 +174,7 @@
161174
import java.util.TreeSet;
162175
import java.util.concurrent.CountDownLatch;
163176
import java.util.concurrent.TimeUnit;
177+
import java.util.concurrent.TimeoutException;
164178
import java.util.zip.GZIPInputStream;
165179

166180
import javax.microedition.khronos.egl.EGL10;
@@ -185,6 +199,8 @@
185199
import okio.Sink;
186200
import okio.Source;
187201
import tgx.td.Td;
202+
import tgx.td.data.HlsPath;
203+
import tgx.td.data.HlsVideo;
188204

189205
@SuppressWarnings ("JniMissingFunction")
190206
public class U {
@@ -726,7 +742,7 @@ public static ExoPlayer newExoPlayer (Context context, boolean preferExtensions)
726742
// DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON
727743
final int extensionMode = preferExtensions || org.thunderdog.challegram.unsorted.Settings.instance().getNewSetting(org.thunderdog.challegram.unsorted.Settings.SETTING_FLAG_FORCE_EXO_PLAYER_EXTENSIONS) ? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER : DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON;
728744
final RenderersFactory renderersFactory = new DefaultRenderersFactory(context).setExtensionRendererMode(extensionMode);
729-
final MediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true));
745+
final MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true));
730746
return new ExoPlayer.Builder(context, renderersFactory, mediaSourceFactory)
731747
.setTrackSelector(new DefaultTrackSelector(context))
732748
.setLoadControl(new DefaultLoadControl())
@@ -746,29 +762,109 @@ public static MediaSource newMediaSource (File file) {
746762
}
747763

748764
public static androidx.media3.common.MediaItem newMediaItem (Uri uri) {
749-
return new androidx.media3.common.MediaItem.Builder().setUri(uri).build();
765+
return androidx.media3.common.MediaItem.fromUri(uri);
750766
}
751767

752768
public static MediaSource newMediaSource (int accountId, TdApi.Message message) {
753769
return newMediaSource(accountId, TD.getFile(message));
754770
}
755771

772+
public static MediaSource newMediaSource (int accountId, @Nullable HlsVideo hlsVideo) {
773+
if (hlsVideo == null) {
774+
throw new IllegalArgumentException();
775+
}
776+
777+
Uri manifestUri = TdlibDataSource.UriFactory.create(accountId, -1);
778+
779+
TdlibDataSource.Factory factory = new TdlibDataSource.Factory(accountId, new TdlibDataSource.RequestModifier() {
780+
@Override
781+
public Uri modifyUri (Uri sourceUri) {
782+
String scheme = sourceUri.getScheme();
783+
if (scheme == null) {
784+
throw new IllegalArgumentException(sourceUri.toString());
785+
}
786+
switch (scheme) {
787+
case HlsVideo.MTPROTO_SCHEME: {
788+
long streamId = HlsVideo.extractStreamId(sourceUri);
789+
int videoFileId = hlsVideo.findVideoFileIdByStreamId(streamId);
790+
return TdlibDataSource.UriFactory.create(accountId, videoFileId);
791+
}
792+
case HlsVideo.SCHEME: {
793+
HlsPath hlsPath = HlsPath.fromUri(sourceUri);
794+
return TdlibDataSource.UriFactory.create(accountId, hlsPath.hlsFileId);
795+
}
796+
default: {
797+
return sourceUri;
798+
}
799+
}
800+
}
801+
802+
@Nullable
803+
@Override
804+
public DataSource redirectDataSource (Uri uri) {
805+
if (uri.equals(manifestUri)) {
806+
String playlistData = hlsVideo.multivariantPlaylistData();
807+
return new ByteArrayDataSource(playlistData.getBytes());
808+
}
809+
return null;
810+
}
811+
});
812+
813+
return new HlsMediaSource.Factory(factory)
814+
.setAllowChunklessPreparation(false)
815+
.setExtractorFactory(newHlsExtractorFactory(hlsVideo))
816+
.createMediaSource(newMediaItem(manifestUri));
817+
}
818+
819+
@NonNull private static HlsExtractorFactory newHlsExtractorFactory (@NonNull HlsVideo hlsVideo) {
820+
DefaultHlsExtractorFactory defaultHlsExtractorFactory = new DefaultHlsExtractorFactory();
821+
return new HlsExtractorFactory() {
822+
@Override
823+
@NonNull
824+
public HlsMediaChunkExtractor createExtractor (@NonNull Uri uri, @NonNull Format format, @Nullable List<Format> muxedCaptionFormats, @NonNull TimestampAdjuster timestampAdjuster, @NonNull Map<String, List<String>> responseHeaders, @NonNull ExtractorInput sniffingExtractorInput, @NonNull PlayerId playerId) throws IOException {
825+
if (HlsVideo.MTPROTO_SCHEME.equals(uri.getScheme())) {
826+
long streamId = HlsVideo.extractStreamId(uri);
827+
TdApi.AlternativeVideo alternativeVideo = hlsVideo.findVideoByStreamId(streamId);
828+
format = format.buildUpon()
829+
.setCodecs(alternativeVideo.codec)
830+
.setWidth(alternativeVideo.width)
831+
.setHeight(alternativeVideo.height)
832+
.setContainerMimeType(MimeTypes.VIDEO_MP4)
833+
.setCryptoType(C.CRYPTO_TYPE_UNSUPPORTED)
834+
.build();
835+
if (!timestampAdjuster.isInitialized()) {
836+
try {
837+
timestampAdjuster.sharedInitializeOrWait(true, 0, 0);
838+
} catch (TimeoutException | InterruptedException ignored) { }
839+
}
840+
}
841+
return defaultHlsExtractorFactory.createExtractor(uri, format, muxedCaptionFormats, timestampAdjuster, responseHeaders, sniffingExtractorInput, playerId);
842+
}
843+
};
844+
}
845+
756846
public static MediaSource newMediaSource (int accountId, @Nullable TdApi.File file) {
757847
if (file == null)
758848
throw new IllegalArgumentException();
849+
Uri uri;
850+
DataSource.Factory factory;
759851
if (file.id == -1 && !StringUtils.isEmpty(file.local.path)) {
760-
return newMediaSource(new File(file.local.path));
852+
uri = Uri.fromFile(new File(file.local.path));
853+
factory = new FileDataSource.Factory();
761854
} else {
762-
return new ProgressiveMediaSource.Factory(new TdlibDataSource.Factory()).createMediaSource(newMediaItem(TdlibDataSource.UriFactory.create(accountId, file)));
855+
uri = TdlibDataSource.UriFactory.create(accountId, file);
856+
factory = new TdlibDataSource.Factory();
763857
}
858+
androidx.media3.common.MediaItem media = newMediaItem(uri);
859+
return new ProgressiveMediaSource.Factory(factory).createMediaSource(media);
764860
}
765861

766862
public static MediaSource newMediaSource (RandomAccessFile file) {
767863
return new ProgressiveMediaSource.Factory(new RandomAccessDataSource.Factory(file)).createMediaSource(newMediaItem(Uri.EMPTY));
768864
}
769865

770866
public static MediaSource newMediaSource (int accountId, int fileId) {
771-
return new ProgressiveMediaSource.Factory(new TdlibDataSource.Factory()).createMediaSource(newMediaItem(TdlibDataSource.UriFactory.create(accountId, fileId)));
867+
return new ProgressiveMediaSource.Factory(new TdlibDataSource.Factory(accountId)).createMediaSource(newMediaItem(TdlibDataSource.UriFactory.create(accountId, fileId)));
772868
}
773869

774870
public static boolean isGooglePlayServicesAvailable (Context context) {
@@ -1204,11 +1300,12 @@ public static float getAnimationScale (Context context) {
12041300
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
12051301
return ValueAnimator.getDurationScale();
12061302
}
1207-
try {
1208-
return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
1209-
} catch (Throwable ignored) {
1210-
return 1.0f;
1303+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1304+
try {
1305+
return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
1306+
} catch (Throwable ignored) { }
12111307
}
1308+
return 1.0f;
12121309
}
12131310
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
12141311
final String column = "_data";

‎app/src/main/java/org/thunderdog/challegram/component/chat/MessageView.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -1019,22 +1019,26 @@ public static Object fillMessageOptions (MessagesController m, TGMessage msg, @N
10191019
TdApi.File file = TD.getFile(msg.getMessage());
10201020
if (file != null && !file.remote.isUploadingActive) {
10211021
if (Config.useCloudPlayback(msg.getMessage()) && !file.local.isDownloadingCompleted) {
1022-
if (isMore) {
1023-
if (file.local.isDownloadingActive && !TdlibManager.instance().player().isPlayingFileId(file.id)) {
1022+
if (file.local.isDownloadingActive && !TdlibManager.instance().player().isPlayingFileId(file.id)) {
1023+
if (isMore) {
10241024
ids.append(R.id.btn_pauseFile);
10251025
strings.append(R.string.CloudPause);
10261026
icons.append(R.drawable.baseline_cloud_pause_24);
1027+
} else {
1028+
moreOptions++;
10271029
}
1028-
if (!file.local.isDownloadingActive) {
1030+
}
1031+
if (!file.local.isDownloadingActive) {
1032+
if (isMore) {
10291033
ids.append(R.id.btn_downloadFile);
10301034
if (file.local.downloadedSize > 0)
10311035
strings.append(R.string.CloudResume);
10321036
else
10331037
strings.append(Lang.getString(R.string.CloudDownload, Strings.buildSize(file.size)));
10341038
icons.append(R.drawable.baseline_cloud_download_24);
1039+
} else {
1040+
moreOptions++;
10351041
}
1036-
} else {
1037-
moreOptions++;
10381042
}
10391043
}
10401044
}
@@ -1043,7 +1047,7 @@ public static Object fillMessageOptions (MessagesController m, TGMessage msg, @N
10431047
boolean hasFilesToRemove = false;
10441048
TdApi.Message[] allMessages = msg.getAllMessages();
10451049
for (TdApi.Message message : allMessages) {
1046-
if (TD.canDeleteFile(message)) {
1050+
if (TD.canDeleteFiles(m.tdlib(), message)) {
10471051
hasFilesToRemove = true;
10481052
break;
10491053
}
@@ -1138,8 +1142,6 @@ public static Object fillMessageOptions (MessagesController m, TGMessage msg, @N
11381142
}
11391143
}
11401144
}
1141-
} else if (!isMore) {
1142-
moreOptions += 2;
11431145
}
11441146
}
11451147

‎app/src/main/java/org/thunderdog/challegram/component/chat/MessagesLoader.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ private TdApi.Message newMessage (final long chatId, final boolean isChannel, fi
12231223
null, null, null, null,
12241224
null, null, 0, 0,
12251225
null, 0, 0,
1226-
0, 0, 0, null,
1226+
0, 0, 0, 0, null,
12271227
0, 0, false,
12281228
null, null, null
12291229
);

‎app/src/main/java/org/thunderdog/challegram/data/ContentPreview.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class ContentPreview {
3737
public static final Emoji EMOJI_LINK = new Emoji("\uD83D\uDD17", R.drawable.baseline_link_16);
3838
public static final Emoji EMOJI_GAME = new Emoji("\uD83C\uDFAE", R.drawable.baseline_videogame_asset_16);
3939
public static final Emoji EMOJI_GROUP = new Emoji("\uD83D\uDC65", R.drawable.baseline_group_16);
40+
public static final Emoji EMOJI_VIDEO_CHAT = new Emoji("\uD83D\uDC65", R.drawable.baseline_group_add_16);
41+
public static final Emoji EMOJI_LIVE_STREAM = new Emoji("\uD83D\uDCE2", R.drawable.baseline_mic_16);
4042
public static final Emoji EMOJI_GIFT = new Emoji("\uD83C\uDF81", R.drawable.baseline_redeem_16);
4143
public static final Emoji EMOJI_STARS = new Emoji("\u2B50", R.drawable.baseline_premium_star_16);
4244
public static final Emoji EMOJI_BOOST = new Emoji("\u26A1", R.drawable.baseline_bolt_16);
@@ -1165,8 +1167,27 @@ else if (((TdApi.PushMessageContentSticker) push.content).sticker != null && Td.
11651167
return getNotificationPreview(TdApi.MessagePaidMedia.CONSTRUCTOR, tdlib, chatId, push.senderId, push.senderName, null);
11661168
}
11671169
}
1170+
case TdApi.PushMessageContentProximityAlertTriggered.CONSTRUCTOR: {
1171+
TdApi.PushMessageContentProximityAlertTriggered proximityAlertTriggered = (TdApi.PushMessageContentProximityAlertTriggered) push.content;
1172+
return getNotificationPreview(TdApi.MessageProximityAlertTriggered.CONSTRUCTOR, tdlib, chatId, push.senderId, push.senderName, null, proximityAlertTriggered.distance, 0);
1173+
}
1174+
case TdApi.PushMessageContentVideoChatStarted.CONSTRUCTOR: {
1175+
return getNotificationPreview(TdApi.MessageVideoChatStarted.CONSTRUCTOR, tdlib, chatId, push.senderId, push.senderName, null);
1176+
}
1177+
case TdApi.PushMessageContentVideoChatEnded.CONSTRUCTOR: {
1178+
return getNotificationPreview(TdApi.MessageVideoChatEnded.CONSTRUCTOR, tdlib, chatId, push.senderId, push.senderName, null);
1179+
}
1180+
case TdApi.PushMessageContentInviteVideoChatParticipants.CONSTRUCTOR: {
1181+
TdApi.PushMessageContentInviteVideoChatParticipants inviteVideoChatParticipants = (TdApi.PushMessageContentInviteVideoChatParticipants) push.content;
1182+
boolean isChannel = tdlib.isChannel(chatId);
1183+
if (inviteVideoChatParticipants.isCurrentUser) {
1184+
return new ContentPreview(isChannel ? EMOJI_LIVE_STREAM : EMOJI_VIDEO_CHAT, isChannel ? R.string.ChatContentLiveStreamAddYou : R.string.ChatContentVideoChatAddYou);
1185+
} else {
1186+
return new ContentPreview(isChannel ? EMOJI_LIVE_STREAM : EMOJI_VIDEO_CHAT, isChannel ? R.string.ChatContentLiveStreamAddSomeone : R.string.ChatContentVideoChatAddSomeone);
1187+
}
1188+
}
11681189
default:
1169-
Td.assertPushMessageContent_7e58be7d();
1190+
Td.assertPushMessageContent_6685917b();
11701191
throw Td.unsupported(push.content);
11711192
}
11721193
}
@@ -1443,12 +1464,15 @@ else if (isChatsList)
14431464
return new ContentPreview(EMOJI_GIFT, 0, text, true);
14441465
}
14451466

1467+
case TdApi.MessageProximityAlertTriggered.CONSTRUCTOR: {
1468+
int distance = (int) arg1;
1469+
return new ContentPreview(EMOJI_LOCATION, 0, Lang.plural(distance >= 1000 ? R.string.ChatContentProximityFromYouKm : R.string.ChatContentProximityFromYouM, distance >= 1000 ? distance / 1000 : distance, tdlib.senderName(sender, true)), true);
1470+
}
14461471

14471472
// Must be supported by the caller and never passed to this method.
14481473
case TdApi.MessageGiftedPremium.CONSTRUCTOR:
14491474
case TdApi.MessageGiftedStars.CONSTRUCTOR:
14501475
case TdApi.MessageGameScore.CONSTRUCTOR:
1451-
case TdApi.MessageProximityAlertTriggered.CONSTRUCTOR:
14521476
case TdApi.MessageChatAddMembers.CONSTRUCTOR:
14531477
case TdApi.MessageChatDeleteMember.CONSTRUCTOR:
14541478
case TdApi.MessageCustomServiceAction.CONSTRUCTOR:

0 commit comments

Comments
 (0)