Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/191.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当重复处理程序达到某个条件时,如何结束它?_Java_Android_Audio_Handler - Fatal编程技术网

Java 当重复处理程序达到某个条件时,如何结束它?

Java 当重复处理程序达到某个条件时,如何结束它?,java,android,audio,handler,Java,Android,Audio,Handler,我正在制作一个应用程序,在设备的存储器中播放音频文件,我有一个搜索栏,每秒检查音频文件的进度(播放了多长时间),并相应地更新搜索栏 音频通过在前台运行的服务播放,并显示音频正在播放的通知 当音频结束时,我注意到处理程序仍在循环中,我想在音频结束后结束处理程序 我目前试图做的是从处理程序运行的runnable内部结束处理程序,因为我不知道如何结束它 主活动,其中我处理ListView中的OnClick,您可以在其中选择音频文件并处理seekbar更新 import androidx.appcomp

我正在制作一个应用程序,在设备的存储器中播放音频文件,我有一个搜索栏,每秒检查音频文件的进度(播放了多长时间),并相应地更新搜索栏

音频通过在前台运行的服务播放,并显示音频正在播放的通知

当音频结束时,我注意到处理程序仍在循环中,我想在音频结束后结束处理程序

我目前试图做的是从处理程序运行的runnable内部结束处理程序,因为我不知道如何结束它

主活动,其中我处理ListView中的OnClick,您可以在其中选择音频文件并处理seekbar更新

import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    SeekBar musicProgBar;
    Handler progBarHandler = null;
    Runnable r = null;
    private MP3Service.MyBinder myService = null;
    TextView progressText = null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        musicProgBar = findViewById(R.id.musicProgressBar);
        progressText = findViewById(R.id.progressText);
        final ListView lv = (ListView) findViewById(R.id.musicList);
        Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                null,
                MediaStore.Audio.Media.IS_MUSIC + "!= 0",
                null,
                null);

        progBarHandler = new Handler();
        final int progBarDelay = 1000; // delay for the handler, making it repeat itself only every 1000 miliseconds (1 second)

        lv.setAdapter(new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1,
                cursor,
                new String[] { MediaStore.Audio.Media.DATA},
                new int[] { android.R.id.text1 }));

        Intent tempIntent = new Intent(this, MP3Service.class);
        startService(tempIntent);
        bindService(tempIntent, serviceConnection, 0);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> myAdapter,
                                    View myView,
                                    int myItemInt,
                                    long myLong) {
                Cursor c = (Cursor) lv.getItemAtPosition(myItemInt);
                String uri = c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA));
                Log.d("g53mdp", uri);

                if (myService.fetchPlayerState() != MP3Player.MP3PlayerState.STOPPED)
                    myService.stopMusic();

                myService.loadMusic(uri);
                myService.playMusic();
                musicProgBar.setMax(myService.fetchDuration()); // set the max value of the seekbar to be the duration of the song
                r = new Runnable()
                {
                    @Override
                    public void run()
                    {
                        int tempInt = myService.fetchProgress();
                        Log.d("progress ticking", tempInt + " " + musicProgBar.getProgress());
                        musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
                        long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
                        long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
                        if (seconds >= 60)
                            seconds = seconds - 60;
                        String tempString = minutes + ":" + seconds;
                        progressText.setText(tempString);
                        progBarHandler.postDelayed(this, progBarDelay);
                        if (musicProgBar.getProgress() == myService.fetchDuration())
                            progBarHandler.removeCallbacks(this);
                    }
                };
                progBarHandler.post(r);
            }});
    }

    private ServiceConnection serviceConnection = new ServiceConnection()
    {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            myService = (MP3Service.MyBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            myService = null;
        }
    };

    public void playButClicked(View view)
    {
        myService.playMusic();
    }

    public void pauseButClicked(View view)
    {
        myService.pauseMusic();
    }

    public void stopButClicked(View view)
    {
        myService.stopMusic();
    }

    @Override
    protected void onDestroy()
    {
        unbindService(serviceConnection);
        progBarHandler.removeCallbacks(r);
        super.onDestroy();
    }
}
处理音乐播放器和播放音乐的服务

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

public class MP3Service extends Service
{
    public static MP3Service instance = null; // implementing singleton by instantiating a reference to the instance
    private final String SERVICE_ID = "100"; // id for the service
    public static boolean isRunning = false; //
    NotificationManager notificationManager = null;
    int notificationID = 001;
    private final IBinder binder = new MyBinder();
    MP3Player mainPlayer;

