Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.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 Android MIDI线程中断异常-触摸后消息_Java_Android_Multithreading_Midi_Interrupted Exception - Fatal编程技术网

Java Android MIDI线程中断异常-触摸后消息

Java Android MIDI线程中断异常-触摸后消息,java,android,multithreading,midi,interrupted-exception,Java,Android,Multithreading,Midi,Interrupted Exception,正在尝试在我的Android应用程序上运行MIDI。我正在按照配置我的应用程序,它可以正常工作,但后触摸除外。每当我尝试触发后触摸时,我都会遇到线程异常类型 中断异常。我应该如何防止这个线程问题?我在多线程方面的知识不是最好的,否则我早就知道了。我现在真正能说的是消息发送得太快了,线程还没有从睡眠呼叫中醒来 我遵循github回购协议,代码如下: MidiReceiver子类: @TargetApi(Build.VERSION_CODES.M) public class MidiEngine e

正在尝试在我的Android应用程序上运行MIDI。我正在按照配置我的应用程序,它可以正常工作,但后触摸除外。每当我尝试触发后触摸时,我都会遇到线程异常类型
中断异常
。我应该如何防止这个线程问题?我在多线程方面的知识不是最好的,否则我早就知道了。我现在真正能说的是消息发送得太快了,线程还没有从睡眠呼叫中醒来

我遵循github回购协议,代码如下:

MidiReceiver
子类:

@TargetApi(Build.VERSION_CODES.M)
public class MidiEngine extends MidiReceiver {

    public  AudioActivity activity;
    private MidiEventScheduler eventScheduler;
    private MidiFramer midiFramer;
    private MidiReceiver midiReceiver = new MyReceiver();

    private Thread mThread;
    private boolean go;
    private int mProgram;

    public MidiEngine() {
        this(new AudioActivity());
    }

    public MidiEngine(AudioActivity activity) {
        this.activity = activity;
        midiReceiver = new MyReceiver();
        midiFramer = new MidiFramer(midiReceiver);
    }

    public AudioActivity getActivity() {
        return this.activity;
    }

    /* This will be called when MIDI data arrives. */
    @Override
    public void onSend(byte[] data, int offset, int count, long timestamp)
            throws IOException {
        if (eventScheduler != null) {
            if (!MidiConstants.isAllActiveSensing(data, offset, count)) {
                eventScheduler.getReceiver().send(data, offset, count,
                        timestamp);
            }
        }
    }

    // Custom Listener to send to correct methods
    private class MyReceiver extends MidiReceiver {
        @Override
        public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
            byte command    = (byte)(msg[0] & MidiConstants.STATUS_COMMAND_MASK);
            int channel     = (byte)(msg[0] & MidiConstants.STATUS_CHANNEL_MASK);

            switch (command) {
                case MidiConstants.STATUS_NOTE_ON:
                    activity.keyDown(i, msg[1], msg[2]);
                    break;

                case MidiConstants.STATUS_NOTE_OFF:
                    activity.keyUp(channel, msg[1]);
                    break;

                case MidiConstants.STATUS_POLYPHONIC_AFTERTOUCH:
                    activity.keyDown(channel, msg[1], msg[2]);
                    break;

                case MidiConstants.STATUS_PITCH_BEND:
                    activity.pitchBendAction(channel, (msg[2] << 7) + msg[1]);
                    break;

                case MidiConstants.STATUS_CONTROL_CHANGE:
                    activity.ccAction(channel, msg[1], msg[2]);
                    break;

                case MidiConstants.STATUS_PROGRAM_CHANGE:
                    mProgram = msg[1];
                    break;

                default:
                    break;
            }
        }
    }

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            do {
                try {
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                processMidiEvents();
                            }
                            catch (Exception e) {
                                Log.e("Java", "SynthEngine background thread exception.", e);
                            }
                        }
                    });
                    Thread.sleep(100);
                }
                catch (InterruptedException e) {
                    Log.e("Java", "Threading exception", e);
                }
            }
            while (go);
        }
    }

    /**
     * @throws IOException
     *
     */
    private void processMidiEvents() throws IOException {
        long now = System.nanoTime();
        MidiEventScheduler.MidiEvent event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
        while (event != null) {
            midiFramer.send(event.data, 0, event.count, event.getTimestamp());
            eventScheduler.addEventToPool(event);
            event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
        }
    }

    public void start() {
        stop();
        go = true;
        mThread = new Thread(new MyRunnable());
        mThread.setPriority(6);
        eventScheduler = new MidiEventScheduler();
        mThread.start();
    }

    public void stop() {
        go = false;
        if (mThread != null) {
            try {
                mThread.interrupt();
                mThread.join(500);
            }
            catch (Exception e) {

            }
            mThread = null;
            eventScheduler = null;
        }
    }

}
谢谢

