Skip to content

Commit 7f47c1c

Browse files
authored
Merge pull request #4177 from parneet-guraya/migrate-to-media3
Migrate to media3
2 parents fb8a1c9 + 2d3ccb8 commit 7f47c1c

17 files changed

+510
-1066
lines changed

gradle/libs.versions.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ androidxWork = "2.8.1"
2424
coil = "2.2.2"
2525
dexopener = "2.0.5"
2626
disklrucache = "2.0.2"
27-
exoplayer ="2.16.1"
27+
media3 ="1.1.1"
2828
floatingactionbutton = "1.10.1"
2929
glide = "4.15.1"
3030
glideToVectorYou = "v2.0.0"
@@ -81,7 +81,8 @@ androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx"
8181
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
8282
dexopener = { group = "com.github.tmurakami", name = "dexopener", version.ref = "dexopener" }
8383
disklrucache = { group = "com.jakewharton", name = "disklrucache", version.ref = "disklrucache" }
84-
exoplayer = { group = "com.google.android.exoplayer", name = "exoplayer", version.ref = "exoplayer" }
84+
media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
85+
media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" }
8586
floatingactionbutton = { group = "com.getbase", name = "floatingactionbutton", version.ref = "floatingactionbutton" }
8687
glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
8788
glide-vector = { group = "com.github.2coffees1team", name = "GlideToVectorYou", version.ref = "glideToVectorYou" }

owncloudApp/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ dependencies {
4949

5050
// Miscellaneous
5151
implementation libs.disklrucache
52-
implementation libs.exoplayer
52+
implementation libs.media3.exoplayer
53+
implementation libs.media3.ui
5354
implementation libs.floatingactionbutton
5455
implementation libs.material
5556
implementation libs.patternlockview

owncloudApp/src/main/AndroidManifest.xml

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,16 @@
5656
android:supportsPictureInPicture="false"
5757
android:taskAffinity=""
5858
android:theme="@style/Theme.ownCloud.Toolbar">
59+
<activity
60+
android:name=".ui.preview.PreviewVideoActivity"
61+
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
62+
android:theme="@style/Theme.ownCloud.Video"
63+
android:exported="false" />
5964

60-
<meta-data android:name="android.content.APP_RESTRICTIONS"
65+
<meta-data
66+
android:name="android.content.APP_RESTRICTIONS"
6167
android:resource="@xml/managed_configurations" />
68+
6269
<activity
6370
android:name=".presentation.releasenotes.ReleaseNotesActivity"
6471
android:exported="false" />
@@ -67,10 +74,11 @@
6774
<activity android:name=".presentation.migration.StorageMigrationActivity" />
6875
<activity
6976
android:name=".ui.activity.SplashActivity"
70-
android:theme="@style/Theme.ownCloud.Splash"
71-
android:exported="true">
77+
android:exported="true"
78+
android:theme="@style/Theme.ownCloud.Splash">
7279
<intent-filter>
7380
<action android:name="android.intent.action.MAIN" />
81+
7482
<category android:name="android.intent.category.LAUNCHER" />
7583
</intent-filter>
7684
</activity>
@@ -83,8 +91,8 @@
8391
android:name=".ui.activity.ReceiveExternalFilesActivity"
8492
android:configChanges="orientation|screenSize"
8593
android:excludeFromRecents="true"
86-
android:taskAffinity=""
87-
android:exported="true">
94+
android:exported="true"
95+
android:taskAffinity="">
8896
<intent-filter>
8997
<action android:name="android.intent.action.SEND" />
9098

@@ -168,8 +176,8 @@
168176

169177
<activity
170178
android:name=".presentation.security.passcode.PassCodeActivity"
171-
android:theme="@style/Theme.ownCloud"
172-
android:screenOrientation="portrait"/>
179+
android:screenOrientation="portrait"
180+
android:theme="@style/Theme.ownCloud" />
173181
<activity
174182
android:name=".presentation.conflicts.ConflictsResolveActivity"
175183
android:theme="@style/Theme.ownCloud" />
@@ -191,11 +199,11 @@
191199
<activity android:name=".ui.activity.UploadPathActivity" />
192200
<activity
193201
android:name=".presentation.sharing.ShareActivity"
202+
android:exported="false"
194203
android:label="@string/share_dialog_title"
195204
android:launchMode="singleTop"
196205
android:theme="@style/Theme.ownCloud"
197-
android:windowSoftInputMode="adjustResize"
198-
android:exported="false">
206+
android:windowSoftInputMode="adjustResize">
199207
<intent-filter>
200208
<action android:name="android.intent.action.SEARCH" />
201209
</intent-filter>
@@ -208,10 +216,6 @@
208216
android:name=".ui.activity.ManageSpaceActivity"
209217
android:label="@string/manage_space_title"
210218
android:theme="@style/Theme.ownCloud" />
211-
<activity
212-
android:name=".ui.preview.PreviewVideoActivity"
213-
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
214-
android:theme="@style/Theme.ownCloud.Fullscreen" />
215219
<activity
216220
android:name=".presentation.security.pattern.PatternActivity"
217221
android:screenOrientation="portrait"
@@ -234,4 +238,5 @@
234238
</intent-filter>
235239
</activity>
236240
</application>
237-
</manifest>
241+
242+
</manifest>

owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ import com.owncloud.android.ui.fragment.FileFragment
7474
import com.owncloud.android.ui.preview.PreviewAudioFragment
7575
import com.owncloud.android.ui.preview.PreviewImageFragment
7676
import com.owncloud.android.ui.preview.PreviewTextFragment
77-
import com.owncloud.android.ui.preview.PreviewVideoFragment
77+
import com.owncloud.android.ui.preview.PreviewVideoActivity
7878
import com.owncloud.android.usecases.synchronization.SynchronizeFileUseCase
7979
import com.owncloud.android.utils.DisplayUtils
8080
import com.owncloud.android.utils.MimetypeIconUtil
@@ -533,7 +533,7 @@ class FileDetailsFragment : FileFragment() {
533533
fileDisplayActivity.startAudioPreview(fileWaitingToPreview, 0)
534534
}
535535

536-
PreviewVideoFragment.canBePreviewed(fileWaitingToPreview) -> {
536+
PreviewVideoActivity.canBePreviewed(fileWaitingToPreview) -> {
537537
fileDisplayActivity.startVideoPreview(fileWaitingToPreview, 0)
538538
}
539539

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ import com.owncloud.android.ui.activity.FileActivity
104104
import com.owncloud.android.ui.activity.FileDisplayActivity
105105
import com.owncloud.android.ui.activity.FolderPickerActivity
106106
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment
107-
import com.owncloud.android.ui.preview.PreviewVideoFragment
108107
import com.owncloud.android.utils.DisplayUtils
109108
import com.owncloud.android.utils.MimetypeIconUtil
110109
import com.owncloud.android.utils.PreferenceUtils
@@ -1135,16 +1134,8 @@ class MainFileListFragment : Fragment(),
11351134
downloadWorkerUuid = fileWithSyncInfo.downloadWorkerUuid,
11361135
isSynchronizing = fileWithSyncInfo.isSynchronizing
11371136
)
1138-
1139-
val secondFragment = requireActivity().supportFragmentManager.findFragmentByTag(TAG_SECOND_FRAGMENT)
1140-
val isAnyFileVideoPreviewing = if (secondFragment is PreviewVideoFragment) {
1141-
secondFragment.file == file
1142-
} else {
1143-
false
1144-
}
1145-
11461137
mainFileListViewModel.filterMenuOptions(
1147-
listOf(file), listOf(fileSync), isAnyFileVideoPreviewing,
1138+
listOf(file), listOf(fileSync),
11481139
displaySelectAll = false, isMultiselection = false
11491140
)
11501141
}
@@ -1199,15 +1190,9 @@ class MainFileListFragment : Fragment(),
11991190
)
12001191
}
12011192

