Опишите ошибку
Когда я полностью закрываю приложение, уведомление не появляется, но звук продолжает играть в фоновом режиме.
Сообщения об ошибках
[ ] E/ActivityThread( 4106): Activity example.com.base.MainActivity has leaked ServiceConnection android.media.browse.MediaBrowser$MediaServiceConnection@f5f22bd that was originally bound here
[ ] E/ActivityThread( 4106): android.app.ServiceConnectionLeaked: Activity example.com.base.MainActivity has leaked ServiceConnection android.media.browse.MediaBrowser$MediaServiceConnection@f5f22bd that was originally bound here
[ ] E/ActivityThread( 4106): at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1618)
[ ] E/ActivityThread( 4106): at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:1510)
[ ] E/ActivityThread( 4106): at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1669)
[ ] E/ActivityThread( 4106): at android.app.ContextImpl.bindService(ContextImpl.java:1622)
[ ] E/ActivityThread( 4106): at android.content.ContextWrapper.bindService(ContextWrapper.java:708)
[ ] E/ActivityThread( 4106): at android.media.browse.MediaBrowser$1.run(MediaBrowser.java:187)
[ ] E/ActivityThread( 4106): at android.os.Handler.handleCallback(Handler.java:873)
[ ] E/ActivityThread( 4106): at android.os.Handler.dispatchMessage(Handler.java:99)
[ ] E/ActivityThread( 4106): at android.os.Looper.loop(Looper.java:201)
[ ] E/ActivityThread( 4106): at android.app.ActivityThread.main(ActivityThread.java:6810)
[ ] E/ActivityThread( 4106): at java.lang.reflect.Method.invoke(Native Method)
[ ] E/ActivityThread( 4106): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
[ ] E/ActivityThread( 4106): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
[ +13 ms] W/cr_ChildProcessConn( 4106): onServiceDisconnected (crash or killed by oom): pid=4317 bindings:W S state:3 counts:0,0,0,1,
Среда выполнения (при необходимости заполните следующую информацию):
- Устройство: [например, Xioami Mi Note 3]
- ОС: [например, Android 9.0.0]
Версия Flutter SDK
[√] Flutter (Channel stable, v1.12.13+hotfix.9, on Microsoft Windows [Version 10.0.18362.778], locale tr-TR)
• Flutter version 1.12.13+hotfix.9 at D:\flutter
• Framework revision f139b11009 (4 weeks ago), 2020-03-30 13:57:30 -0700
• Engine revision af51afceb8
• Dart version 2.7.2
Дополнительный контекст MainActivity. java
package example.com.base;
import android.content.Context;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
@Override
public FlutterEngine provideFlutterEngine(Context context) {
// Instantiate a FlutterEngine.
FlutterEngine flutterEngine = new FlutterEngine(context.getApplicationContext());
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
return flutterEngine;
}
}
Приложение. java
package example.com.base;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
public class Application extends FlutterApplication implements PluginRegistrantCallback {
@Override
public void onCreate() {
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
}
@Override
public void registerWith(PluginRegistry registry) {
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
}
}
AndroidManifest. xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="example.com.base">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name=".Application"
android:label="Radio"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<service android:name="com.ryanheise.audioservice.AudioService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value=""/>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
media_player_service.dart
import 'package:audio_service/audio_service.dart';
import 'package:base/core/services/ad_service.dart';
import 'package:base/core/sharedpref/shared_preference_helper.dart';
import 'package:base/core/utils/audio_player_task.dart';
import 'package:base/data/models/radio_station.dart';
import 'package:base/injection_container.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
class MediaPlayerService {
Future<void> start(RadioStation radio, {List<RadioStation> queue = const []}) async {
if (await _run()) {
if (queue.length > 0) {
await Future.forEach(queue, (radio) async => await AudioService.customAction('addQueue', radio.toJson()));
}
await sl<SharedPreferenceHelper>().incrementRadioListeningCount();
if (await sl<SharedPreferenceHelper>().getRadioListeningCount() % int.parse(sl<DotEnv>().env['INTERSTITIAL_SHOW_EVERY_X_LISTENING'] ?? "1") == 0 &&
(sl<DotEnv>().env["SHOW_ADMOB_INTERSTITIAL"] ?? "0") == "1") {
sl<AdService>().buildInterstitialAd();
}
//set media item
await AudioService.customAction('startMedia', radio.toJson());
}
}
Future<void> updateItem(RadioStation radio) async {
if (!AudioService.connected) {
//connect service
await AudioService.connect();
}
if (AudioService.running) {
await AudioService.customAction('updateMedia', radio.toJson());
}
}
Future<bool> _run() async {
if (!AudioService.connected) {
//connect service
await AudioService.connect();
}
//if not connected, start new service
if (!AudioService.running) {
await AudioService.start(
backgroundTaskEntrypoint: audioPlayerTaskEntryPoint,
androidNotificationChannelName: sl<DotEnv>().env['APP_NAME'],
notificationColor: 0xFF2196f3,
androidNotificationIcon: 'mipmap/ic_launcher',
enableQueue: true,
androidNotificationOngoing: true
);
}
do {
if (AudioService.running) {
return true;
}
} while (!AudioService.running);
return false;
}
}