Flutter - AudioService уведомление не появляется - PullRequest
0 голосов
/ 27 апреля 2020

Опишите ошибку

Когда я полностью закрываю приложение, уведомление не появляется, но звук продолжает играть в фоновом режиме.

Сообщения об ошибках

[        ] 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;
  }
}

...