florent37 / Flutter-AssetsAudioPlayer

Play simultaneously music/audio from assets/network/file directly from Flutter, compatible with android / ios / web / macos, displays notifications
https://pub.dartlang.org/packages/assets_audio_player
Apache License 2.0
757 stars 372 forks source link

Handle certificate issues with old Android versions #697

Open douroussounnah opened 2 years ago

douroussounnah commented 2 years ago

Flutter Version

My version : 3.0.1

Lib Version

My version : 3.0.4+1

Platform (Android / iOS / web) + version

Platform : Android 6.0.1

Describe the bug

In old android version (like Android 6, 7, ...), there's an issue with the "Let's encrypt" certificate authority (more here https://letsencrypt.org/2020/12/21/extending-android-compatibility.html)

To get around with it, I do this in the main:

import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:flutter/material.dart';

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext? context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true; // here to ignore bad certificate issues
  }
}

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  HttpOverrides.global = MyHttpOverrides(); // and here in the init before the run
   runApp(GetMaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

And it's working like a charm for the entire app, except for the _assets_audioplayer pub which doesn't handle it when I use the player this way:

 try {
      final audioToPlay = Audio.network(url, metas: metas);
      await player.open(audioToPlay);
    } catch (error) {
      debugPrint("error catch " + error.toString());
    }
  }

Here is the error log:

E/ExoPlayerImplInternal(31718): Playback error
E/ExoPlayerImplInternal(31718):   com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:624)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:596)
E/ExoPlayerImplInternal(31718):       at android.os.Handler.dispatchMessage(Handler.java:98)
E/ExoPlayerImplInternal(31718):       at android.os.Looper.loop(Looper.java:158)
E/ExoPlayerImplInternal(31718):       at android.os.HandlerThread.run(HandlerThread.java:61)
E/ExoPlayerImplInternal(31718):   Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:358)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1014)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:409)
E/ExoPlayerImplInternal(31718):       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
E/ExoPlayerImplInternal(31718):       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
E/ExoPlayerImplInternal(31718):       at java.lang.Thread.run(Thread.java:818)
E/ExoPlayerImplInternal(31718):   Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.Connection.connect(Connection.java:1322)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:466)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:447)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:353)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:476)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:118)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
E/ExoPlayerImplInternal(31718):       at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:629)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:526)
E/ExoPlayerImplInternal(31718):       at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:352)
E/ExoPlayerImplInternal(31718):       ... 6 more
E/ExoPlayerImplInternal(31718):   Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:643)
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
E/ExoPlayerImplInternal(31718):       at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)
E/ExoPlayerImplInternal(31718):       ... 20 more
E/ExoPlayerImplInternal(31718):   Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
E/ExoPlayerImplInternal(31718):       ... 26 more
I/ExoPlayerImpl(31718): Release 7d050db [ExoPlayerLib/2.15.0] [kltelgt, SM-G900L, samsung, 23] [goog.exo.core]
I/MediaPlayer(31718): Need to enable context aware info
V/MediaPlayer-JNI(31718): native_setup
E/ExtMediaPlayer-JNI(31718): env->IsInstanceOf fails
E/MediaPlayer-JNI(31718): JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
E/ExtMediaPlayer-JNI(31718): env->IsInstanceOf fails
E/MediaPlayer-JNI(31718): JNIMediaPlayerFactory: bIsQCMediaPlayerPresent 0
V/MediaPlayer(31718): constructor
V/MediaPlayer(31718): setListener
V/MediaPlayer-JNI(31718): reset
V/MediaPlayer(31718): reset
D/RingtoneManager(31718): Can't get current user. return default user
W/MediaPlayer(31718): Couldn't open file on client side; trying server side: java.io.FileNotFoundException: No content provider: https://www.example.com/file.mp3
D/MediaPlayer(31718): setDataSource IOException | SecurityException happend : 
D/MediaPlayer(31718): java.io.FileNotFoundException: No content provider: https://www.example.com/file.mp3
D/MediaPlayer(31718):   at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1141)
D/MediaPlayer(31718):   at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:991)
D/MediaPlayer(31718):   at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:914)
D/MediaPlayer(31718):   at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1121)
D/MediaPlayer(31718):   at com.github.florent37.assets_audio_player.playerimplem.PlayerImplemMediaPlayer$open$2.invokeSuspend(PlayerImplemMediaPlayer.kt:129)
D/MediaPlayer(31718):   at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
D/MediaPlayer(31718):   at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
D/MediaPlayer(31718):   at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
D/MediaPlayer(31718):   at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
D/MediaPlayer(31718):   at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
D/MediaPlayer(31718):   at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
D/MediaPlayer(31718):   at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
D/MediaPlayer(31718):   at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
V/MediaPlayer(31718): setVideoSurfaceTexture
V/MediaPlayer(31718): prepare
D/MediaHTTPConnection(31718): setReadTimeOut =  30000ms
D/MediaHTTPConnection(31718): setReadTimeout with 30000ms
I/System.out(31718): (HTTPLog)-Static: isSBSettingEnabled false
I/System.out(31718): (HTTPLog)-Static: isSBSettingEnabled false
W/MediaHTTPConnection(31718): request failed with error => 0
D/MediaHTTPConnection(31718): setReadTimeout with 30000ms
I/System.out(31718): (HTTPLog)-Static: isSBSettingEnabled false
I/System.out(31718): (HTTPLog)-Static: isSBSettingEnabled false
W/MediaHTTPConnection(31718): request failed with error => 0
V/MediaPlayer(31718): message received msg=100, ext1=1, ext2=-1005
E/MediaPlayer(31718): error (1, -1005)
V/MediaPlayer(31718): signal application thread
V/MediaPlayer(31718): prepare complete - status=1
V/MediaPlayer-JNI(31718): release
V/MediaPlayer(31718): setListener
V/MediaPlayer(31718): disconnect
V/MediaPlayer(31718): destructor
V/MediaPlayer(31718): disconnect
W/System.err(31718): com.github.florent37.assets_audio_player.playerimplem.PlayerFinder$NoPlayerFoundException
W/System.err(31718):    at com.github.florent37.assets_audio_player.playerimplem.PlayerFinder._findWorkingPlayer(PlayerFinder.kt:70)
W/System.err(31718):    at com.github.florent37.assets_audio_player.playerimplem.PlayerFinder._findWorkingPlayer(PlayerFinder.kt:88)
W/System.err(31718):    at com.github.florent37.assets_audio_player.playerimplem.PlayerFinder.access$_findWorkingPlayer(PlayerFinder.kt:26)
W/System.err(31718):    at com.github.florent37.assets_audio_player.playerimplem.PlayerFinder$_findWorkingPlayer$1.invokeSuspend(PlayerFinder.kt)
W/System.err(31718):    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
W/System.err(31718):    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
W/System.err(31718):    at android.os.Handler.handleCallback(Handler.java:739)
W/System.err(31718):    at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err(31718):    at android.os.Looper.loop(Looper.java:158)
W/System.err(31718):    at android.app.ActivityThread.main(ActivityThread.java:7224)
W/System.err(31718):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err(31718):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
W/System.err(31718):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I/flutter (31718): PlatformException(OPEN, null, null, null)

For the moment, I download mp3 files to launch it, but some users have a bad connexion, or they don't understand why the app needs to download before playing instead of streaming the audio file

ShadyBoshra2012 commented 2 years ago

No updates ?!