I tied something like this to open a listener did not work

330 views
Skip to first unread message

Frank Znidarsic

unread,
Oct 12, 2015, 1:43:45 PM10/12/15
to android-midi
I am trying to follow the institutions within the android.media.midi and the MidiDevice classes.  Nothing works.
I now believe that the implementation of these classes is beyond the scope of my comprehension.



 //these methods are called by and action bar item

//open the listener device. Device Info was passed as the selected device
openDevice(deviceInfo, null, null);

//open the output port 2
openOutputPort(2);

//open the input port 1
openInputPort(1);

}

// From class MidiDevice open the device
public void openDevice(MidiDeviceInfo[] device, OnDeviceOpenedListener listener, Handler handler)

{
this.listener = listener;
TextView textout = null;

//send the information to a textview
textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);

//the only thing that comes through is device = void upon the initial call. The listener initiates no action.
textout.setText(String.format("Midi Keydown detected Device = %s", device + " handler = " +handler));


}

//Class Myreciever was extracted from MidiScope. It was also tried. It appears to do nothing.
private class MyReceiver extends MidiReceiver {
@Override
public void onSend(byte[] data, int offset, int count,
long timestamp) throws IOException {
TextView textout = null;
textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
textout.setText("Midi Keydown detected Handler");
}
}
// here is where the port is opened my devices only need output port 2
public boolean openOutputPort(int i) {

return true;
}
// the input port is opened. They are never used.
public void openInputPort(int i){

}
}

//




Phil Burk

unread,
Oct 12, 2015, 5:21:08 PM10/12/15
to android-midi
> I now believe that the implementation of these classes is beyond the scope of my comprehension.

I think you should try one step at a time. First try to just open the device. Don't worry about the ports yet.

On Monday, October 12, 2015 at 10:43:45 AM UTC-7, Frank Znidarsic wrote:
        //open the listener device.  Device Info was passed as the selected device
openDevice(deviceInfo, null, null);

When the device is opened, it will get passed back to your listener. If you pass a null listener then you will never get the open device.

Try something like this:

