生成于Android FileDescriptor的无需先打开一个文件 [英] Generating a FileDescriptor on Android without first opening a file
问题描述
在Android中,是否有可能直接从字节数组生成的FileDescriptor,而不必首先打开一个文件?
In Android, is it possible to generate a FileDescriptor directly from a byte array, without having to open a file first?
在Android 2.2系统,我生成动态MIDI文件,然后打回用MediaPlayer的。我已经包括,这是否顺利下面的Main.java文件的文本。到目前为止好。
In Android 2.2, I am generating a MIDI file on the fly, and then playing it back using MediaPlayer. I've included the text of the Main.java file that does this successfully below. So far so good.
然而,这个过程首先调用...
However, this process first calls...
FileOutputStream outputStream = openFileOutput(file, MODE_PRIVATE);
outputStream.write(byteStream);
outputStream.close();
...写出来的文件,然后调用...
... to write out the file, and then calls...
FileInputStream inputStream = new FileInputStream(midifile);
FileDescriptor fileDescriptor = inputStream.getFD();
...以回读它,打电话之前:
... to read it back in, before calling:
mediaPlayer.setDataSource(fileDescriptor);
这对我来说似乎是一种浪费。我可以直接创建的FileDescriptor从字节数组,使得MIDI流可以立即播放?
This seems to me to be wasteful. Can I create the FileDescriptor directly from the byteArray, so that the MIDI stream can be played immediately?
==工作code ==
== Working code ==
package com.example.midi;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
public class Main extends Activity {
private String file = "midi.mid";
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
createNewMIDIFile();
playNewMIDIFile();
}
public void createNewMIDIFile() {
Integer[] stream = new Integer[]{
//
0x4d, 0x54, 0x68, 0x64, // MThd = MIDI file designator
0x00, 0x00, 0x00, 0x06, // Standard MIDI File (SMF)
0x00, 0x01, 0x00, 0x02, // multiple-track format: 2 tracks
0x00, 0x40, // 64 ticks per beat (quarter note)
0x4D, 0x54, 0x72, 0x6B, // Header for track 1
0x00, 0x00, 0x00, 0x0B, // 11 bytes to describe the track
0x00, 0xFF, 0x51, 0x03, // set tempo:
0x0F, 0x42, 0x40, // 1,000,000 microseconds / beat: 60 bpm
0x00, 0xFF, 0x2F, 0x00, // End of track 1
0x4D, 0x54, 0x72, 0x6B, // Header for track 2
0x00, 0x00, 0x00, 0x0F, // 15 bytes to describe the track
0x00, // Immediately
0xC1, 0x01, // change instrument for track 2 to piano
0x00, // Immediately
0x91, 0x3C, 0x7F, // play middle C with a velocity of 127
0x30, // 48 ticks later (dotted eighth note)
0x81, 0x3C, 0x00, // stop playing the middle C
0x00, 0xFF, 0x2F, 0x00 // End of track 2
};
int length = stream.length;
byte[] byteStream = new byte[length];
for (int ii = 0; ii < length; ii++) {
byteStream[ii] = (byte) (stream[ii] % 256);
}
try {
FileOutputStream outputStream = openFileOutput(file, MODE_PRIVATE);
outputStream.write(byteStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void play(View view) {
/* Triggered by a button defined in activity_main.xml as
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="play"
android:text="Play MIDI" />
*/
playNewMIDIFile();
}
public void playNewMIDIFile() {
try {
String filename = getFilesDir() + "/" + file;
File midifile = new File(filename);
FileInputStream inputStream = new FileInputStream(midifile);
FileDescriptor fileDescriptor = inputStream.getFD();
mediaPlayer.reset();
mediaPlayer.setDataSource(fileDescriptor);
inputStream.close();
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
有关建筑上飞MIDI文件的更多信息,请参见 kevinboone.net ,的 skytopia 和的 sonicspot
For more information on building a MIDI file on the fly, see kevinboone.net, skytopia and sonicspot
推荐答案
的MediaPlayer将起到无论是从一个文件,或者从HTTP URL。
MediaPlayer will play either from a file, or from HTTP url.
所以这里的伎俩是从URL指向到本地主机服务器,在那里你生成动态的数据,从内存,或其他任何方式播放。
So the trick here is to play from url which points to localhost server, where you generate data on-fly, from memory, or any other way.
请参阅我的答案在这里如何做到这一点:
<一href=\"http://stackoverflow.com/questions/9058135/android-serversocket-programming-with-jcifs-streaming-files/9096241#9096241\">Android ServerSocket的编程JCIFS流文件
See my answer here how to do it: Android ServerSocket programming with jCIFS streaming files
这篇关于生成于Android FileDescriptor的无需先打开一个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!