Nieuw in de market : VirtuaFly

Ik ben al een tijdje bezig met een SoundBoard. Het is VirtuaFly geworden, een vrij simpele app die de gebruiker in staat stelt een virtuele vlieg te laten horen. De vlieg kan allerlei avonturen beleven; Verliefd worden, in een shredder terechtkomen en zelfs een kamikaze-zelfmoord-missie uitvoeren. Ik heb geen idee hoe deze app wordt ontvangen door het publiek, maar het werken met geluidsbestanden gaf weer een heel nieuwe dimensie aan het ontwikkelen. Ik ben begonnen met ogg-bestanden. Deze worden het best door de verschillende delen van het Android besturingssysteem verwerkt. De SoundPool-methode die ik gebruikte, bleek niet toereikend. Een Heap Size Overflow was het gevolg.

ERROR/AudioCache(34): Heap size overflow! req size: 1052672, max size: 1048576

Dit komt, doordat het Android systeem het ogg geluidsbestand uitpakt in het werkgeheugen. Afhankelijk van het aantal kanalen, de samplerate en andere variabelen, kan dit een groot tot zeer groot bestand tot gevolg hebben. Het vreemde is, dat de applicatie wel gewoon opstart en blijft werken. De geluidsbestanden worden afgespeeld tot op het moment dat het geheugen vol was. In eerste instantie kortte ik de geluidsbestanden zo ver mogelijk in. Pas later vond ik een andere (makkelijker) methode om geluidsbestanden af te spelen ; MediaPlayer.
Vergeleken met Applez en Flitswoorden is de code voor deze app zeer eenvoudig.

Je maakt een Mediaplayer instantie aan met de volgende regel;

final MediaPlayer mp1 = MediaPlayer.create(this, R.raw.fly_start_01);

Daarna kun je dit geluidsbestand afspelen met ;

mp1.start();

Let op ; je kunt niet zomaar een geluid dat je hebt gestopt met mp1.stop(); opnieuw starten. Er is een prepare() voor nodig. Zie onderstaande state diagram :

Hieronder volgt de volledige code voor VirtuaFly (gereduceerd tot 2 knoppen). Als je behoefte hebt aan een complete tutorial voor een SoundBoard, laat dat dan even weten.. dan kan ik die maken ;).

Op mn werk heb ik ondertussen door toeval kennis gemaakt met MQTT (een message Queueing systeem). Met dit systeem zou ik vliegen die in een bepaalde straal gebruikt worden, met elkaar kunnen synchroniseren. Ik denk dat ik daar wat tijd ga besteden. Lijkt me cool om 40.000 vliegen in bijvoorbeeld een EK Stadion op hetzelfde moment door de shredder te halen..

package happyworx.nl.VirtuaFly;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.RelativeLayout;

import com.google.ads.AdView;

public class VirtuaFlyActivity extends Activity {
	private AdView adView;

	private SoundManager mSoundManager;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// Create the adView
		// adView = new AdView(this, AdSize.BANNER, "CODE");

		// Lookup your LinearLayout assuming it’s been given
		// the attribute android:id="@+id/mainLayout"
		RelativeLayout layout = (RelativeLayout) findViewById(R.id.RelativeLayout1);

		// Add the adView to it
		// layout.addView(adView);

		// Initiate a generic request to load it with an ad
		// AdRequest adRequest = new AdRequest();
		// adRequest.addTestDevice(AdRequest.TEST_EMULATOR); // Emulator
		// adRequest.addTestDevice("DEVICECODE"); // Test
		// Android Device
		AdView adView = (AdView) this.findViewById(R.id.adView);

		mSoundManager = new SoundManager();
		mSoundManager.initSounds(getBaseContext());
		final MediaPlayer mp1 = MediaPlayer.create(this, R.raw.fly_start_01);
		final MediaPlayer mp2 = MediaPlayer.create(this, R.raw.fly_buzz_01);
		final MediaPlayer mp3 = MediaPlayer.create(this, R.raw.fly_end_01);
		final MediaPlayer mp4 = MediaPlayer.create(this, R.raw.fly_swatter_01);
		final MediaPlayer mp5 = MediaPlayer.create(this, R.raw.fly_drown_01);
		final MediaPlayer mp6 = MediaPlayer.create(this, R.raw.fly_love_01);
		final MediaPlayer mp7 = MediaPlayer.create(this, R.raw.fly_shredder_01);
		final MediaPlayer mp8 = MediaPlayer.create(this, R.raw.fly_frog_01);
		final MediaPlayer mp9 = MediaPlayer.create(this, R.raw.fly_kamikaze_01);