MidiDeviceInfo info = deviceInfos[0];
midiManager.openDevice(info, new MidiManager.OnDeviceOpenedListener() {
  @Override
  public void onDeviceOpened(MidiDevice device) {
    if (device == null) {
      Log.e(TAG, "could not open device");
    } else {
      TextView textout = (TextView) findViewById(R.id.log);
      textout.setTextColor(Color.RED);
      textout.setText("Got open device! " + device);
      mDevice = device;
    }, new Handler(Looper.getMainLooper())

);
 
//Class Myreciever was extracted from MidiScope. It was also tried. It appears to do nothing.
private class MyReceiver extends MidiReceiver {


This is because you never got the open device. If the program fails at one point then it is likely that everything after that will fail.

Phil Burk

Frank Znidarsic

unread,
Oct 19, 2015, 5:08:27 PM10/19/15
to android-midi

Thanks for your help Phil Burk.  I tried your code and it did not work.  I put the supplied code into a simplest Hello world example (below).  Several error segments of the code light up in red.  The errors are displayed in the comments and within the attached image.  There seems no way to fix this.  Perhaps there is a global error in my coding.

 
The Java Main is posted below.

 package comscifi2zpt.angelfire.www.midireciever;

import android.graphics.Color;
import android.media.midi.MidiDevice;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//Frank Znidarsic code


final MidiDeviceInfo info;
MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);
final MidiDeviceInfo[] deviceInfos = m.getDevices();


//code supplied by Phill burk
info = deviceInfos[0];



//error cannot resolve symbol MidiManager
        midiManager.openDevice(info, new MidiManager.OnDeviceOpenedListener() {
@Override
public void onDeviceOpened(MidiDevice device) {
if (device == null) {
                    TextView textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
textout.setText("Device did not open! " + info);
} else {
TextView textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
textout.setText("Got open device! " + info);

//error cannot resolve symbol mdevice
mDevice = device;
//error unexpected token after comma and Looper ())
},new Handler(Looper.getMainLooper())
//error Unexpected token after ")"
);


}}
//error expected )
1019151652.jpg

Pedro Lopez-Cabanillas

unread,
Oct 20, 2015, 5:15:37 AM10/20/15
to androi...@googlegroups.com
Hi,

The code example given by the reference docs. is syntactically wrong here:

Inline image 1

It requires an additional closed brace, like this:

m.openDevice(info, new MidiManager.OnDeviceOpenedListener() {

@Override
public void onDeviceOpened(MidiDevice device) {
if (device == null) {
            Log.e(TAG, "could not open device " + info);
} else {
// ...
}
}
}, new Handler(Looper.getMainLooper()));

Hope this helps.

Regards,
Pedro


--
You received this message because you are subscribed to the Google Groups "android-midi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-midi...@googlegroups.com.
To post to this group, send email to androi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/android-midi/3b9a326f-1494-4d5f-b94b-a7b317ba2fe7%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Frank Znidarsic

unread,
Oct 20, 2015, 10:35:43 AM10/20/15
to androi...@googlegroups.com
Thanks I will try it.
You received this message because you are subscribed to a topic in the Google Groups "android-midi" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/android-midi/4Uaa5Brtfaw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to android-midi...@googlegroups.com.

To post to this group, send email to androi...@googlegroups.com.

Frank Znidarsic

unread,
Oct 20, 2015, 10:47:17 AM10/20/15
to androi...@googlegroups.com
Thank's Pedro.  What you gave me works.  I saw were I made an error and opened an instance of the class m then tried to use the instance of the class midimanager.  The looper now seems to work.  I will try again.

Frank Znidarsic


-----Original Message-----
From: Pedro Lopez-Cabanillas <pedro.lopez...@gmail.com>
To: android-midi <androi...@googlegroups.com>
Sent: Tue, Oct 20, 2015 5:15 am
Subject: Re: I tied something like this to open a listener did not work

You received this message because you are subscribed to a topic in the Google Groups "android-midi" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/android-midi/4Uaa5Brtfaw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to android-midi...@googlegroups.com.

To post to this group, send email to androi...@googlegroups.com.

Phil Burk

unread,
Oct 26, 2015, 2:45:15 PM10/26/15
to android-midi
> The code example given by the reference docs. is syntactically wrong here:

Thanks Pedro! Your fix for the openDevice() example looks correct. I updated the docs internally. The change will eventually appear online.

Please let us know if you find any other errors.

Phil Burk

Phil Burk

unread,
Oct 29, 2015, 2:19:21 PM10/29/15
to android-midi
The updated doc with the added bracket is here:
Thanks again Pedro.

Frank Znidarsic

unread,
Oct 30, 2015, 11:36:48 AM10/30/15
to androi...@googlegroups.com
I have still no luck.  If anyone makes or finds a simple example of a MIDI Receiver on the web please let me know.  I believe that part of my problem is that I don't know how to initialize MidiDevice.  I can get and initialize MidiDeviceInfo but I know how set MidiDevice to point to a device.  All that I can do is to set it null as below.
MidiDevice device =null;


-----Original Message-----
From: Phil Burk <phil...@google.com>
To: android-midi <androi...@googlegroups.com>
Sent: Thu, Oct 29, 2015 2:19 pm
Subject: Re: I tied something like this to open a listener did not work

--
You received this message because you are subscribed to a topic in the Google Groups "android-midi" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/android-midi/4Uaa5Brtfaw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to android-midi...@googlegroups.com.
To post to this group, send email to androi...@googlegroups.com.

Frank Znidarsic

unread,
Nov 5, 2015, 8:43:32 PM11/5/15
to android-midi
I tied again.  MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE); does not reach the code from the onCreate method.   I put it in my method open_device.  it seems to work from there. 

  I leftthe m. in the open_device method.  m.open device was implement just is in the documentation.  The m. has to be left in for the code to compile.  

The method   m.openDevice(info0, new OnDeviceOpenedListener() apparently takes device info and returns device.  That is what Android Studio asks for.

The looper seems to link up with Myreciever in the location shown.  It can access device from this location.  All of the code compiles with no red lines as shown. 

 When it runs, the Android Marshmallow device returns.  "Unfortunately Your Program Has Stopped."  This error goes away if   outputPort.connect(new MyReceiver()); is commented out.  I want to open output port 2 on the MIDI that is why I set index to 2.

Any ideas of what is wrong?


// start of code 
public void open_device() {


//Call Midimanager onCreate method
        MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);


        //init data types
// MidiDevice device = null;
MidiDeviceInfo[] info = m.getDevices();
final MidiDeviceInfo info0 = info[0];


//get property name
Bundle properties = info0.getProperties();
final String manufacturer = properties.getString(MidiDeviceInfo.PROPERTY_NAME);

//Open an instance of the class openDevice
m.openDevice(info0, new OnDeviceOpenedListener() {



@Override
public void onDeviceOpened(MidiDevice device) {

if (device == null) {
                    TextView textout = null;
textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
                    textout.setText("Device failed to open");
} else {

TextView textout = null;
textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
                    textout.setText("Device opened  = " + manufacturer);

//open oputput port #2 on MIDI device
//put here to obtain device info and to avoid null pointer exception error
int index = 2;
MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(new MyReceiver());
}
int index = 2;


}

}, new Handler(Looper.getMainLooper()));


}


//Class Myreciever

class MyReceiver extends MidiReceiver {

Phil Burk

unread,
Nov 5, 2015, 8:57:14 PM11/5/15
to android-midi
Hello Frank,

I'm glad you are making progress.

On Thu, Nov 5, 2015 at 5:43 PM, 'Frank Znidarsic' via android-midi <androi...@googlegroups.com> wrote:
The method   m.openDevice(info0, new OnDeviceOpenedListener() apparently takes device info and returns device.  That is what Android Studio asks for.

Not exactly. It does not return the device. The opened device is passed to the callback.
 
 When it runs, the Android Marshmallow device returns.  "Unfortunately Your Program Has Stopped."  This error goes away if   outputPort.connect(new MyReceiver()); is commented out.  I want to open output port 2 on the MIDI that is why I set index to 2.

Probably because the index is set to 2. You can use info0.getOutputPortCount() to get the number of ports. Most keyboards will only have one output port. In that case the index can only be zero.

Try using index=0

Is the manufacturer name that you display the same as what you expected?

Phil Burk

Frank Znidarsic

unread,
Nov 5, 2015, 11:02:30 PM11/5/15
to androi...@googlegroups.com
Thank you Phil.  I got a big improvement when I set the index to zero.  Finally something happened upon keydown.  Unfortunately what happens is that the Marshmallow device produces an "device stopped working" error on keydown.


I am trying ways to fix that now.

Frank Znidarsic


Frank Znidarsic

unread,
Nov 6, 2015, 12:34:35 AM11/6/15
to androi...@googlegroups.com
Hi Phil, setting the index to zero worked.  The onSend method works, sort of.  It returns the keydown = and the number of the key that is pressed.  After briefly displaying this it then goes into,  "Unfortunately my program has stopped"  The below program will loop until key 90 or higher is pressed.  It displays keydown= 90.  Yes!  Then trips and says "Unfortunately your program has stopped"  It stops with a text view, a call to a function, or an imageview.  Any ideas.

Frank Znidarsic

//code below
//method open_device opens midi device Called by menu item
public void open_device() {

//Call Midimanager onCreate method
MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);


//init data types
// MidiDevice device = null;
MidiDeviceInfo[] info = m.getDevices();
final MidiDeviceInfo info0 = info[0];


//get property name
Bundle properties = info0.getProperties();
final String manufacturer = properties.getString(MidiDeviceInfo.PROPERTY_NAME);

//Open an instance of the class openDevice
m.openDevice(info0, new OnDeviceOpenedListener() {


@Override
public void onDeviceOpened(MidiDevice device) {

if (device == null) {
TextView textout =
null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
RED);
textout.setText(
"Device failed to open");
}
else {
TextView textout =
null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
RED);
textout.setText(
"Device opened = " + manufacturer
);

//open output port #0 on MIDI device

int index = 0;

MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(
new MyReceiver());
}



}

},
new Handler(Looper.getMainLooper()));


}


