0

I am currently learning how to programm apps on Android. Heres my attempt:

    package com.example.android.miwok;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import static android.view.View.GONE;

/**
 * Created by Lukas on 14.02.2018.
 */

public class WordAdapter extends ArrayAdapter<Word> {
    public static Timer timer;
    Activity act;
    MediaPlayer player;

    public WordAdapter(Activity context, ArrayList<Word> list) {
        super(context, 0, list);
        this.act = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View listItemView = convertView;
        if (listItemView == null) {
            listItemView = LayoutInflater.from(getContext()).inflate(R.layout.listitem_normal, parent, false);
        }
        Word current_word = getItem(position);
        final TimerTask progresstask;
        final AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View dialogview = inflater.inflate(R.layout.player_dialog, null);
        final ProgressBar progress = dialogview.findViewById(R.id.progress);
        final SeekBar volseek = dialogview.findViewById(R.id.volumeseek);
        TextView MiwokView = listItemView.findViewById(R.id.miwok_word);
        TextView DefaultView = listItemView.findViewById(R.id.default_word);
        final TextView TimeGone = dialogview.findViewById(R.id.time_gone_player);
        final TextView TimeTotal = dialogview.findViewById(R.id.time_total);
        final ImageView icon = listItemView.findViewById(R.id.item_image);
        final ImageButton playbutton = listItemView.findViewById(R.id.playbutton);
        final ImageButton volup = dialogview.findViewById(R.id.vol_up);
        final ImageButton voldown = dialogview.findViewById(R.id.vol_down);
        MiwokView.setText(current_word.getMiwokTranslation());
        DefaultView.setText(current_word.getDefaultTranslation());
        if (current_word.getImageRes() == 0) {
            icon.setVisibility(GONE);
        } else {
            icon.setImageResource(current_word.getImageRes());
        }
        volup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) + 1, 0);
            }
        });
        voldown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) - 1, 0);
            }
        });

        dialog.setTitle(current_word.getMiwokTranslation());
        dialog.setMessage(current_word.getDefaultTranslation());
        dialog.setView(dialogview);
        progresstask = new TimerTask() {
            @Override
            public void run() {
                act.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        TimeGone.setText(Integer.toString(player.getCurrentPosition()));
                    }
                });
                progress.setProgress(player.getCurrentPosition());
            }
        };
        final AlertDialog crdialog = dialog.create();
        crdialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                player.stop();
                timer.cancel();
                timer.purge();
                timer = null;
                Log.i("Miwok/Timer Task", "Timer cancelled");
                playbutton.setImageResource(android.R.drawable.ic_media_play);
                Log.d("onDismiss", "onDismiss: executed");
            }
        });
        playbutton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                player = MediaPlayer.create(getContext(), R.raw.unison_aperture_ncs_release);
                player.start();
                playbutton.setImageResource(android.R.drawable.ic_media_pause);
                crdialog.show();
                progress.setMax(player.getDuration());
                TimeTotal.setText(Integer.toString(player.getDuration() / 60));
                timer = new Timer();
                timer.scheduleAtFixedRate(progresstask, 0, 500);
                player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mediaPlayer) {
                        crdialog.dismiss();
                        playbutton.setImageResource(android.R.drawable.ic_media_play);
                    }
                });
            }
        });
        return listItemView;

    }
}

As you can see, if you click the ImageButton a dialog with a progress will show up and a new instance of timer will be created. BUT iam getting this Error:

04-02 21:47:36.602 27524-27524/com.example.android.miwok E/AndroidRuntime: FATAL EXCEPTION: main
                                                                           Process: com.example.android.miwok, PID: 27524
                                                                           java.lang.IllegalStateException: Task already scheduled or cancelled
                                                                               at java.util.Timer.sched(Timer.java:401)
                                                                               at java.util.Timer.scheduleAtFixedRate(Timer.java:328)
                                                                               at com.example.android.miwok.WordAdapter$5.onClick(WordAdapter.java:115)
                                                                               at android.view.View.performClick(View.java:6213)
                                                                               at android.view.View$PerformClick.run(View.java:23645)
                                                                               at android.os.Handler.handleCallback(Handler.java:751)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:154)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

I would be happy if someone could explain why this error occurs and how i can fix it. Thank you very much!

laim2003
  • 299
  • 4
  • 19
  • Possible duplicate of [Java Timer](https://stackoverflow.com/questions/1041675/java-timer) – d.j.brown Apr 02 '18 at 20:07
  • In short, you need to make a new `TimerTask` as `Timer` will reject your already used `TimerTask` as its internal state is incorrect. In your case, move the declaration and instantiation of your `TimerTask` into the `playbutton`'s `OnClickListener`. – d.j.brown Apr 02 '18 at 20:09
  • @d.j.brown Thank you. i found out that i need to create a new TimerTask, but i just created a new Timer as you saw. But thank you! – laim2003 Apr 02 '18 at 20:26

2 Answers2

0

In short that is so because you are using same TimerTask for multiple timers

Inside Timer class there is a check:

if (task.state != TimerTask.VIRGIN)
   throw new IllegalStateException("Task already scheduled or cancelled");

So if TimerTask is already used you cannot use it in another Timer.

In other words you have to create new TimerTask for new Timer or limit yourself with only one pair of them

Andrey Danilov
  • 6,194
  • 5
  • 32
  • 56
0

try this :

progresstask.run();

or recreate give timer another instance beacause you cancel it :

timer = new Timer();
timer.scheduleAtFixedRate(progresstask, 0, 500);