V. Sử dụng MMAPI:
Trong bài này, sẽ mô tả làm thế nào để sử dụng các API multimedia, và các đoạn ví dụ mẫu. Nếu bạn muốn có nhiều code đầy đủ, bạn có thể vào ví dụ trong Wireless Toolkit.
1.Tone Generation:
Tone generation được đặc trưng bởi tần số và thời gian. Kiểu media này thường được sử dụng trong các game và các ứng dụng audio khác, đặc biệt trên các thiết bị nhỏ, hay các thiết bị hỗ trợ hạn chế các kiểu media.
Manager.playTone() phát sinh ra các tone. Thực thi của nó có thể được ánh xạ vào bộ phát sinh tone của phần cứng. Nó có 3 tham số:

...
try {
   // play a tone for 4000 milliseconds at volume 100
   Manager.playTone((ToneControl.C4, 4000, 100));
}
catch(MediaException me) {
}
...


Bạn có thể tạo ra một Player để tổng hợp các chuỗi tone:

...
Player player =
  Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
...

Kiểu của Player cung cấp một ToneControl có thể được sử dụng để tạo ra một chuỗi các tone. Đặc điểm này chỉ sẵn có trên các thiết bị mạnh.
2.MP3 Playback
Đoạn code sau mô tả cách play một đoạn media mà không có control playback fine-grained

...
try {
   Player p = Manager.createPlayer
     ("http://server/somemusic.mp3");
   p.setLoopCount(5);
   p.start();
}
catch(IOException ioe) {
}
catch(MediaException e) {
}
...

Điều này cho biết thêm một ít điều khiển:

...
Player p;
VolumeControl vc;
try {
   p = Manager.createPlayer("http://server/somemusic.mp3");
   p.realize();
   // get volume control for player and set volume to max
   vc = (VolumeControl) p.getControl("VolumeControl");
   if(vc != null) {
      vc.setVolume(100);
   }
   // the player can start with the smallest latency
   p.prefetch();
   // non-blocking start
   p.start();
}
catch(IOException ioe) {
}
catch(MediaException e) {
}
...

Bởi vì bất kỳ InputStream có thể được truyền cho các phương thức Manager.createPlayer (), ứng dụng của bạn có thể playback từ một RMS(Record Management System), hoặc từ một tập tin JAR. Đây là cách để có được một InputStream từ RMS và play media được lưu trữ bên trong nó:

...
RecordStore store;
int id;
// play back from a record store
try {
   InputStream is = new ByteArrayInputStream
     (store.getRecord(id));
   Player player = Manager.createPlayer(is, "audio/X-wav");
   p.start();
}
catch (IOException ioe) {
}
catch (MediaException me) {
}
...

Và đây là cách tương tự cách trên với media được lưu trữ trong file JAR

...
try {
   InputStream is =
     getClass().getResourceAsStream("audio.wav");
   Player player = Manager.createPlayer(is, "audio/X-wav");
   p.start();
}
catch(IOException ioe) {
}
catch(MediaException me) {
}
...

3.Video Playback
Đoạn code sau mô tả cách play một đoạn video MPG:

...
Player p;
VideoControl vc; 
try {
   p = Manager.createPlayer("http://server/somemovie.mpg");
   p.realize();
   // get video control
   vc = (VideoControl) p.getControl("VideoControl");
   ....
   p.start();
}
catch(IOException ioe) {
}
catch(MediaException me) {
}
...

4. Camera
MMAPI còn hỗ trợ cả camera, với một locator đặc biệt: được sử dụng để tạo ra Player. Một ứng dụng có thể sử dụng một VideoControl để hiển thị kính ngắm viewfinder trên màn hình, sau đó có thể chụp ảnh bằng cách gọi hàm VideoControl.getSnapshot(String imageType). Định dạng hình ảnh mặc định của nó là PNG. Bạn có thể sử dụng tham số imageType để chọn bất kỳ format hỗ trợ khác, và truy vấn thuộc tính “video.snapshot.encodings” để tìm hiểu các định dạng được hỗ trợ.
5.The J2ME Wireless Toolkit and MMAPI
Các J2ME Wireless Toolkit 2.0 hỗ trợ MMAPI. Nó cung cấp các ứng dụng demo và một MediaControlSkin – giả lập một nội dung có khả năng chơi audio và video. Để thử nghiệm với demo, mở dự án mmademo và chạy nó. Bạn sẽ thấy một danh sách như một trong những thể hiện trong hình dưới:

5.1.Supported Formats
MMAPI hỗ trợ một số định dạng âm thanh và video, trong đó J2ME Wireless Toolkit hỗ trợ:

* Audio: PCM và WAV
* MIDI: Loại 0 (một bài nhạc), Loại 1 (nhiều bài nhạc), và SP-MIDI
* Video: MPEG-1
5.2.Limitations on Using MMAPI in the Toolkit
Hãy nhớ rằng J2ME Wireless Toolkit có những hạn chế sau – và rằng mọi thiết bị sẽ có, khác với những hạn chế của nó:

  • Một ứng dụng có thể tạo ra nhiều Player, nhưng chỉ có thể nhận thấy một player MIDI hoặc tone-sequence. Bất kỳ cố gắng để nhận ra một player thứ hai đều sẽ ném một MediaException. Nói cách khác, chỉ có một player MIDI hay tone-sequence có thể được sử dụng bất cứ lúc nào.
  • Toolkit cho phép gọi phương thức playTone() nhiều lần đồng thời cho một note đơn, nhưng chỉ đảm bảo rằng tối thiểu có 4 lần làm việc thực sự. Phương thức playTone() có thể được gọi trong khi player MIDI hay tone-sequence được play.
  • Số lượng các player video được giới hạn bởi kích thước bộ nhớ heap, được chỉ định trong option Xheapsize của command emulator nếu sử dụng tiện ích command line hay từ Ktoolbar bằng cách chọn Edit->Preferences->Storage.
  • Số lượng các player audio WAV cũng được giới hạn bởi heap size.
  • Chỉ có một audio capture được sử dụng ở một thời điểm.

Lưu ý rằng MIDP giới hạn số lượng kết nối HTTP được mở đồng thời tối đa là 4.
Ví dụ: ví dụ này mô phỏng cách sử dụng Mobile Media API, với PlayerMIDlet cho phép người dùng nhập một URL của một file audio hay video và play nó.

import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.midlet.*;

public class PlayerMIDlet extends MIDlet implements
  CommandListener, PlayerListener, Runnable {
   private Display display;
   private Form form;
   private TextField url;
   private Command start = new Command("Play",
     Command.SCREEN, 1);
   private Command stop = new Command("Stop",
     Command.SCREEN, 2);
   private Player player;

   public PlayerMIDlet() {
      display = Display.getDisplay(this);
      form = new Form("Demo Player");
      url = new TextField("Enter URL:", "", 100,
            TextField.URL);
      form.append(url);
      form.addCommand(start);
      form.addCommand(stop);
      form.setCommandListener(this);
      display.setCurrent(form);
   }

   protected void startApp() {
      try {
         if(player != null && player.getState() ==
                  Player.PREFETCHED) {
           player.start();
         } else {
            defplayer();
            display.setCurrent(form);
         }
      }
      catch(MediaException me) {
         reset();
      }
   }

   protected void pauseApp() {
      try {
         if(player != null && player.getState() ==
                  Player.STARTED) {
            player.stop();
         } else {
            defplayer();
         }
      }
      catch(MediaException me) {
         reset();
      }
   }

   protected void destroyApp(
      boolean unconditional) {
      form = null;
      try {
         defplayer();
      }
      catch(MediaException me) {
      }
   }

   public void playerUpdate(Player player,
     String event, Object data) {
      if(event == PlayerListener.END_OF_MEDIA) {
         try {
            defplayer();
         }
         catch(MediaException me) {
         }
         reset();
      }
   }

   public void commandAction(Command c, Displayable d) {
      if(c == start) {      
         start();
      } else if(c == stop) {
         stopPlayer();
      }
   }

   public void start() {
      Thread t = new Thread(this);
      t.start();
   }

   // to prevent blocking, all communication should
   // be in a thread
   // and not in commandAction
   public void run() {
      play(getURL());
   }

   String getURL() {
     return url.getString();
   }

   void play(String url) {
      try {
         VideoControl vc;
         defplayer();
         // create a player instance
         player = Manager.createPlayer(url);
         player.addPlayerListener(this);
         // realize the player
         player.realize();
         vc = (VideoControl)player.getControl(
                  "VideoControl");
         if(vc != null) {
            Item video = (Item)vc.initDisplayMode(
                         vc.USE_GUI_PRIMITIVE, null);
            Form v = new Form("Playing Video...");
            StringItem si = new StringItem("Status: ",
                         "Playing...");
            v.append(si);
            v.append(video);
            display.setCurrent(v);
         }
         player.prefetch();
         player.start();
      }
      catch(Throwable t) {
         reset();
      }
   }

   void defplayer() throws MediaException {
      if (player != null) {
         if(player.getState() == Player.STARTED) {
            player.stop();
         }
         if(player.getState() == Player.PREFETCHED) {
            player.deallocate();
         }
         if(player.getState() == Player.REALIZED ||
                   player.getState() == Player.UNREALIZED) {
            player.close();
         }
      }
      player = null;
   }
    void reset() {
      player = null;
   }
    void stopPlayer() {
      try {
         defplayer();
      }
      catch(MediaException me) {
      }
      reset();
   }
}

Phương thức play() thực hiện các công việc sau:

  • Tạo một thể hiển Player.
  • Đăng ký MIDlet như là một PlayerListener, bởi vì MIDlet thực thi giao diện PlayerListener bằng cách định nghĩa phương thức playerUpdated(). Khi một sự kiện player phát sinh, thì tất cả các listener của player đã đăng ký sẽ được thông báo. Một sự kiện được ký hiệu là một string constant như PlayerListener.END_OF_MEDIA.
  • Nhận ra các Player.
  • Kiểm tra xem một VideoControl được trình bày hay chưa, nếu có thì khởi tạo một item hiển thị thành phần và thêm nó vào form để được hiển thị.
  • Prefetch player và start nó.

Các bài liên quan:

J2ME Mobile Media API(P1)
J2ME Mobile Media API(P2)