生成于Android FileDescriptor的无需先打开一个文件 [英] Generating a FileDescriptor on Android without first opening a file

查看:516
本文介绍了生成于Android FileDescriptor的无需先打开一个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