1202-
val secondFragment = requireActivity().supportFragmentManager.findFragmentByTag(TAG_SECOND_FRAGMENT)
1203-
val isAnyFileVideoPreviewing = if (secondFragment is PreviewVideoFragment) {
1204-
checkedFiles.any { secondFragment.file == it }
1205-
} else {
1206-
false
1207-
}
12081193
val displaySelectAll = checkedCount != fileListAdapter.itemCount - 1 // -1 because one of them is the footer :S
12091194
mainFileListViewModel.filterMenuOptions(
1210-
checkedFiles, checkedFilesSync, isAnyFileVideoPreviewing,
1195+
checkedFiles, checkedFilesSync,
12111196
displaySelectAll, isMultiselection = true
12121197
)
12131198

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ class MainFileListViewModel(
300300
}
301301

302302
fun filterMenuOptions(
303-
files: List<OCFile>, filesSyncInfo: List<OCFileSyncInfo>, isAnyFileVideoPreviewing: Boolean,
303+
files: List<OCFile>, filesSyncInfo: List<OCFileSyncInfo>,
304304
displaySelectAll: Boolean, isMultiselection: Boolean
305305
) {
306306
val shareViaLinkAllowed = contextProvider.getBoolean(R.bool.share_via_link_feature)
@@ -312,7 +312,7 @@ class MainFileListViewModel(
312312
files = files,
313313
filesSyncInfo = filesSyncInfo,
314314
accountName = currentFolderDisplayed.value.owner,
315-
isAnyFileVideoPreviewing = isAnyFileVideoPreviewing,
315+
isAnyFileVideoPreviewing = false,
316316
displaySelectAll = displaySelectAll,
317317
displaySelectInverse = isMultiselection,
318318
onlyAvailableOfflineFiles = fileListOption.value.isAvailableOffline(),

owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ import com.owncloud.android.ui.preview.PreviewImageActivity
105105
import com.owncloud.android.ui.preview.PreviewImageFragment
106106
import com.owncloud.android.ui.preview.PreviewTextFragment
107107
import com.owncloud.android.ui.preview.PreviewVideoActivity
108-
import com.owncloud.android.ui.preview.PreviewVideoFragment
109108
import com.owncloud.android.usecases.synchronization.SynchronizeFileUseCase
110109
import com.owncloud.android.usecases.transfers.downloads.DownloadFileUseCase
111110
import com.owncloud.android.utils.PreferenceUtils
@@ -430,7 +429,7 @@ class FileDisplayActivity : FileActivity(),
430429
// Otherwise, decide which fragment should be shown.
431430
return when {
432431
PreviewAudioFragment.canBePreviewed(file) -> {
433-
val startPlaybackPosition = intent.getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0)
432+
val startPlaybackPosition = intent.getIntExtra(PreviewVideoActivity.EXTRA_PLAY_POSITION, 0)
434433
val autoplay = intent.getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true)
435434
PreviewAudioFragment.newInstance(
436435
file,
@@ -440,17 +439,6 @@ class FileDisplayActivity : FileActivity(),
440439
)
441440
}
442441

443-
PreviewVideoFragment.canBePreviewed(file) -> {
444-
val startPlaybackPosition = intent.getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0)
445-
val autoplay = intent.getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true)
446-
PreviewVideoFragment.newInstance(
447-
file,
448-
account,
449-
startPlaybackPosition,
450-
autoplay
451-
)
452-
}
453-
454442
PreviewTextFragment.canBePreviewed(file) -> {
455443
PreviewTextFragment.newInstance(
456444
file,
@@ -459,7 +447,7 @@ class FileDisplayActivity : FileActivity(),
459447
}
460448

461449
else -> {
462-
FileDetailsFragment.newInstance(file, account)
450+
FileDetailsFragment.newInstance(file, account, false)
463451
}
464452
}
465453
}
@@ -971,10 +959,6 @@ class FileDisplayActivity : FileActivity(),
971959
is PreviewAudioFragment -> {
972960
secondFragment.stopPreview()
973961
}
974-
975-
is PreviewVideoFragment -> {
976-
secondFragment.releasePlayer()
977-
}
978962
}
979963
file = storageManager.getFileById(lastRemovedFile.parentId!!)
980964
cleanSecondFragment()
@@ -1546,15 +1530,11 @@ class FileDisplayActivity : FileActivity(),
15461530
* in milliseconds.
15471531
*/
15481532
fun startVideoPreview(file: OCFile, startPlaybackPosition: Int) {
1549-
val mediaFragment = PreviewVideoFragment.newInstance(
1550-
file,
1551-
account,
1552-
startPlaybackPosition,
1553-
true
1554-
)
1555-
setSecondFragment(mediaFragment)
1556-
updateToolbar(file)
1557-
setFile(file)
1533+
val videoActivityIntent = Intent(this, PreviewVideoActivity::class.java)
1534+
videoActivityIntent.putExtra(PreviewVideoActivity.EXTRA_FILE, file)
1535+
videoActivityIntent.putExtra(PreviewVideoActivity.EXTRA_ACCOUNT, account)
1536+
videoActivityIntent.putExtra(PreviewVideoActivity.EXTRA_PLAY_POSITION, startPlaybackPosition)
1537+
startActivity(videoActivityIntent)
15581538
}
15591539

