关闭应用程序时停止 AsyncTask

Posted

技术标签:

【中文标题】关闭应用程序时停止 AsyncTask【英文标题】:Stop AsyncTask when app is closed 【发布时间】:2018-07-17 00:35:36 【问题描述】:

我正在尝试创建一个使用AsynTask 在后台播放音乐的广播流应用程序,我的应用程序还有一个使用WallpaperService 的将 Gif 设置为动态壁纸功能。

我的问题

    当我将一些 gif 设置为壁纸并尝试关闭应用程序时 从最近的任务或向左/向右滑动,我的应用程序仍然没有 播放音乐AsynTask 还在(doInBackground),我发现了一个问题 当AsynTask 结束时,音乐开始播放 即使我的应用程序已关闭,也可以在后台运行。

我想要什么

    当我将一些 gif 设置为壁纸时,当我关闭我的应用程序时,我想 停止AsynTask

主活动:

@Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        playerTask = new PlayerTask();
        playerTask.execute("URL_STREAM");



@Override
    protected void onDestroy() 
        super.onDestroy();
        MApplication.sBus.post(PlaybackEvent.CLOSE);
        try 
            MApplication.sBus.unregister(this);
         catch (Exception e) 
            e.printStackTrace();
        
    

   @Subscribe
    public void handlePlaybackEvent(PlaybackEvent event) 
        switch (event) 
            case PAUSE:
                if (mediaPlayer.isPlaying()) 
                    mediaPlayer.pause();
                    MusicButton.setChecked(true);
                
                break;
            case PLAY:
                if (!mediaPlayer.isPlaying()) 
                    mediaPlayer.start();
                    MusicButton.setChecked(false);
                
                break;
            case CLOSE:
                MApplication.sBus.post(PlaybackEvent.PAUSE);
                NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                assert n != null;
                n.cancelAll();
                playerTask.cancel(true);

    

 @SuppressLint("StaticFieldLeak")
    public class PlayerTask extends AsyncTask<String, Void, Boolean> 
        ProgressBar loadingRL = findViewById(R.id.progressBar);

        @Override
        protected void onPreExecute() 
            super.onPreExecute();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) 
                AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
                mediaPlayer.setAudioAttributes(attribs);

             else 
                mediaPlayer.setAudiostreamType(AudioManager.STREAM_MUSIC);
            
            loadingRL.setVisibility(View.VISIBLE);
            beforradio.start();
        

        @Override
        protected Boolean doInBackground(String... strings) 
             if(!isCancelled())
            try 
                mediaPlayer.setDataSource(strings[0]);
                mediaPlayer.prepare();
                prepared = true;
             catch (IOException e) 
                e.printStackTrace();
             catch (IllegalArgumentException e) 
                e.printStackTrace();
             catch (IllegalStateException e) 
                e.printStackTrace();
            
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() 
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) 
                    mediaPlayer.start();

                
            );
        
            return prepared;
        

        @Override
        protected void onPostExecute(Boolean aBoolean) 
            super.onPostExecute(aBoolean);
            MusicButton.setVisibility(View.VISIBLE);
            MusicButton.setChecked(true);
            loadingRL.setVisibility(View.GONE);
             /*get details : */
            Uri uri = Uri.parse(JsonData.NightWavePlazaRadioStream);
            OnNewMetadataListener ilistener = new OnNewMetadataListener() 
                @Override
                public void onNewHeaders(String stringUri, List<String> name, List<String> desc, List<String> br, List<String> genre, List<String> info) 
                

                @Override
                public void onNewStreamTitle(String stringUri, String streamTitle) 
                    Animation a = AnimationUtils.loadAnimation(MainActivity.this, R.anim.textanim);
                    a.reset();
                    songinfo.setText("Song : " + streamTitle);
                    createNotification(getApplicationContext(), streamTitle, "notificationchannel", notificationManager);

                
            ;
            AudiostreamMetadataManager.getInstance()
                    .setUri(uri)
                    .setOnNewMetadataListener(ilistener)
                    .setUserAgent(UserAgent.WINDOWS_MEDIA_PLAYER)
                    .start();
            Rlsong.setVisibility(View.VISIBLE);
        
    

【问题讨论】:

我也处理过这些问题,并通过使用服务而不是 asynctask 找到了自己的解决方案。 @statosdotcom 非常感谢您的评论,请您给我一些关于使用service 流式广播的教程或文档 AsyncTask 专为需要定期更新 UI 的短任务而构建。您应该寻找其他线程解决方案,例如 HandlerThread 或 IntentService。 【参考方案1】:

删除异步任务。由于您使用 asynctask 只是为了显示进度条。您可以在 onCreate() 中设置进度条 VISIBLE,然后在 mediaPlayer.setOnPreparedListener()

中将其设置为 GONE

【讨论】:

【参考方案2】:

没有“停止”异步任务。您在任务上调用取消,但在您的 doInBackground 代码中,您应该检查您的任务是否被取消,如果是,则中断。

参考这里

https://***.com/a/6053943/599346

【讨论】:

非常感谢您的评论,但仍然无法正常工作,请查看我的新更新帖子 您不需要异步任务来播放音乐,因此您通过添加异步任务来做不必要的工作。试图阻止它不会为你做任何事情。你应该使用prepareAsync() 然后你就不需要它了 来自文档的For streams, you should call prepareAsync(), which returns immediately, rather than blocking until enough data has been buffered. developer.android.com/reference/android/media/… 实际上我使用asynctask 只是为了在尚未播放音乐时显示progressbar。所以我在onPreExecute 中显示progressbar 并将其隐藏在onPostExecute 请如果我可以使用其他东西请告诉我【参考方案3】:

您可以在 AsyncTasks doInBackground() 函数中调用 cancel(true)。为此,您可以在 AsyncTask 中保留一个布尔标志,并检查它是否在 doInBackgroundcancel(true) 中被取消。

【讨论】:

非常感谢您的评论,但仍然无效

以上是关于关闭应用程序时停止 AsyncTask的主要内容,如果未能解决你的问题,请参考以下文章

停止 AsyncTask 会导致服务结束

应用程序关闭后后台进程(AsyncTask)仍在运行

如何在切换片段时停止 AsyncTask?

安卓停止下载

运行并行 AsyncTask

即使 Activity 已销毁,AsyncTask 也不会停止