【问题标题】:Flutter Android Platform EventChannel not stopping when back button press destroy application当后退按钮按下销毁应用程序时,Flutter Android Platform EventChannel 不会停止
【发布时间】:2020-01-06 11:56:27
【问题描述】:

我正在尝试创建一个颤振应用程序,它使用我正在创建的本机 android 插件的后台服务:一个简单的计数器应用程序,它每 5 秒通过 EventChannel 发送一次计数值。

当我按下后退按钮并且应用程序被销毁时,服务仍在运行(这就是我想要做的)。但是当我再次打开应用程序时,事件接收器不再将数据发送到新的颤动视图。 我认为事件通道插件没有停止。

【问题讨论】:

    标签: android flutter


    【解决方案1】:

    当我们按下后退按钮时,我们的应用程序会被破坏。因此 EventSink(位于我们的 Native Code 中)无法将数据发送到我们的 Flutter 端。

    您可以在控制台中看到此消息: 尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。无法发送。频道:com.example.timestamp_saver 响应 ID:0 这里 com.example.timestamp_saver 是事件通道名称。

    因此,当您按下返回按钮后再次打开应用程序时,要再次开始收听事件,您需要再次开始收听该频道,并且您可以在您的应用程序状态为“恢复”时执行此操作或 按下某个按钮。

    要根据应用状态执行此操作,请按照以下步骤操作 -

    1. 所以首先使用 WidgetsBindingObserver

      实现您的 Stateful 小部件
    2. 然后在 initState() 方法和 dispose() 中

        @override
        void initState() {
         super.initState();
         WidgetsBinding.instance.addObserver(this);
         }
      
        @override
        void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
        }
      
    3. 现在覆盖 didChangeAppLifecycleState(AppLifecycleState state) 并在 Flutter 中获取应用程序的当前状态。 您也可以在按下一些刷新按钮时开始收听事件接收器

      @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
       print('state = $state');
       if(state == AppLifecycleState.resumed)
         {
           //start listening to the Event Sink again
           listenData();
         }
       }
      

    这里是listenData()方法-

    void listenData() async {
     if(Platform.isAndroid){
            var eventChannel = EventChannel("com.example.timestamp_saver");
            eventChannel.receiveBroadcastStream("Just Listen").listen((event) async {
             debugPrint("Inside Listen Data");
             debugPrint(event);
          });
         }
       } 
    
    1. 这是我的示例代码,我每 5 秒更新一次带有时间戳的列表。在这种情况下,当用户按下返回按钮时,侦听器将使用 EventSink 发出的数据进行更新,因此在这种情况下,我正在保存数据到数据库,当用户再次打开应用程序时,我正盯着同一个频道再次收听。

    main.dart

    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:timestamp_saver/db/db_helper.dart';
    import 'package:timestamp_saver/db/timestamp_model.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(),
        );
      }
    }
    
     class MyHomePage extends StatefulWidget {
       @override
       _MyHomePageState createState() => _MyHomePageState();
     }
    
     class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
       DBHelper _dbHelper;
       List<TimeStampModel> timeStampList;
    
       @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
        _dbHelper = DBHelper();
      }
    
       @override
       void dispose() {
         WidgetsBinding.instance.removeObserver(this);
         super.dispose();
       }
     
    
       @override
       Widget build(BuildContext context) {
         return Scaffold(
             appBar: AppBar(),
             body: Container(
               child: Column(
                 children: [
                   RaisedButton(
                     onPressed: (){startServiceAndReceiveUpdatea();},
                     child: Text("Start"),
                   ),
                   SizedBox(height: 20,),
                   RaisedButton(
                     onPressed: (){listenData();},
                     child: Text("Listen"),
                   ),
                   Expanded(
                       child: FutureBuilder<List<TimeStampModel>>(
                           future: _dbHelper.getTimeStampModels(),
                           builder: (context, snapshot) {
                              if(snapshot.hasData)
                                {
                                  timeStampList = snapshot.data;
                                  return ListView.builder(
                                       itemCount: timeStampList.length,
                                      itemBuilder: (context, index) => ListTile(
                                        title: Text(timeStampList[index].timestamp),
                                      ),
                                  );
                                }else if(snapshot.hasError)
                                return Center(child: Text("Error"),);
                              else
                                return Center(child: CircularProgressIndicator(),);
                           },
                       )
                   )
                 ],
               ),
             )
         );
       }
    
      
    
       void startServiceAndReceiveUpdatea() async
       {
         if(Platform.isAndroid){
           var eventChannel = EventChannel("com.example.timestamp_saver");
           eventChannel.receiveBroadcastStream("startService").listen((event) async {
             debugPrint("Listner called in dart");
             debugPrint(event);
             TimeStampModel timeStamp = TimeStampModel(id: null,timestamp: event);
             setState(() {
    
             });
        });
         }
       }
    
       void listenData() async
       {
         if(Platform.isAndroid){
           var eventChannel = EventChannel("com.example.timestamp_saver");
           eventChannel.receiveBroadcastStream("Just Listen").listen((event) async {
             debugPrint("Inside Listen Data");
             debugPrint(event);
             TimeStampModel timeStamp = TimeStampModel(id: null,timestamp: event);
             setState(() {
    
             });
    
           });
         }
       }
    
    
    }
    

    MainActivity.java

    package com.example.timestamp_saver;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.lifecycle.Observer;
    import java.nio.ByteBuffer;
    import io.flutter.embedding.android.FlutterActivity;
    import io.flutter.embedding.engine.FlutterEngine;
    import io.flutter.plugin.common.BinaryMessenger;
    import io.flutter.plugin.common.EventChannel;
    import io.flutter.plugin.common.MethodCall;
    import io.flutter.plugin.common.MethodChannel;
    import io.flutter.plugins.GeneratedPluginRegistrant;
    
    public class MainActivity extends FlutterActivity {
    
        private Intent forService;
        static EventChannel.EventSink events;
        @Override
        public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
            super.configureFlutterEngine(flutterEngine);
            GeneratedPluginRegistrant.registerWith(flutterEngine);
            forService = new Intent(MainActivity.this,MyService.class);
     new EventChannel(flutterEngine.getDartExecutor(),"com.example.timestamp_saver").setStreamHandler(new EventChannel.StreamHandler() {
                @Override
                public void onListen(Object arguments, EventChannel.EventSink events) {
                    MainActivity.events = events;
                    System.out.println("On Listen in Activity called");
                         if(arguments.equals("startService"))
                         {
                             System.out.println("if");
                             startService();
                        }else if(arguments.equals("Just Listen")){
                             System.out.println("Just Listen");
                         }
                }
    
                @Override
                public void onCancel(Object arguments) {
    
                }
            });
    
        }
    
        private void startService(){
           if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                startForegroundService(forService);
            } else {
                startService(forService);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
    }
    

    MyService.java

    package com.example.timestamp_saver;
    import android.app.NotificationManager;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.PowerManager;
    import android.util.Log;
    
    import androidx.annotation.Nullable;
    import androidx.core.app.NotificationCompat;
    import androidx.lifecycle.LifecycleService;
    import androidx.lifecycle.LiveData;
    import androidx.lifecycle.MutableLiveData;
    import androidx.lifecycle.Observer;
    
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.List;
    import java.util.Timer;
    import java.util.TimerTask;
    
    import io.flutter.plugin.common.EventChannel;
    
    public class MyService extends LifecycleService {
    
        MutableLiveData<String> stringMutableLiveData = new MutableLiveData<>();
        int timerCount = 0;
        private PowerManager.WakeLock wl;
        private DBManager dbManager;
        @Override
        public void onCreate() {
            super.onCreate();
            dbManager = new DBManager(this);
            dbManager.open();
            //Creating a partial wake lock,Because if we don't create wake lock then CPU Will stop working when
            //screen will be locked,which will cause timer to work inconsistently.
    
            //This solution can be modified more.For example Acquire the Wake Lock when user locks the screen and release
            //it when phone gets unlock.This can be achieved using Brodcast Receiver.
            //Because Wake Lock consumes much power,so use it properly.
            PowerManager pm = (PowerManager)  getSystemService(Context.POWER_SERVICE);
            wl =  pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"a:waketag");
            wl.acquire();
            //stringMutableLiveData = new MutableLiveData<>();
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"messages")
                        .setContentText("This is running in Background")
                        .setContentTitle("Flutter Background")
                        .setSmallIcon(R.drawable.launch_background);
    
                startForeground(101,builder.build());
            }
    
            timerLogic();
    
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return super.onStartCommand(intent, flags, startId);
        }
    
        void timerLogic()
        {
            stringMutableLiveData.observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    System.out.println("On Changed");
                    if(MainActivity.events != null) {
                        dbManager.insert(s);
                        MainActivity.events.success(s);
                    }
                    else
                        System.out.println("Event is null");
                }
            });
             
    
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    timerCount++;
                    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    Calendar cal = Calendar.getInstance();
                    String timerString = dateFormat.format(cal.getTime());
                    System.out.println(timerString+": "+timerCount);
                    stringMutableLiveData.postValue(timerString);
    
                }
            },1000,5000);
        }
    
        @Override
        public void onDestroy() {
            //Remember to relese wake lock
            wl.release();
            super.onDestroy();
    
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    
     
    

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多