15601540
/**
@@ -1728,7 +1708,7 @@ class FileDisplayActivity : FileActivity(),
17281708
fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(file, account.name))
17291709
}
17301710

1731-
PreviewVideoFragment.canBePreviewed(file) && !WorkManager.getInstance(this).isDownloadPending(account, file) -> {
1711+
PreviewVideoActivity.canBePreviewed(file) && !WorkManager.getInstance(this).isDownloadPending(account, file) -> {
17321712
// Available offline but not downloaded yet, don't initialize streaming
17331713
if (!file.isAvailableLocally && file.isAvailableOffline) {
17341714
// sync file content, then open with external apps

owncloudApp/src/main/java/com/owncloud/android/ui/preview/CustomHttpDataSourceFactory.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@
2020
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2121
*/
2222

23-
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
24-
import com.google.android.exoplayer2.upstream.HttpDataSource;
25-
import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory;
26-
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
27-
import com.google.android.exoplayer2.upstream.TransferListener;
23+
import androidx.annotation.OptIn;
24+
import androidx.media3.common.util.UnstableApi;
25+
import androidx.media3.datasource.DefaultHttpDataSource;
26+
import androidx.media3.datasource.HttpDataSource;
27+
import androidx.media3.datasource.TransferListener;
2828

2929
import java.util.Map;
3030

