18
18
import androidx .annotation .NonNull ;
19
19
import androidx .annotation .Nullable ;
20
20
import androidx .annotation .RequiresApi ;
21
+ import androidx .media3 .common .MediaItem ;
22
+ import androidx .media3 .common .PlaybackException ;
23
+ import androidx .media3 .common .Player ;
24
+ import androidx .media3 .exoplayer .ExoPlayer ;
25
+ import androidx .media3 .ui .PlayerView ;
21
26
22
27
import com .blankj .utilcode .util .AppUtils ;
23
28
import com .blankj .utilcode .util .LogUtils ;
31
36
import com .hss01248 .bigimageviewpager .photoview .MyGifPhotoView ;
32
37
import com .hss01248 .glide .aop .file .AddByteUtil ;
33
38
import com .hss01248 .media .metadata .ExifUtil ;
39
+ import com .hss01248 .motion_photos .MotionPhotoUtil ;
34
40
import com .hss01248 .viewstate .StatefulLayout ;
35
41
import com .hss01248 .viewstate .ViewStateConfig ;
36
42
import com .tencent .qcloud .image .avif .subsampling .AvifSubsamplingImageDecoder ;
@@ -88,7 +94,7 @@ public MyLargeImageViewBySubSamplingView(@NonNull Context context) {
88
94
}
89
95
90
96
}
91
-
97
+ ImageView ivPlayVideo ;
92
98
private void init (Context context ) {
93
99
stateBinding = StateItemLargeImgSubsamplingBinding .inflate (LayoutInflater .from (context ),this ,true );
94
100
largeImgBinding = stateBinding .itemLargeImg ;
@@ -107,6 +113,8 @@ public void run() {
107
113
tvScale = largeImgBinding .tvScale ;
108
114
jpgView = largeImgBinding .ivLarge ;
109
115
gifView = largeImgBinding .gifLarge ;
116
+ ivPlayVideo = stateBinding .itemLargeImg .ivPlayVideo ;
117
+ playerView = stateBinding .itemLargeImg .playView ;
110
118
jpgView .setDebug (AppUtils .isAppDebug ());
111
119
jpgView .setMaxScale (12 );
112
120
@@ -183,7 +191,7 @@ public void setOritation(boolean isLandscape, boolean fromConfigChange){
183
191
}
184
192
185
193
private void reload () {
186
- loadUri (info .uri );
194
+ loadUri (info .uri , true );
187
195
188
196
}
189
197
@@ -210,7 +218,7 @@ public void setOnClickListener(@Nullable OnClickListener l) {
210
218
}
211
219
}
212
220
213
- private void loadUrl (String url ) {
221
+ private void loadUrl (String url , boolean loadMotionVideo ) {
214
222
215
223
stateManager .showLoading ();
216
224
@@ -245,35 +253,35 @@ public void onFail(Throwable throwable) {
245
253
246
254
}
247
255
248
- private void loadFile (String filePath ) {
249
- loadFile (filePath , false );
256
+ private void loadFile (String filePath , boolean loadMotionVideo ) {
257
+ loadFile (filePath , false , loadMotionVideo );
250
258
}
251
259
252
- private void loadFile (String filePath , boolean isGif ) {
253
- loadLocal (filePath , isGif );
260
+ private void loadFile (String filePath , boolean isGif , boolean loadMotionVideo ) {
261
+ loadLocal (filePath , isGif , loadMotionVideo );
254
262
}
255
263
256
264
private void toastMsg (String message ) {
257
265
Toast .makeText (getContext ().getApplicationContext (), message , Toast .LENGTH_LONG ).show ();
258
266
}
259
267
260
- public void loadUri (String uri ) {
268
+ public void loadUri (String uri , boolean loadMotionVideo ) {
261
269
info .uri = uri ;
262
270
//if(uri.startsWith("file://") || uri.startsWith("/storage/"))
263
271
if (uri .startsWith ("http" )) {
264
- loadUrl (uri );
272
+ loadUrl (uri , loadMotionVideo );
265
273
return ;
266
274
}
267
275
if (uri .startsWith ("/storage/" )) {
268
- loadFile (uri , false );
276
+ loadFile (uri , false , loadMotionVideo );
269
277
return ;
270
278
}
271
279
if (uri .startsWith ("file://" )) {
272
- loadFile (uri .substring ("file://" .length ()), false );
280
+ loadFile (uri .substring ("file://" .length ()), false , loadMotionVideo );
273
281
return ;
274
282
}
275
283
if (uri .startsWith ("content://" )) {
276
- loadLocal (uri , false );
284
+ loadLocal (uri , false , loadMotionVideo );
277
285
return ;
278
286
}
279
287
}
@@ -286,9 +294,30 @@ public String getInfoStr(){
286
294
return info .getInfo ();
287
295
}
288
296
289
- private void loadLocal (String uri , boolean isGif ) {
297
+ PlayerView playerView ;
298
+
299
+ private void loadLocal (String uri , boolean isGif , boolean loadMotionVideo ) {
290
300
info .localPathOrUri = uri ;
291
301
largeImgBinding .ivGo360 .setVisibility (GONE );
302
+ // stateBinding.stateLayout.showContent();
303
+ stateManager .showContent ();
304
+ if ( MotionPhotoUtil .isMotionImage (uri ,false )){
305
+ if (loadMotionVideo ){
306
+ loadMotionVideo (uri );
307
+ return ;
308
+ }
309
+ ivPlayVideo .setVisibility (VISIBLE );
310
+ ivPlayVideo .setOnClickListener (new OnClickListener () {
311
+ @ Override
312
+ public void onClick (View view ) {
313
+ loadLocal (info .localPathOrUri ,isGif ,true );
314
+ }
315
+ });
316
+
317
+ }else {
318
+ ivPlayVideo .setVisibility (GONE );
319
+ }
320
+
292
321
if (uri .contains (".gif" ) || isGif ) {
293
322
gifView .setVisibility (VISIBLE );
294
323
jpgView .setVisibility (GONE );
@@ -301,6 +330,21 @@ private void loadLocal(String uri, boolean isGif) {
301
330
}
302
331
stateManager .showContent ();
303
332
} else {
333
+ if (MotionPhotoUtil .isMotionImage (uri ,false ) ){
334
+ if (playerView .getVisibility () != View .GONE ){
335
+ LargeImageViewer .fadeToGone (playerView ,500 );
336
+ }
337
+ ivHelper .setVisibility (VISIBLE );
338
+ ivHelper .setOnClickListener (new OnClickListener () {
339
+ @ Override
340
+ public void onClick (View view ) {
341
+ loadLocal (info .localPathOrUri , isGif , true );
342
+ }
343
+ });
344
+
345
+ }else {
346
+ playerView .setVisibility (View .GONE );
347
+ }
304
348
gifView .setVisibility (GONE );
305
349
jpgView .setVisibility (VISIBLE );
306
350
//兼容avif格式
@@ -333,6 +377,96 @@ private void loadLocal(String uri, boolean isGif) {
333
377
}
334
378
}
335
379
380
+
381
+ ExoPlayer player ;
382
+ Player .Listener listener ;
383
+ private void loadMotionVideo (String uri ) {
384
+ String motionVideoPath = MotionPhotoUtil .getMotionVideoPath (uri );
385
+ if (motionVideoPath ==null || motionVideoPath .equals ("" )){
386
+ return ;
387
+ }
388
+ ivHelper .setVisibility (GONE );
389
+ playerView .setVisibility (VISIBLE );
390
+ gifView .setVisibility (GONE );
391
+ LargeImageViewer .fadeToGone (jpgView ,300 );
392
+ //jpgView.setVisibility(GONE);
393
+ File file = new File (motionVideoPath );
394
+
395
+ if (player !=null ){
396
+ if (player .isPlaying ()){
397
+ player .stop ();
398
+ }else if (player .isLoading ()){
399
+ player .stop ();
400
+ }
401
+ player .release ();
402
+ player = null ;
403
+ }
404
+
405
+ player = new ExoPlayer .Builder (getContext ())
406
+ .build ();
407
+ playerView .setPlayer (player );
408
+ listener = new Player .Listener () {
409
+ @ Override
410
+ public void onPlaybackStateChanged (int playbackState ) {
411
+ Player .Listener .super .onPlaybackStateChanged (playbackState );
412
+ if (playbackState == Player .STATE_ENDED ){
413
+ loadLocal (uri ,false ,false );
414
+ }
415
+ }
416
+
417
+ @ Override
418
+ public void onPlayerError (PlaybackException error ) {
419
+ Player .Listener .super .onPlayerError (error );
420
+ LogUtils .w (error );
421
+ loadLocal (uri ,false ,false );
422
+ }
423
+ };
424
+ player .addListener (listener );
425
+ player .setPlayWhenReady (true );
426
+ player .setRepeatMode (Player .REPEAT_MODE_OFF );
427
+
428
+
429
+ //sending message to a Handler on a dead thread
430
+ try {
431
+ //IllegalStateException: Handler (android.os.Handler) {674e76a} sending message to a Handler on a dead thread
432
+ player .setMediaItem (MediaItem .fromUri (Uri .fromFile (file )));
433
+ player .prepare ();
434
+ }catch (Throwable throwable ){
435
+ LogUtils .w (throwable );
436
+ player .release ();
437
+ player = null ;
438
+ loadLocal (uri ,false ,false );
439
+ }
440
+
441
+ }
442
+
443
+ public void pausePlayer (){
444
+ if (player !=null ){
445
+ if (player .isPlaying () || player .isLoading ()){
446
+ player .stop ();
447
+ }
448
+ player .release ();
449
+ player = null ;
450
+ }
451
+ }
452
+
453
+ @ Override
454
+ protected void onDetachedFromWindow () {
455
+ super .onDetachedFromWindow ();
456
+ LogUtils .w ("onDetachedFromWindow-" +this );
457
+ try {
458
+ if (player !=null ){
459
+ if (player .isPlaying ()){
460
+ player .stop ();
461
+ }
462
+ player .release ();
463
+ }
464
+ }catch (Throwable throwable ){
465
+ LogUtils .w (throwable );
466
+ }
467
+
468
+ }
469
+
336
470
public static boolean isPanoramaImage (String path ){
337
471
Map <String , String > map = ExifUtil .readExif (path );
338
472
String xml = map .get ("Xmp" );
@@ -341,10 +475,10 @@ public static boolean isPanoramaImage(String path){
341
475
LogUtils .i ("根据exif特征识别出为360全景图,不进行压缩" );
342
476
return true ;
343
477
}
344
- if (xml .contains ("MotionPhoto" )){
478
+ /* if(xml.contains("MotionPhoto")){
345
479
LogUtils.i("根据exif特征识别出为MotionPhoto,不进行压缩");
346
480
return true;
347
- }
481
+ }*/
348
482
//MotionPhoto
349
483
}
350
484
return false ;
0 commit comments