		ImageButton SoundButton1 = (ImageButton) findViewById(R.id.imageButton1);
		SoundButton1.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (mp2.isPlaying()) {
					mp2.pause();
				}
				mp1.start();
				while (mSoundManager.mAudioManager.isMusicActive()) {
				}
				findViewById(R.id.imageButton2).setPressed(true);
				mp2.setLooping(true);
				mp2.start();
			}
		});

		ImageButton SoundButton2 = (ImageButton) findViewById(R.id.imageButton2);
		SoundButton2.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp2.start();

			}
		});

		ImageButton SoundButton3 = (ImageButton) findViewById(R.id.imageButton3);
		SoundButton3.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp3.start();
				findViewById(R.id.imageButton2).setPressed(false);
				mp2.pause();
			}
		});

		ImageButton SoundButton4 = (ImageButton) findViewById(R.id.imageButton4);
		SoundButton4.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp4.start();
				findViewById(R.id.imageButton2).setPressed(false);
				mp2.pause();
			}
		});

		ImageButton SoundButton5 = (ImageButton) findViewById(R.id.imageButton5);
		SoundButton5.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp5.start();
				findViewById(R.id.imageButton2).setPressed(false);
				mp2.pause();
			}
		});

		ImageButton SoundButton6 = (ImageButton) findViewById(R.id.imageButton6);
		SoundButton6.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				findViewById(R.id.imageButton2).setPressed(false);
				mp2.pause();
				mp6.start();
				while (mSoundManager.mAudioManager.isMusicActive()) {
				}
				findViewById(R.id.imageButton2).setPressed(true);
				mp2.start();
			}
		});

		ImageButton SoundButton7 = (ImageButton) findViewById(R.id.imageButton7);
		SoundButton7.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp7.start();
				findViewById(R.id.imageButton2).setPressed(false);
				mp2.pause();
			}
		});

		ImageButton SoundButton8 = (ImageButton) findViewById(R.id.imageButton8);
		SoundButton8.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp2.pause();
				mp8.start();
				findViewById(R.id.imageButton2).setPressed(false);
			}
		});
		ImageButton SoundButton9 = (ImageButton) findViewById(R.id.imageButton9);
		SoundButton9.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				mp2.pause();
				mp9.start();
				findViewById(R.id.imageButton2).setPressed(false);
			}
		});

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent browserIntent = new Intent(Intent.ACTION_VIEW,
				Uri.parse("http://happyworx.nl/blog"));
		startActivity(browserIntent);

		return true;
	}

	@Override
	public void onDestroy() {
		if (adView != null) {
			adView.destroy();
		}
		super.onDestroy();
	}
}
You can leave a response, or trackback from your own site.

2 Responses to “Nieuw in de market : VirtuaFly”

  1. Dennis schreef:

    Ziet er goed uit, als ik binnenkort Android tot mijn beschikking heb zal ik de app eens bekijken.

    Een vraagje over de code:

    Waarom is de code onder SoundButton1 langer dan bij SoundButton2. Dan heb ik het over

    findViewById(R.id.imageButton2).setPressed(true);
    mp2.setLooping(true);
    mp2.start();

    Bij de rest van de Soundsbuttons staat mp2.pause(); er nog bij.
    Waarom jusit mp2.pause? Ik zie hier de logica niet van? (waarschijnlijk omdat ik nog nooit een regel heb geprogrammeerd)

    Voor de rest ziet er weer goed uit.

    Keep up the good work!
    Dennis

    • admin schreef:

      Leuk! Je kunt ook een Emulator installeren en Android op je PC draaien (zie mijn tutorials).

      mp2.pause(); Omdat mp2 het geluid is van een rechtdoor vliegende vlieg. Als de vliegenmepper langskomt, moet het geluid van de rechtdoor vliegende vlieg stoppen ;).

Leave a Reply