//Class Myreciever

class MyReceiver extends MidiReceiver {

public void onSend(byte[] data, int offset,
int count, long timestamp) throws
IOException {

if (data[2] > 80) {

TextView textout =
null;
textout=(TextView)
findViewById(R.id.
log);
textout.setText(
"keydown = "+data[2]);
}

}

}

}





Phil Burk

unread,
Nov 6, 2015, 5:55:25 PM11/6/15
to android-midi
Hello Frank,


On Thu, Nov 5, 2015 at 9:34 PM, 'Frank Znidarsic' via android-midi <androi...@googlegroups.com> wrote:
> Hi Phil, setting the index to zero worked.  The onSend method works, sort of.  It returns the keydown = and the number of the key that is pressed.


Good. But normally the number of the key would be in data[1].

       textout.setText("keydown = "+data[2]);
data[2] is generally velocity.



>  After briefly displaying this it then goes into,  "Unfortunately my program has stopped"  The below program will loop until key 90 or higher is pressed.  It displays keydown= 90.  
> Yes!  Then trips and says "Unfortunately your program has stopped"  It stops with a text view, a call to a function, or an imageview.  Any ideas.

You can probably find an error message in the logcat that will explain why your program stopped. 

I have some suggestions:

In the openDevice() callback, save the device object in an instance variable called mOpenDevice.
Then in your onDestroy() method, call mOpenDevice.close().

