goo blog サービス終了のお知らせ 

gooブログはじめました!

写真付きで日記や趣味を書くならgooブログ

android mp3およびoggファイルのループ再生

2010-10-16 21:27:37 | android

android mp3およびoggファイルのループ再生

<form>

android mp3およびoggファイルのループ再生

mp3を使用したゲーム等を作成した場合、無料ならライセンス料はかからないが有料にするとライセンス料金がが必要になるためできればサウンドはoggファイルを使用する。oggファイルは商用利用可能なライセンスのため、
ライセンス料金や制約を気にする必要はない。そのためandroidでoggファイルを再生するにはMediaPlyerクラスを使用する。
androidでmp3,oggファイルを再生するためにはMediaPlayerクラスを使用する。注意点としてはmp3を使用する場合で
MediaPlayer.createを使用する場合はMediaPlayer.prepare()メソッドを呼ばす,assetsフォルダ下のmp3、oggファイルを再生する場合はMediaPlayer.prepare()メソッドが必要という事。
Mediaplayerのmanualには「Convenience method to create a MediaPlayer for a given Uri. On success, prepare() will already have been called and must not be called again.」と記述されていた。
/data/data/パッケージ名/の下でしか、ファイルの読み込み、書き込みとうができないため
ogg,mp3ファイルはassetsフォルダもしくはresource/rawフォルダを作成してその下に格納する必要がある。


ogg,mp3でも共通に呼び出すためには下記のように使用する


//resource/assets/music/の下にmp3,oggファイルがある どちらもloop再生可能
//final AssetFileDescriptor assetFileDescritor = m_Context.getAssets().openFd( "music/est_battle2.mp3" );    
final AssetFileDescriptor assetFileDescritor = m_Context.getAssets().openFd( "music/wagner_the_ride_of_the_valkyries.ogg" );

media2.reset();
media2.setDataSource( assetFileDescritor.getFileDescriptor(),
assetFileDescritor.getStartOffset(), assetFileDescritor.getLength() );
media2.setLooping(true);

media2.setAudioStreamType(AudioManager.STREAM_MUSIC);
assetFileDescritor.close();
media2.prepare();   
media2.start();


