Why event channel disables when an asyncTask will execute? In flutter android

207 views Asked by At

I have written a native code for flutter that will download file from given url. Everything works fine and file will download and store perfectly. The problem is that when i want to retrieve downloaded percentage(download progress). I used event channel. It will work until I tap download button. After I tap download button nothing will retrieve from event channel until the download is finish. The download is a class that implement asyncTask. Even the onProgressUpdate method in asyncTask is unavailable until the download is complete. looks like the only and only one place that I can see progress and that is inside the doInBackGround method. I see the percentage by logs. I used event.success(percentage) inside while loop to retrieve percentage but got an error that said:

Methods marked with @UiThread must be executed on the main thread

Then used a Handler with mainloop but nothing happened.

and this is where i'm stuck and don't know what to do.

I appreciate any help.

Here is the codes:

Android Side: (MainActivity)

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "bot/native_services";
    private static final String STREAM = "bot/native_services/stream";
    private Download download = new Download();
    static int percentage = 0;
    static boolean dlStart = false;
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        EventChannel.StreamHandler handler = new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                Log.i("MyTestApp","Registered");
                Handler h = new Handler(Looper.getMainLooper());
                TimerTask timerTask = new TimerTask() {
                    @Override
                    public void run() {
                            h.post(new Runnable() {
                                @Override
                                public void run() {
                                    events.success(percentage);
                                    if (percentage == 100) {
                                        events.endOfStream();
                                    }
                                }
                            });
                    }
                };
            Timer timer = new Timer();
            timer.schedule(timerTask,0,100);
            if (percentage == 100) {
                timer.cancel();
            }


            }

            @Override
            public void onCancel(Object arguments) {

            }
        };
        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),STREAM).setStreamHandler(handler);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),CHANNEL).setMethodCallHandler((call, result) -> {
            if (call.method.equals("openUrl")) {
                openUrl(call.argument("url"), result);
            }else if(call.method.equals("checkNetwork")) {
                    checkNetwork(result);
            }else if(call.method.equals("downloadFromUrl")) {
                downloadFromUrl(call.argument("url"), result);
            }
        });
    }
public void downloadFromUrl(String url,MethodChannel.Result result) {
        download.execute(url);
        try {
            HashMap<String,String> res = download.get();
            Log.i("MyTestApp",res.get("status"));
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Android side: (Download class)

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import javax.net.ssl.HttpsURLConnection;

import io.flutter.plugin.common.EventChannel;

class Download extends AsyncTask<String,Integer, HashMap<String,String>>{

    String path = "";

    @Override
    protected HashMap<String,String> doInBackground(String... strings) {
        int count = 0;
        try {
            URL url = new URL(strings[0]);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            int length = connection.getContentLength();
            Log.i("MyTestApp",String.valueOf(length));
            File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/apk");

            if (!folder.exists()) {
                boolean res = folder.mkdirs();
            }

            String appName = "bot.apk";
            File apk = new File(folder,appName);
            path = apk.getPath();
            FileOutputStream fos = new FileOutputStream(apk);
            InputStream is = connection.getInputStream();
            byte[] buffer = new byte[1024];
            long totalReaded = 0l;
            while ((count = is.read(buffer)) != -1) {

                fos.write(buffer, 0, count);
                totalReaded += count;
                MainActivity.percentage = (int) (totalReaded * 100) / length;
                Log.i("Value",String.valueOf( MainActivity.percentage));


            }

            fos.flush();
            fos.close();
            is.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        HashMap<String,String> result = new <String,String>HashMap();
        result.put("status","OK");
        result.put("path",path);
        return result;
    }

    @Override
    protected void onPostExecute(HashMap<String,String> s) {
        super.onPostExecute(s);


    }
}

Flutter side:

class CheckForUpdatesState extends State<CheckForUpdates> {
  static const streamChannel =
      EventChannel('bot/native_services/stream');
  Stream<int> percentage = Stream.empty();

  checkUpdates() async {
    String url = 'App link';
    Map data = await NativeService.downloadFromUrl(url);
  }


  Stream<int> getPercentage() {
    percentage = streamChannel.receiveBroadcastStream().map<int>((event) {
      print(event);
      return event;
    });
    return percentage;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Checking for updates'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Looking for latest version'),
            ],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [Text('Version 1.0.0')],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextButton(
                  onPressed: checkUpdates,
                  child: Text(
                    'Check for updates',
                    style: TextStyle(color: Colors.green),
                  ))
            ],
          ),
          StreamBuilder(
            initialData: percentage,
            stream: getPercentage(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                print('snap shot data is: ${snapshot.data}');
                return Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [Text('percentage:${snapshot.data}')],
                );
              } else {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [Text('percentage:${snapshot.error}')],
                );
              }
            },
          )
        ],
      ),
    );
  }
}
0

There are 0 answers