3131
/**
3232
* A {@link Factory} that produces {@link CustomHttpDataSourceFactory} instances.
3333
*/
34-
public final class CustomHttpDataSourceFactory extends BaseFactory {
34+
@OptIn(markerClass = UnstableApi.class)
35+
public final class CustomHttpDataSourceFactory extends HttpDataSource.BaseFactory {
3536

3637
private final String userAgent;
3738
private final TransferListener listener;

owncloudApp/src/main/java/com/owncloud/android/ui/preview/PrepareVideoPlayerAsyncTask.java

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
2019
package com.owncloud.android.ui.preview;
2120

2221
import android.accounts.Account;
@@ -27,15 +26,17 @@
2726
import android.os.AsyncTask;
2827
import android.util.Base64;
2928

30-
import com.google.android.exoplayer2.MediaItem;
31-
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
32-
import com.google.android.exoplayer2.source.MediaSource;
33-
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
34-
import com.google.android.exoplayer2.upstream.DataSource;
35-
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
36-
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
37-
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
38-
import com.google.android.exoplayer2.upstream.HttpDataSource;
29+
import androidx.annotation.OptIn;
30+
import androidx.media3.common.MediaItem;
31+
import androidx.media3.common.util.UnstableApi;
32+
import androidx.media3.datasource.DataSource;
33+
import androidx.media3.datasource.DefaultDataSourceFactory;
34+
import androidx.media3.datasource.DefaultHttpDataSource;
35+
import androidx.media3.datasource.HttpDataSource;
36+
import androidx.media3.exoplayer.source.MediaSource;
37+
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
38+
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter;
39+
import androidx.media3.extractor.DefaultExtractorsFactory;
3940
import com.owncloud.android.MainApp;
4041
import com.owncloud.android.domain.files.model.OCFile;
4142
import com.owncloud.android.lib.common.accounts.AccountUtils;
@@ -53,20 +54,22 @@
5354
/**
5455
* Task for prepare video player asynchronously
5556
*/
57+
@OptIn(markerClass = UnstableApi.class)
5658
public class PrepareVideoPlayerAsyncTask extends AsyncTask<Object, Void, MediaSource> {
5759

5860
private final Context mContext;
5961
private final WeakReference<OnPrepareVideoPlayerTaskListener> mListener;
6062
private final OCFile mFile;
6163
private final Account mAccount;
6264

63-
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
65+
private static DefaultBandwidthMeter BANDWIDTH_METER;
6466

6567
public PrepareVideoPlayerAsyncTask(Context context, OnPrepareVideoPlayerTaskListener listener, OCFile file, Account account) {
6668
mContext = context;
6769
mListener = new WeakReference<>(listener);
6870
mFile = file;
6971
mAccount = account;
72+
BANDWIDTH_METER = new DefaultBandwidthMeter.Builder(mContext).build();
7073
}
7174

7275
@Override
@@ -79,8 +82,7 @@ protected MediaSource doInBackground(Object... params) {
7982
try {
8083
// If the file is already downloaded, reproduce it locally, if not, do streaming
8184
uri = mFile.isAvailableLocally() ? UriUtilsKt.INSTANCE.getStorageUriForFile(mFile) :
82-
Uri.parse(AccountUtils.getWebDavUrlForAccount(mContext, mAccount) +
83-
Uri.encode(mFile.getRemotePath(), "/"));
85+
Uri.parse(AccountUtils.getWebDavUrlForAccount(mContext, mAccount) + Uri.encode(mFile.getRemotePath(), "/"));
8486

8587
boolean useBandwidthMeter = true;
8688

@@ -121,10 +123,7 @@ private MediaSource buildMediaSource(DataSource.Factory mediaDataSourceFactory,
121123
* DataSource factory.
122124
* @return A new HttpDataSource factory.
123125
*/
124-
private HttpDataSource.Factory buildHttpDataSourceFactory(
125-
DefaultBandwidthMeter bandwidthMeter,
126-
OCFile file,
127-
Account account) {
126+
private HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter, OCFile file, Account account) {
128127

129128
if (file.isAvailableLocally()) {
130129

@@ -150,8 +149,7 @@ private HttpDataSource.Factory buildHttpDataSourceFactory(
150149
params.put("Authorization", auth);
151150
}
152151

153-
return new CustomHttpDataSourceFactory(MainApp.Companion.getUserAgent(),
154-
bandwidthMeter, params);
152+
return new CustomHttpDataSourceFactory(MainApp.Companion.getUserAgent(), bandwidthMeter, params);
155153

156154
} catch (AuthenticatorException | IOException | OperationCanceledException e) {
157155
Timber.e(e);

0 commit comments

Comments
 (0)