mp3のライセンス
mp3のライセンス料金が必要になるのはドイツのFraunhofer-Gesellschaft社とフランスのThomson社が発明した音声圧縮アルゴリズム(mp3のデコード)を使用する場合で
Lame(LAME Ain't an MP3 Encoder)を利用した場合はライセンス料金は必要ない。
Lameは上記の会社の音声圧縮アルゴリズムを使用しないで、mp3にデコードしているため。
普通にmp3ファイルのtagをみてもどちらのアルゴリズムを使用しているかは分からないので
結局,面倒な事を回避するために音楽も配布する場合は、oggファイルがベストな選択
だと思う。



以下がサンプル。android sdk 2.1  Desire 2.2で mp3,oggどちらもループ再生できることを確認

<textarea rows="8" cols="75" readonly="readonly">package org.jp.MediaPlayerTest; import android.app.Activity; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.os.Bundle; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import java.io.File; import java.io.IOException; public class MediaPlayerTest extends Activity {     /** Called when the activity is first created. */     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.main); android.view.View b = this.findViewById( R.id.btn1 ); android.view.View b2 = this.findViewById( R.id.btn2 ); android.view.View b3 = this.findViewById( R.id.btn3 ); android.view.View b4 = this.findViewById( R.id.btn4 ); android.view.View b5 = this.findViewById( R.id.btn5 ); android.view.View b6 = this.findViewById( R.id.btn6 ); ClickListener listener = new ClickListener(); b.setOnClickListener( listener ); b2.setOnClickListener( listener ); b3.setOnClickListener( listener ); b4.setOnClickListener( listener ); b5.setOnClickListener( listener ); b6.setOnClickListener( listener ); Button bb = (Button)b; bb.setText( "play assets ogg file  play loop" ); Button b22 = (Button)b2; b22.setText( "play res/raw mp3 file play loop" ); Button b33 = (Button)b3; b33.setText( "stop" ); Button b44 = (Button)b4; b44.setText("MusicPlayerMgr test" ); Button b55 = (Button)b5; b55.setText("MusicPlayerMgr stop" ); listener.SetContest( this );     } } class ClickListener implements OnClickListener { private Context m_Context; private static String strAssetspath = ""; private static MediaPlayer m_mediaPlayer; public void SetContest(Context cnt) { m_Context = cnt; } public void onClick(View v) { MediaPlayer mediaPlayer = new MediaPlayer(); switch (v.getId()) { case R.id.btn1: Log.d("meida","btn1 click"); try { //ogg file loop ok final AssetFileDescriptor assetFileDescritor = m_Context.getAssets().openFd( "music/wagner_the_ride_of_the_valkyries.ogg" ); mediaPlayer.setDataSource( assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength() ); mediaPlayer.prepare(); mediaPlayer.setLooping(true); mediaPlayer.start(); } catch(Exception e) { } break; case R.id.btn2: Log.d("meida","btn2 click"); //MediaPlayer mediaPlayer = new MediaPlayer(); try { //androidでは/data/data/パッケージ名/ の下にしかアクセスできないため //res/rawの下にoggファイルを配置してみたが、再生されなかった //String dst = "/data/data/" + this.getPackageName() + "/dst.txt" // resouce/raw/wagner_the_ride_of_the_valkyries.oggは再生されない。nullはかえらないが再生はされない //mediaPlayer = MediaPlayer.create( m_Context, R.raw.wagner_the_ride_of_the_valkyries ); //mp3 ok mediaPlayer = MediaPlayer.create(  m_Context, R.raw.est_battle2 ); //mediaPlayer.prepare();  //mp3再生の場合、prepareをやるとmediaPlayerがnullになる mediaPlayer.setLooping(true); mediaPlayer.start(); } catch(Exception e) { //MediaPlayer.prepare()を実行した場合, nullが返却される Log.d("meida","btn2 click:" + e.getMessage()); } break; case R.id.btn3: Log.d("meida","btn3 click"); mediaPlayer.stop(); break; case R.id.btn4: Log.d("meida","btn4 click"); break; case R.id.btn5: Log.d("meida","btn5 click"); MusicPlayerMgr.stop( 0 ); break; case R.id.btn6: Log.d("meida","btn6 click"); try { //resource/assets/music/の下にmp3,oggファイルがある どちらもloop再生可能 //final AssetFileDescriptor assetFileDescritor = m_Context.getAssets().openFd( "music/est_battle2.mp3" ); final AssetFileDescriptor assetFileDescritor = m_Context.getAssets().openFd( "music/wagner_the_ride_of_the_valkyries.ogg" ); media2.reset(); media2.setDataSource( assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength() ); media2.setLooping(true); media2.setAudioStreamType(AudioManager.STREAM_MUSIC); assetFileDescritor.close(); media2.prepare();  media2.start(); } catch ( Exception e ) { // TODO 自動生成された catch ブロック e.printStackTrace(); Log.d("meida","btn6 clicked" + e); } break; case R.id.btn7: Log.d("meida","btn7 click"); break; } } }; </textarea>

</form>

androidのroj (android 2D game engine)

2010-10-11 14:19:23 | android

androidの2D Game Engineのrokonの使い方 

公式ページ:http://www.rokonandroid.com/

rokon.jarのリンクおよび、AndroidManfest.xmlに横画面を固定する処理を記述する必要がある。

eclipseの設定

1.適当なprojectを作成  (HTC desireのandroid2.2でも実機で動作することは確認済み) android sdkは1.5以上なので、xperia,desire,auのISシリーズで開発は可能と思われる。

2.projectを作成したら、rokon公式のsampleのlibフォルダごとコピーして作成したprojectの下に格納。 以下のようにする。
  libs -  rokon-2-0-3.jar
           armeabi(フォルダ) - libgdx.so
3.そして[libs] - [rokon-2-0-3.jar]を右クリックしてコンテキストメニューから
[ビルドパスの構成を選択し、[ライブラリー]タブの[JARの追加]ボタンをクリックして
作成した自分のprojectにある  [libs\rokon-2-0-3.jar]ファイルを追加する。
4.AndroidManifest.xmlで横画面を固定するため以下を追記する。
android:screenOrientation="landscape" 

AndroidManifest.xmlを追加したり編集するとビルド時にエラーがおきてAndroidManifest.xml(1)
AndroidManifest.xml(2)と増えていくので、余計なAndroidManifest.xml(X)を全てけした後に
いったんrokon.jarを削除して、ふたたびJARファイルを追加する手順が必要。そうしないとbuildで毎回、失敗する。


android fps計算

2010-08-28 08:51:52 | android

androidでfpsを計算するclassを作成

fps計算

<form>

<textarea rows="8" cols="75" readonly="readonly">package org.jp.Box2dTest; import java.text.DecimalFormat; import java.util.LinkedList; import android.os.SystemClock; import android.util.Log; public class FPS {     private int              m_sampleNum;                     // サンプル数     private float            m_fps;                           // fps     private long             m_oldTime;                       // 前回getFPSを呼び出した時間     private long             m_diffTime;                      // 前回の時間差分     private long             m_sumTime;                       // 経過時間の和     // private Vector<Long> _timeList; //経過時間のテーブル     private LinkedList<Long> m_timeList;     private DecimalFormat    df = new DecimalFormat( "0.0" );         // ------ここから移動平均によってFPSを算出している(fpsにあわせるためのwait処理なし)     public void Init()     {         // sample数の指定しなければ10回サンプリング         Init( 10 );     }     /**      * @param iSampleNum サンプリング周波数(精度が必要な場合はこの値を増やす)      */     public void Init(int iSampleNum)     {         // サンプリング数         m_sampleNum = iSampleNum;         m_oldTime = 0;         m_diffTime = 0;         m_sumTime = 0;         //サンプリングされたものを、移動平均で算出するためLinkedListを使う         m_timeList = new LinkedList<Long>();                 for ( int i = 0; i <iSampleNum; i++ )         {             m_timeList.add( 0L );         }     }     /**      * 移動平均によってFPSを算出する。      *      * 移動平均説明(サンプリング数5の場合)      * 1回目のデータ算出   10,11,12,13,15,14      *      * 1回目のfps 計算      (10 + 11 + 12 + 13 + 15) / 5      * 2回目のfps計算        (11 + 12 + 13 + 15 + 14 ) / 5   (一番古いデータは計算に使わない)      */     public void calcFPS()     {         long nowTime = SystemClock.uptimeMillis();         m_diffTime = nowTime -m_oldTime;         m_oldTime = nowTime;         m_sumTime += m_diffTime;         // // double doldestdata = _timeList.get( location )         m_timeList.add( m_diffTime );         // // 一番古いやつは削除(移動平均で算出)         m_sumTime -= m_timeList.poll();         // //  平均時間         long tmp = m_sumTime /m_sampleNum;         // FPS         if (tmp !=0l)         {             m_fps = 1000.0f /tmp;         }         else         {             m_fps = 0.0f;         }     }     /**      * 指定したサンプリング数で算出した現在のFPS      *      * @return 現在のFPS (wait処理なし)      */     public String GetFPS()     {         return df.format( m_fps );     }         // ------ここまで移動平均によってFPSを算出している(fpsにあわせるためのwait処理なし)         // ----- ここから FPSを合わせるためのwait処理あり()    //DxLibの龍神録を参考にしたFPS計算 ほぼそのまま javaに変更しただけ     private static final int FRAME = 40;   //FPS  この部分を変更すればfpsを変更できる。 携帯では40fps程度でok 60fpsはオブジェクトを増やすときつい     private int              m_fps_count;     private long             m_count0t;     private long[]           F     = new long[FRAME];     private static long      m_frame;     private double           m_ave;     /**      * メンバ変数で設定したFPSにあわせるためのwait処理      */     public void fps_wait()     {         long term, gnt; if( m_fps_count ==0 )         {             if ( m_frame ==0 )             {                 // 最初のフレーム                 term = 0;             }             else             {                 // //前回記録した時間を元に計算                 term = m_count0t +1000 -System.currentTimeMillis();                 // term = _count0t + 1000000000 - System.nanoTime();             }         }         else         {             // 待つべき時間=現在あるべき時刻-現在の時刻             term = m_count0t +m_fps_count *( 1000 /FRAME )                     -System.currentTimeMillis();         }         if ( term > 0 )         {             try             {                 Log.d( "MyLOG", "term:" +String.valueOf( term ) );                 Thread.sleep( term );             } catch ( InterruptedException ex )             {                 ex.printStackTrace();                 Log.d( "MyLOG", "Thread sleep exception" );             }         }         gnt = System.currentTimeMillis(); if( m_fps_count ==0 )         {             // 指定されたフレームごとに基準をつくりなおし         //40 fpsの場合  40 % 40 で0になる,         m_count0t = gnt;         }         F[m_fps_count] = gnt -m_frame;         m_frame = gnt; if( m_fps_count ==FRAME -1 )         {         m_ave = 0;             for ( int count = 0; count <FRAME; count++ )             {              m_ave += F[count];             }             m_ave /= FRAME;         }         m_fps_count = ( ++m_fps_count ) %FRAME;     }     /**      * 現在のFPS      *      * @return 現在のFPS (wait処理つき)      */ public String GetFPS2() { if ( m_ave !=0 ) { double fps = ( 1000 /m_ave ); return df.format( fps ); } else { return ""; } }     } </textarea>

</form>

androidログ用クラスの作成

2010-06-12 12:07:39 | android

androidログ出力用クラス

androidのutil.logのログを使いやすくする。ログにはファイル名、行番号、関数名と任意のデータを追記する。
c,C++のように__FILE__,__LINE__,__function__マクロと同等な動作をするようにする。
下記ログ用クラスを使うために
1. AndroidManifest.xmlにdebugフラグをいれておく。android:debuggable="true"

  <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true">

 

<textarea rows="8" cols="75" readonly="readonly"><application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true"> </textarea>

2.ログを使用したいクラスのContextを指定する。 MyUtility.ctx_main = this;
3.ログを出力したいところで下記のようする。これで、LogCatの出力には「ファイル名:行数:関数名:書き込んだログ」 MyUtility.MY_LOG( "MyLOG", "on click log" );



<form>

androidログ出力用クラス

<textarea readonly="readonly" cols="75" rows="8">import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.util.Log; public final class MyUtility { public static Context ctx_main; /** * @param ctx *            Contextを指定する * @return AndroidManifest.xmlでandroid:debuggablがtrueかfalseか */ public static boolean isDebugAble(Context ctx) { PackageManager manager = ctx.getPackageManager(); ApplicationInfo appInfo = null; try { appInfo = manager.getApplicationInfo( ctx.getPackageName(), 0 ); Thread.currentThread().getStackTrace()[1].getMethodName(); } catch ( NameNotFoundException e ) { Log.e( e.toString(), null ); return false; } if (( appInfo.flags &ApplicationInfo.FLAG_DEBUGGABLE ) ==ApplicationInfo.FLAG_DEBUGGABLE) return true; return false; } /** * @param ctx *            Contextを指定する * @param TAG *            logのTAG用の文字列 * @param msg *            デバッグ用のメッセージを指定 */ public static void MY_LOG(Context ctx, String TAG, String msg) { if (isDebugAble( ctx )) { String strData = Thread.currentThread().getStackTrace()[3]         .getFileName()         +":"         +Thread.currentThread().getStackTrace()[3].getLineNumber()         +" "         +Thread.currentThread().getStackTrace()[3].getMethodName(); Log.d( TAG, strData +":" +msg ); } } /** * @param TAG * logのTAG用の文字列 * @param msg * デバッグ用のメッセージを指定 */ public static void MY_LOG(String TAG, String msg) { if (ctx_main !=null) { if (isDebugAble( ctx_main )) { String strData = Thread.currentThread().getStackTrace()[3]         .getFileName()         +":"         +Thread.currentThread().getStackTrace()[3]                 .getLineNumber()         +" "         +Thread.currentThread().getStackTrace()[3]                 .getMethodName(); Log.d( TAG, strData +":" +msg ); } } } /** * @return ファイル名:行番号:関数名を返す (事前にContextを取得している必要あり) */ public static String GetFileLineMethod() { return Thread.currentThread().getStackTrace()[3].getFileName() +":"         +Thread.currentThread().getStackTrace()[3].getLineNumber() +" "         +Thread.currentThread().getStackTrace()[3].getMethodName(); } /** * @param context * @return version codeを返す */ public static int getVersionCode(Context context) { int ver; try { ver = context.getPackageManager().getPackageInfo(         context.getPackageName(), 1 ).versionCode; } catch ( NameNotFoundException e ) { ver = -1; } return ver; } /** * @param context * @return versionを返す */ public static String getVersionName(Context context) { String ver; try { ver = context.getPackageManager().getPackageInfo(         context.getPackageName(), 1 ).versionName; } catch ( NameNotFoundException e ) { ver = ""; } return ver; } } </textarea>

</form></application>

HTC desire実機デバッグ

2010-05-21 00:47:55 | android

android実機の設定

android_winusb.infの設定

eclipseの設定

android実機の設定


<textarea rows="8" cols="75" readonly="readonly">1.[設定] - [アプリケーション] - [不明な情報元]にチェック 2.[設定] - [アプリケーション] - [開発] - [USBデエバッグ]にチェック </textarea>



.androidsdkをインストールしたフォルダの下のusb_driverの「android_winusb.inf」ファイルを編集し設定を追加する。その後 USB接続したHTC desireをPCにつなげandroidsdkフォルダ下にある[usb_driver]を指定する。再起動は必要ない。
[Google.NTx86],[Google.NTamd64]セクションの下に下記を追記、
;
; HTC Desire
%SingleAdbInterface%        = USB_Install, USB\VID_0BB4&PID_0C87
%CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C87&MI_01

android_winusb.infの設定


<form>

android実機の設定

<textarea rows="8" cols="75" readonly="readonly">; ; Android WinUsb driver installation. ; [Version] Signature           = "$Windows NT$" Class               = AndroidUsbDeviceClass ClassGuid           = {3F966BD9-FA04-4ec5-991C-D326973B5128} Provider            = %ProviderName% DriverVer           = 08/11/2009,2.0.0010.00002 CatalogFile.NTx86   = androidwinusb86.cat CatalogFile.NTamd64 = androidwinusba64.cat ; ; This section seems to be required for WinUsb driver installation. ; If this section is removed the installer will report an error ; "Required section not found in INF file". ; [ClassInstall32] Addreg = AndroidWinUsbClassReg [AndroidWinUsbClassReg] HKR,,,0,%ClassName% HKR,,Icon,,-1 [Manufacturer] %ProviderName% = Google, NTx86, NTamd64 [Google.NTx86] ; HTC Dream %SingleAdbInterface%        = USB_Install, USB\VID_0BB4&PID_0C01 %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C02&MI_01 %SingleBootLoaderInterface% = USB_Install, USB\VID_0BB4&PID_0FFF ; HTC Magic %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C03&MI_01 ; ;Moto Sholes %SingleAdbInterface%        = USB_Install, USB\VID_22B8&PID_41DB %CompositeAdbInterface%     = USB_Install, USB\VID_22B8&PID_41DB&MI_01 ; ;Google NexusOne %SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_0D02 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_0D02&MI_01 %SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4E11 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E12&MI_01 ; ; HTC Desire %SingleAdbInterface%        = USB_Install, USB\VID_0BB4&PID_0C87 %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C87&MI_01 [Google.NTamd64] ; HTC Dream %SingleAdbInterface%        = USB_Install, USB\VID_0BB4&PID_0C01 %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C02&MI_01 %SingleBootLoaderInterface% = USB_Install, USB\VID_0BB4&PID_0FFF ; HTC Magic %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C03&MI_01 ; ;Moto Sholes %SingleAdbInterface%        = USB_Install, USB\VID_22B8&PID_41DB %CompositeAdbInterface%     = USB_Install, USB\VID_22B8&PID_41DB&MI_01 ; ;Google NexusOne %SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_0D02 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_0D02&MI_01 %SingleAdbInterface%        = USB_Install, USB\VID_18D1&PID_4E11 %CompositeAdbInterface%     = USB_Install, USB\VID_18D1&PID_4E12&MI_01 ; ; HTC Desire %SingleAdbInterface%        = USB_Install, USB\VID_0BB4&PID_0C87 %CompositeAdbInterface%     = USB_Install, USB\VID_0BB4&PID_0C87&MI_01 [USB_Install] Include = winusb.inf Needs   = WINUSB.NT [USB_Install.Services] Include     = winusb.inf AddService  = WinUSB,0x00000002,WinUSB_ServiceInstall [WinUSB_ServiceInstall] DisplayName     = %WinUSB_SvcDesc% ServiceType     = 1 StartType       = 3 ErrorControl    = 1 ServiceBinary   = %12%\WinUSB.sys [USB_Install.Wdf] KmdfService = WINUSB, WinUSB_Install [WinUSB_Install] KmdfLibraryVersion  = 1.7 [USB_Install.HW] AddReg  = Dev_AddReg [Dev_AddReg] HKR,,DeviceInterfaceGUIDs,0x10000,"{F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}" [USB_Install.CoInstallers] AddReg    = CoInstallers_AddReg CopyFiles = CoInstallers_CopyFiles [CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01007.dll,WdfCoInstaller","WinUSBCoInstaller.dll" [CoInstallers_CopyFiles] WinUSBCoInstaller.dll WdfCoInstaller01007.dll [DestinationDirs] CoInstallers_CopyFiles=11 [SourceDisksNames] 1 = %DISK_NAME%,,,\i386 2 = %DISK_NAME%,,,\amd64 [SourceDisksFiles.x86] WinUSBCoInstaller.dll  = 1 WdfCoInstaller01007.dll = 1 [SourceDisksFiles.amd64] WinUSBCoInstaller.dll  = 2 WdfCoInstaller01007.dll = 2 [Strings] ProviderName                = "Google, Inc." SingleAdbInterface          = "Android ADB Interface" CompositeAdbInterface       = "Android Composite ADB Interface" SingleBootLoaderInterface   = "Android Bootloader Interface" WinUSB_SvcDesc              = "Android USB Driver" DISK_NAME                   = "Android WinUsb installation disk" ClassName                   = "Android Phone" </textarea>

</form>
<form>

eclipseの設定


<textarea rows="8" cols="75" readonly="readonly">1.なんでも良いのでテストアプリを作成する。 2.[実行構成] - [Androidアプリケーション] - [ターゲット]タブ -[手動作]にチェック - [実行]をクリック 3.[Android Device Chooser]で実機が選択できるのでそれを指定すれば、eclipseから実機に自作アプリをインストール可能。 </textarea>

</form>