编辑:线程开始 Midi设备服务子类(当设备连接或断开连接时,线程将启动)

活动类别:

public class AudioActivity extends AppCompatActivity {
    private Thread thread;
    public static MidiEngine midiEngine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Layout inits
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

        // Setup MIDI:
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) {
            Toast.makeText(this, "MIDI not supported!", Toast.LENGTH_LONG).show();
        }
        else {
            midiEngine = new MidiEngine(this);
            setupMidi();
        }

        // Setup audio thread:
        if (thread == null) {
            thread = new Thread() {
                public void run() {
                    setPriority(Thread.MAX_PRIORITY);
                    // Runs an Open SL audio thread (C++)
                    // This generates a waveform. 
                    // AudioEngine is a wrapper class connecting C++ to Java
                    AudioEngine.runProcess();
                }
            }
        }
    }

    public void setupMidi() {
        if (activity == null) activity = (AudioActivity) getContext();

        mMidiManager = (MidiManager) activity.getSystemService(AudioActivity.MIDI_SERVICE);
        if (mMidiManager == null) {
            Toast.makeText(activity, "MidiManager is null!", Toast.LENGTH_LONG).show();
            return;
        }
        // Get Device Info
        MidiDeviceInfo deviceInfo = MidiTools.findDevice(mMidiManager, "RFOO", "AudioApp");

        // MIDI Input
        portIndex = 0;
        inputPortSelector = new MidiOutputPortConnectionSelector(mMidiManager, activity, R.id
                .inputListView, deviceInfo, portIndex);
        inputPortSelector.setConnectedListener(new MyPortsConnectedListener());

        midi_ch_input = 0;
        midi_ch_output = 0;
    }

    // Bunch of UI code here....
}

请在调用
MyRunnable
的位置提供更多信息。它的线程在那里启动,cancelled@Vyacheslav当然可以-刚刚添加的。那么,如何开始
音频活动
?我只看到您更改了示例项目的代码。什么是
AudioActivity.midiEngine
?@Vyacheslav
AudioActivity
只是Android应用程序的主要活动。
midiEngine
变量是一个
MidiReceiver
子类(与示例中的相同;几乎所有的MIDI内容都取自midisuite示例)
midiEngine
是属于
AudioActivity
的静态变量。如果需要的话,我也会发布这个类
@TargetApi(Build.VERSION_CODES.M)
public class MidiSynthDeviceService extends MidiDeviceService {
    private static final String TAG = "MidiSynthDeviceService";
    private boolean midiStarted = false;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        AudioActivity.midiEngine.stop();
        super.onDestroy();
    }

    @Override
    // Declare the receivers associated with your input ports.
    public MidiReceiver[] onGetInputPortReceivers() {
        return new MidiReceiver[] { AudioActivity.midiEngine };
    }

    /**
     * This will get called when clients connect or disconnect.
     * You can use it to turn on your synth only when needed.
     */
    @Override
    public void onDeviceStatusChanged(MidiDeviceStatus status) {

        if (status.isInputPortOpen(0) && !midiStarted) {
            AudioActivity.midiEngine.start();
            midiStarted = true;
        } else if (!status.isInputPortOpen(0) && midiStarted){
            AudioActivity.midiEngine.stop();
            midiStarted = false;
        }
    }
}
public class AudioActivity extends AppCompatActivity {
    private Thread thread;
    public static MidiEngine midiEngine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Layout inits
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

        // Setup MIDI:
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) {
            Toast.makeText(this, "MIDI not supported!", Toast.LENGTH_LONG).show();
        }
        else {
            midiEngine = new MidiEngine(this);
            setupMidi();
        }

        // Setup audio thread:
        if (thread == null) {
            thread = new Thread() {
                public void run() {
                    setPriority(Thread.MAX_PRIORITY);
                    // Runs an Open SL audio thread (C++)
                    // This generates a waveform. 
                    // AudioEngine is a wrapper class connecting C++ to Java
                    AudioEngine.runProcess();
                }
            }
        }
    }

    public void setupMidi() {
        if (activity == null) activity = (AudioActivity) getContext();

        mMidiManager = (MidiManager) activity.getSystemService(AudioActivity.MIDI_SERVICE);
        if (mMidiManager == null) {
            Toast.makeText(activity, "MidiManager is null!", Toast.LENGTH_LONG).show();
            return;
        }
        // Get Device Info
        MidiDeviceInfo deviceInfo = MidiTools.findDevice(mMidiManager, "RFOO", "AudioApp");

        // MIDI Input
        portIndex = 0;
        inputPortSelector = new MidiOutputPortConnectionSelector(mMidiManager, activity, R.id
                .inputListView, deviceInfo, portIndex);
        inputPortSelector.setConnectedListener(new MyPortsConnectedListener());

        midi_ch_input = 0;
        midi_ch_output = 0;
    }

    // Bunch of UI code here....
}