    @Nullable
    @Override
    public IBinder onBind(Intent intent)
    {
        return binder;
    }

    @Override
    public void onRebind(Intent intent)
    {
        // TODO: implement Rebind for screen orientation change
    }

    @Override
    public void onCreate()
    {
        instance = this;
        isRunning = true;
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mainPlayer = new MP3Player();
        super.onCreate();
        Handler handler = new Handler();
    }

    @Override
    public void onDestroy()
    {
        isRunning = false;
        instance = null;
        notificationManager.cancel(notificationID);
    }

    public void createNotification() 
    {
        CharSequence name = "MP3 Notification";
        String description = "Displays a notification when a song is playing";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(SERVICE_ID, name, importance);
        channel.setDescription(description);
        notificationManager.createNotificationChannel(channel);

        Intent intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        // when the user clicks the notification, this will bring them to the activity
        PendingIntent navToMainActivity = PendingIntent.getActivity(this, 0, intent, 0);

        // sets up the info and details for the notification
        final NotificationCompat.Builder mNotification = new NotificationCompat.Builder(this, SERVICE_ID)
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("MP3 Player")
                .setContentText("Playing music")
                .setContentIntent(navToMainActivity)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);

        startForeground(notificationID, mNotification.build());
    }

    public void removeNotification()
    {
        stopForeground(false);
        notificationManager.cancelAll();
    }

    public class MyBinder extends Binder
    {
        public void loadMusic(String filePath)
        {
            mainPlayer.load(filePath);
        }

        public void playMusic()
        {
            mainPlayer.play();
            createNotification();
        }

        public void pauseMusic()
        {
            mainPlayer.pause();
            removeNotification();
        }

        public void stopMusic()
        {
            mainPlayer.stop();
            removeNotification();
        }

        public MP3Player.MP3PlayerState fetchPlayerState()
        {
            return mainPlayer.getState();
        }

        public int fetchDuration()
        {
            return mainPlayer.getDuration();
        }

        public int fetchProgress()
        {
            return mainPlayer.getProgress();
        }
    }
}
提前感谢您的帮助,如果需要,我很乐意提供更多信息


编辑:将runnable之外的progBarHandler.postDelay()更改为简单的progBarHandler.post()

我认为无法停止处理程序的唯一原因是不断调用
progBarHandler.postDelay(这是progBarDelay),您需要检查它为什么仍在运行。

通过向runnable引入一种不同类型的if语句,使其正常工作,如下所示

Runnable r = new Runnable()
{
    @Override
    public void run()
    {
        if (musicProgBar.getProgress() == myService.fetchProgress() && myService.fetchProgress() != 0)
            Log.d("audio", "over");
        else {
            int tempInt = myService.fetchProgress();
            long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
            long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
            if (seconds >= 60)
                seconds = seconds % 60;
            String tempString = minutes + ":" + seconds;
            progressText.setText(tempString);
            musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
            progBarHandler.postDelayed(this, progBarDelay);
        }
    }
};

出于某种原因,使用.fetchDuration()和.fetchProgress()似乎永远不会相互平衡,因此更改if语句是有效的。

是的,我对它进行了更多的处理,基本上对它进行了更改,使runnable中的代码只有在满足条件时才能运行
runnable r=new runnable(){@Override public void run(){if(musicProgBar.getProgress()==myService.fetchProgress()&&myService.fetchProgress()!=0)Log.d(“音频”,“结束”);否则{…progBarHandler.postDelayed(this,progBarDelay}
幸运的是,这使它工作了
Runnable r = new Runnable()
{
    @Override
    public void run()
    {
        if (musicProgBar.getProgress() == myService.fetchProgress() && myService.fetchProgress() != 0)
            Log.d("audio", "over");
        else {
            int tempInt = myService.fetchProgress();
            long minutes = TimeUnit.MILLISECONDS.toMinutes(tempInt);
            long seconds = TimeUnit.MILLISECONDS.toSeconds(tempInt);
            if (seconds >= 60)
                seconds = seconds % 60;
            String tempString = minutes + ":" + seconds;
            progressText.setText(tempString);
            musicProgBar.setProgress(tempInt); // sets the current progress of the seekbar to be the progress of the song
            progBarHandler.postDelayed(this, progBarDelay);
        }
    }
};