Also save and close your open output port.

>  The below program will loop until key 90 or higher is pressed.

What do you mean loop? You should not be looping unless you start your own Thread. If you loop in a method running on the UI Thread then the UI Thread may die. Then your app will die.

Phil Burk

Frank Znidarsic

unread,
Nov 7, 2015, 12:02:18 PM11/7/15
to androi...@googlegroups.com
Thank you Phil.  For the other who have been following this I posted a code that works, sometimes.  I fixed the test for open device to look for a port number not a null.  Thank you on this one Phil.  I did not put the destroy methods in yet but I will.

The code works when sending a message to logcat.  It will give the keydown and the number of the key.  These will be seen after re-plugging the tablet into the desk top at the bottom of Android studio.

I wanted to display the key information into a textview and imageview. I can change colors and include them in a nice window with other stuff.   I get the error:


Only the original thread that created the the hierarchy can touch the text views.

This is not a MIDI error and it may be beyond the scope to this discussion.  I am now trying to get around it.  Any ideas?

Frank

 //method open_device opens midi device  Called by menu item or a button
    public void open_device() {

//Call Midimanager onCreate method
MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);


//init data types
        MidiDeviceInfo[] info = m.getDevices();
//use device zero there may be others but for this simple example zero works
        final MidiDeviceInfo info0 = info[0];
        //use the port count in a test to determine if the device cans open
final int numOutputs = info0.getOutputPortCount();

//get the name of the MIDI keyboard this will be used to show which device has opened
        Bundle properties = info0.getProperties();
final String manufacturer = properties.getString(MidiDeviceInfo.PROPERTY_NAME);

//Open an instance of the class openDevice
m.openDevice(info0, new OnDeviceOpenedListener() {
@Override
public void onDeviceOpened(MidiDevice device) {
            //port number is < 1  if device is connected
if ( numOutputs < 1) {

TextView textout = null;
textout = (TextView) findViewById(R.id.log);
textout.setTextColor(Color.RED);
                    textout.setText("Device failed to open.  Try disconnecting/reconnecting OTG cable. ");

} else {
// send out device has oepned message
                    TextView textout = null;
textout = (TextView) findViewById(R.id.log);
                    textout.setTextColor(Color.BLUE);

textout.setText("Device opened = " + manufacturer);

                    //open output device #0 on MIDI device, there my be others but for this example zero is start
                    int index = 0;
MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(new MyReceiver());
}



}

}, new Handler(Looper.getMainLooper()));


}


    //Class Myreceiver receives MIDI data from a que.

class MyReceiver extends MidiReceiver {

public void onSend(byte[] data, int offset, int count, long timestamp) throws IOException {


            //detect mid c, note number 60, or higher
if (data[2] > 59) {
// prints nicely to logcat
System.out.println("Keydown = "+ data[2]);

// error Android with text view “Only the original thread that created a view hierarchy can touch its views.”
// TextView textout9 = null;
// textout9 = (TextView) findViewById(R.id.log);textout9.setTextColor(Color.BLUE);
// textout9.setText("keydown = " + data[2]);



}

}
}



}


Frank Znidarsic

unread,
Nov 7, 2015, 12:42:07 PM11/7/15
to androi...@googlegroups.com
As per my last email I am getting.  Only the original thread that created the the hierarchy can touch the text views.


I am trying to send the data out to another method and that method will change the textview.  Code snippit is below.  This does not work.



 class MyReceiver extends MidiReceiver {

public void onSend(byte[] data, int offset, int count, long timestamp) throws IOException {


//detect mid c, note number 60, or higher
if (data[2] > 59) {
// tried to send the action out to a method show_c that contains image views.  Does not work.
// generates, Only the original thread that created the the hierarchy can touch the text views.

                    show_c();

// prints nicely to logcat commented out for this test.
// System.out.println("Keydown = "+ data[2]);

Pedro Lopez-Cabanillas

unread,
Nov 7, 2015, 3:02:22 PM11/7/15
to androi...@googlegroups.com

Hi,


You probably need to use Activity.runOnUiThread:

http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29


There is a similar example to your use case called MidiScope:

https://github.com/googlesamples/android-MidiScope/blob/master/Application/src/main/java/com/example/android/midiscope/MainActivity.java

@Override
public void log(final String string) {
runOnUiThread(new Runnable() {
@Override
public void run() {
logOnUiThread(string);
}
});
}

/**
* Logs a message to our TextView. This needs to be called from the UI thread.
*/
private void logOnUiThread(String s) {
mLogLines.add(s);
if (mLogLines.size() > MAX_LINES) {
mLogLines.removeFirst();
}
// Render line buffer to one String.
StringBuilder sb = new StringBuilder();
for (String line : mLogLines) {
sb.append(line).append('\n');
}
mLog.setText(sb.toString());
mScroller.fullScroll(View.FOCUS_DOWN);
}


Regards,

Pedro



--
You received this message because you are subscribed to the Google Groups "android-midi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-midi...@googlegroups.com.

To post to this group, send email to androi...@googlegroups.com.

Frank Znidarsic

unread,
Nov 8, 2015, 10:53:44 AM11/8/15
to androi...@googlegroups.com
Thanks Pedro.  I do not want to implement a logger. MidiScope is a logger.  I want a graphical interface.  The standard way of presenting graphics is with a textview or an image view.  I have tried some tricks to get around the error cannot rewrite to a textview....  I tried to put the textview in a method and calling it.  This did not work.  I then put a method PrintOut() in a class PrintMidi.  A direct implementation of "PrintMidi.Printout();"  produces the error,  "Textview cannot be implemented from a static context".  Next I called an instance of the class "PrintMidi as shown below.    The produces a different error.  It is: 

Can't create handler inside thread that has not called Looper.prepare().  This code is shown below.

class MyReceiver extends MidiReceiver {

public void onSend(byte[] data, int offset, int count, long timestamp) throws IOException {


//detect mid c, note number 60, or higher
if (data[2] > 59) {

// called an instance of PrintMidi to get around the error cannot rewrite to a textview
                    PrintMidi m = new PrintMidi();
m.PrintOut();



}

Its no wonder Java is frustrating.  I did make a lot of progress except for this one last error.  A very basic example of the a Midi receiver was implemented.  The new example is about 50 steps, not 800.  It's all in the main and easy to follow.  Its a starting place to build from.  It is  different from the supplied examples as listed below:
These differences include.
Using  if( numOutputs < 1) instead of  null to test for if a device is open.
Re phrasing the looper.  Thanks Pedro.
Moving 
 int index = 0;
MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(new MyReceiver()); 
into the m.ondevce opened method.  The supplied example shows these two lines of code at the bottom of the onSend method.
Knowing to set the index to zero not to two for the first simple example.
Setting the first parameter in m.openDevice(info0
by calling, final MidiDeviceInfo info0 = info[0];
Knowing to call  m.openDevice from a button or menu but not to call the onDevice opened class.
Thank you Phil for getting me there.  The basics of a MidiReceiver are now done.

Frank Znidarsic

Frank Znidarsic

unread,
Nov 9, 2015, 5:28:13 PM11/9/15
to androi...@googlegroups.com
I finally got it.  Thanks to all.  It was like pulling teeth.  The code is below.  It requires an xml file with a text view named log.  The on destroy and close port has still to be implemented.

  //method open_device opens midi device  Called by menu item or a button
This opens output port 2 on the MIDI and device 0;  

public void open_device() {

//Call Midimanager onCreate method
MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);


//init data types
MidiDeviceInfo[] info = m.getDevices();
//use device zero there may be others but for this simple example zero works
        final MidiDeviceInfo info0 = info[0
];
//use the port count in a test to determine if the device cans open
final int numOutputs = info0.getOutputPortCount();

//get the name of the MIDI keyboard this will be used to show which device has opened
Bundle properties = info0.getProperties();
final String manufacturer = properties.getString(MidiDeviceInfo.PROPERTY_NAME
);

//Open an instance of the class openDevice
m.openDevice(info0, new OnDeviceOpenedListener() {
int singleshot = 0;

@Override
public void onDeviceOpened(MidiDevice device) {
//port number is < 1 if device is connected
                if (numOutputs < 1) {
TextView textout =
null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
RED);
textout.setText(
"Device failed to open. Try disconnecting/reconnecting OTG cable. ");

}
else {
// send out device has opened message
                    TextView textout = null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
BLUE);
textout.setText(
"Device opened = " + manufacturer);

//open output device #0 on MIDI device, there my be others but for this example zero is start
                    int index = 0;
MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(
new
MyReceiver());
}


}

},
new Handler(Looper.getMainLooper()));


}


//Class Myreceiver receives MIDI data from a que.

    class MyReceiver extends MidiReceiver {

public void onSend(final byte[] data, int offset, int count, long timestamp) throws IOException {


//detect mid c, note number 60, or higher
if (data[2] > 59) {

// error Android with text view “Only the original thread that created a view hierarchy can touch its views.” is fixed with the runonUiThread command.


runOnUiThread(new Runnable() {
@Override
public void
run() {

TextView textout =
null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
BLUE);
textout.setText(
"keydown = " + data[2] );
}
});

}

}


}



}

Phil Burk

unread,
Nov 9, 2015, 5:28:34 PM11/9/15
to android-midi
Hello Frank,

A quick google search on that error message led me to this:

I think at this point you are mainly hitting non-MIDI issues. Please look for support in the Android docs and by searching online.
If you have something that is Android MIDI specfic then let us know.

Thanks,
Phil Burk

Frank Znidarsic

unread,
Nov 9, 2015, 5:37:52 PM11/9/15
to androi...@googlegroups.com
Thank you Phil Burk.

I finally got it.  Thanks to you all.  It was like pulling teeth.  The code is below.  It requires an associated xml file with a text view named log.  The on destroy and close port has still to be implemented.  The textview may be slower than a logger but for my next uses I don't care.

Frank Znidarsic

unread,
Nov 9, 2015, 6:05:45 PM11/9/15
to androi...@googlegroups.com
 I finally got it.  Thank Phil. Thanks Pedro.  Pasted below is a simple 37 step program that displays MIDI information on a graphical textview.  It opens only MIDI output port 2 and device zero.  That's all that I am going to need.  The app still needs the closeport and onDestroy methods.  I also plan to put a restore screen timeout in the onDestroy method.  I also plan to move as much code as possible out of the Main.

The solution using the new MIDI methods and a logger was like pulling teeth (for me).  My code is pasted below.  It requires an associated XML file with a text view named log.  The code is much easier to understand than the complex MidiScope.  It contains no context, wrappers or, loggers,  It can be used as an aid in the basic understanding MIDI scope.  I'm  on my way to getting my first app going.  From there I am going to work with a hardware developer to produce hard wired MIDI interfaces and apps.  I can do it!

  //method open_device opens midi device  Called by menu item or a button
This opens output port 2 on the MIDI and device 0;  

public void open_device() {

//Call Midimanager
        MidiManager m = (MidiManager) getSystemService(MIDI_SERVICE);


//init data types
MidiDeviceInfo[] info = m.getDevices();
//use device zero there may be others but for this simple example zero works
        final MidiDeviceInfo info0 = info[0
];
//use the port count in a test to determine if the device cans open
final int numOutputs = info0.getOutputPortCount();

//get the name of the MIDI keyboard this will be used to show which device has opened
Bundle properties = info0.getProperties();
final String manufacturer = properties.getString(MidiDeviceInfo.PROPERTY_NAME);

//Open an instance of the class openDevice
m.openDevice(info0, new OnDeviceOpenedListener() {
int singleshot = 0;

@Override
public void
onDeviceOpened(MidiDevice device) {
//If port number is < 1 the device is connected
                if (numOutputs < 1) {
TextView textout =
null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
RED);
textout.setText(
"Device failed to open. Try disconnecting/reconnecting OTG cable. ");

}
else {
// send out device has opened message
TextView textout = null;
textout = (TextView) findViewById(R.id.
log);
textout.setTextColor(Color.
BLUE);
textout.setText(
"Device opened = " + manufacturer);

//open output device #0 on MIDI device, there my be others but for this example zero is start
                    int index = 0;
MidiOutputPort outputPort = device.openOutputPort(index);
outputPort.connect(
new
MyReceiver());
}


}

},
new Handler(Looper.getMainLooper()));


}


//Class Myreceiver receives MIDI data from a que.

    class MyReceiver extends MidiReceiver {

public void onSend(final byte[] data, int offset, int count, long timestamp) throws IOException {


//detect mid c, note number 60, or higher is pressed

            if (data[2] > 59) {

Frank Znidarsic

unread,
Nov 10, 2015, 3:48:11 PM11/10/15
to androi...@googlegroups.com
Thanks again.  Progress video linked below.  The text view does slow the MIDI down a bit.  I am am algorithm to clear stuck keys.  Short movie linked below. 

Frank Znidarsic

unread,
Nov 11, 2015, 7:29:34 PM11/11/15
to androi...@googlegroups.com
Thank you again Phil.  I'm cleaning up my app to make it look nice.  I am running the code as efficiently as possible.  I used the midi key down number  as an array pointer.   The returned integer then effects only one text view instead of 40 text views and their associated if statements.  It seem to work OK.  I do get some stuck keys if the MIDI is played fast.  My device does not have the new high speed port.  The action is good enough. 

I don't want to make a bad app that leaks memory.  The onDestroy class is important.  Thanks.  The onDestroy code is pasted below and it seems to work well.  I had to put the if statement into the Destroy to prevent the app from throwing an exception and tripping when the screen was rotated before mdevice was set to device.

I am looking for the method to close the MIDI port.  I tried the code below.  It does not work.

mdevice.closeOutputPort(index);

I will look for the close port method again.  Does anyone see it?

Notes on a score is trivial for most, but it is a good start for me.  I want to use the 88 keys to control hardware and interface with the web.  I am working with a small electronic Co on this.  They we happy I got the midi working and look forward to a Bluetooth interface.  We can do a lot with this and the software is simple enough that I can handle it.  The hardware is on the market and it is cheep.  Thanks again.

 //reset screen saver and close object device upon exit from the app
public void onDestroy() {

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

if (mdevice != null){
try {
mdevice.close();
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}

}

Phil Burk

unread,
Nov 11, 2015, 8:05:37 PM11/11/15
to android-midi
On Wed, Nov 11, 2015 at 4:29 PM, 'Frank Znidarsic' via android-midi <androi...@googlegroups.com> wrote:
I am looking for the method to close the MIDI port.  I tried the code below.  It does not work.
mdevice.closeOutputPort(index);

     mOutputPort.close();
 
I will look for the close port method again.  Does anyone see it?

Frank Znidarsic

unread,
Nov 19, 2015, 6:53:33 PM11/19/15
to androi...@googlegroups.com
Testing results:

I have had no luck with the VicTsing MIDI adapter.

Casio Prima does not send keyup only keydown.  This was fixed by using only keyup and or'ed with key impact ==0.

The turtle beach MIDI adapter woks well,  Bass Station II MIDI output works well.


Adapters with LED's on them may draw too much Android power.  I do not have a high speed port.

Frank Znidarsic

Phil Burk

unread,
Nov 24, 2015, 2:48:01 PM11/24/15
to android-midi
I am looking for the method to close the MIDI port.  I tried the code below.  It does not work.
mdevice.closeOutputPort(index);
 

Phil Burk

unread,
Nov 30, 2015, 1:51:07 PM11/30/15
to android-midi
On Thu, Nov 19, 2015 at 3:53 PM, 'Frank Znidarsic' via android-midi <androi...@googlegroups.com> wrote:
Casio Prima does not send keyup only keydown.  This was fixed by using only keyup and or'ed with key impact ==0.

That is legal MIDI. A NoteOn message with velocity==0 is equivalent to a NoteOff. This helps with running status. 


Frank Znidarsic

unread,
Dec 2, 2015, 10:45:05 AM12/2/15
to androi...@googlegroups.com
Thank you Phil and Happy Holidays to you.  

I published my first MIDI app on Amazon.com.  I will observe the comments there before submitting the app to Google play.  So far there are no devices and no sales for this Android M app.  Amazon lists that no Android M devices are available.  My Nexis is upgraded to Android M.  It is blocked from downloading this API 23 app.  I don't know if Google will allow upgraded devices to download Android M apps.  I was hoping that there would be a big release of Android M for Christmas.  Google is a bit late for this.  Feel free to try the free version.



After taking a break I plan to work on my second app Security Monitoring Systems.  It will send an SMS messages upon contact closure.  I would also like to send MMS pictures but I am not sure if this is possible or desirable.   I don't want this app to be used for clandestine peeping. 

There are a lot of MIDI boards out there that can be used for this purpose   I am told that cheaper joy stick control boards also send MIDI readable transmissions.  I'll have to try one and see. 

In off topic news, sales of my books dropped of to very slow. " Energy, Cold Fusion, and Antigravity" was selling one every two days at its peek.  I was hoping to do better with this also.  Its a good thing that I am retired.  My sales have not generated enough revenue to feed my cat.



...................



Frank Znidarsic PE

Frank Znidarsic

unread,
Dec 20, 2015, 2:57:27 PM12/20/15
to androi...@googlegroups.com


Subject: Merry Christmas Song for you

Played by Frank Znidarsic and displayed on his MIDI Staff App.


Frank Znidarsic

ps book Electronic Project is free on New Years Day.

MIDI staff full was modified to use the standard 8va and 8vd notations.
This will run on a smaller screen.
This version will be in review for a few days at amazon.

There will be action on MIDI monitoring until after the New Year.
It looks like I am going to have to use Gmail to communicate with the
MIDI inputs.


Frank Znidarsic

unread,
Feb 18, 2016, 12:18:31 PM2/18/16
to androi...@googlegroups.com
I managed to get my apps out on Amazon.  I will also place them on Google after I see that there are no unexpected problems.




This is all that I want to do for now.  I make make some variations of the same themes.  In the works may be Monitoring Underground with an Audrio aski keyboard type contact input board.  No MIDI board. I can set the api back a little.  And Musial Score for performers that will display their name/info. when they quit playing.  This will work with Chromecast.



I got into an emergent unexpected problem.  The command 


MidiDeviceInfo[] info = m.getDevices();


started returning a empty null array.  I could no longer test, as Phil had suggested, to see if a port was open.  I now test for a null array, or a port not open, and then return a Device Not Connected message. 

 Thanks all for you help, especially Phil


Frank Znidarsic

Frank Znidarsic

unread,
Feb 18, 2016, 12:30:49 PM2/18/16
to androi...@googlegroups.com
PS like the orb here is where it came from.  


When you are a micro developer you have to do the best with what you have.

Frank Znidarsic
Reply all
Reply to author
Forward
0 new messages