Androidで音を再生してみる

今回はSoundPoolクラスを使って音を再生してみたいと思います。再生する音楽ファイルはogg形式でassetsフォルダ配下に格納されているものを使用するので、前回、投稿のAssetManagerも使用します。

やりたいこと

  1. SoundPoolオブジェクトを取得する
  2. assetsフォルダ配下に保存されたoggファイルのFileDescriptorを取得する
  3. 音源をメモリーにloadする
  4. 音を再生する

「Play sound」ボタンを押すと音が再生されます

実装の要点を下記にまとめます

1. 音量ボタンが音楽のStreamを制御するように紐付ける

setVolumeControlStream(AudioManager.STREAM_MUSIC);

2. SoundPoolオブジェクトを取得

private static final int SOUND_NUM = 10;
private SoundPool mSp;

mSp = new SoundPool(SOUND_NUM, AudioManager.STREAM_MUSIC, 0);

3. AssetManagerを取得し、AssetFileDescriptorを取得

private static final String AUDIO = "metal.ogg";

AssetManager am = getAssets();

try {
    AssetFileDescriptor fd = am.openFd(AUDIO);
} catch (IOException e) {
    e.printStackTrace();
}

4. FileDescripterを使って、使用するサウンドをloadしIDを取得する

private int mId = -1;

mId = mSp.load(fd, 1);

5. サウンドのIDを指定して再生

mSp.play(mId, 1, 1, 0, 0, 1);

6. 使わなくなったサウンドをunloadして、SoundPoolはreleaseする

mSp.unload(mId);
mSp.release();

では実装です

続きを読む

軽くAssetManager

連日の投稿です。今回はassetsフォルダにあるテキストファイルを読み込んで、TextViewに表示してみようと思います。

やりたいこと

  1. AssetManagerを取得する
  2. assetsフォルダのテキストファイルを読み込む
  3. 読み込んだファイルをTextViewに表示する

こんな感じで読み込んだassets/lorem.txtの内容を表示

実装の要点を下記にまとめます

1. Context#getAssets()メソッドでAssetManagerを取得

AssetManager assets = getAssets();

2. 読み込みたいファイルのassetsフォルダからの相対パス名を引数として渡しInputStreamを取得する

private static final String TEXT_NAME = "lorem.txt";
InputStream is = null;
        
try {
	is = assets.open(TEXT_NAME);
} catch (IOException e) {
	e.printStackTrace();
} 

3. InputStreamをByteArrayOutputStreamに読みこんで、それからStringを作成する

private String getText(InputStream is) throws IOException{
    	ByteArrayOutputStream bs = new ByteArrayOutputStream();
    	byte[] bytes = new byte[4096];
    	int len = 0;
    	while((len = is.read(bytes)) > 0){
    		Log.d(TAG, "len = " + len);
    		bs.write(bytes, 0, len);
    	}
        //テキストファイルがUTF8でエンコードされているので第2引数に指定
    	return new String(bs.toByteArray(), "UTF8");
    }

では実装です

続きを読む

久しぶりに軽くAndroidでSensorManager

久しぶりのBlogを更新。今まで何をやっていたかというと、業務が開発と離れていたためサボっていました...。ということで、久しぶりに地道に頑張ってBlog更新して行こうかと思います。ということで、今回は軽めにSensorManagerから加速度センサーを取得し、各軸の加速度をTextViewに表示してみたいと思います。

やりたいこと

  1. SensorManagerを取得する
  2. 加速度センサーのSensorオブジェクトを取得する
  3. 加速度を取得する

こんな感じで加速度を表示

実装の要点を下記にまとめます

1. SensorMangerを取得

SensorManager manager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

2. 加速度センサーを取得

Sensor ac = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);

3. 加速度センサーにSensorEventListerを登録

manager.registerListener(this, ac, SensorManager.SENSOR_DELAY_GAME)

4. SensorEventListener#onSensorChanged()内で加速度を取得

        @Override
	public void onSensorChanged(SensorEvent event) {
		mBuilder.setLength(0);
		mBuilder.append("x: ");
		//values[0]にはx軸の加速度
		mBuilder.append(event.values[0]);
		mBuilder.append(", y: ");
		//values[1]にはy軸の加速度
		mBuilder.append(event.values[1]);
		mBuilder.append(", z: ");
		//values[2]にはz軸の加速度
		mBuilder.append(event.values[2]);
		mTextView.setText(mBuilder.toString());
	}

では実装です

続きを読む

Fragmentを勉強する - part2

今回も前回の続きでFragmentに関しての覚え書きです。今回はここから

Managing Fragment

Fragmentを管理するにはFragmentManagerを使用する。Activity#getFragmentManager()でFragmentManagerを取得する

FragmentManagerで出来る事の例

    • FragmentManager#findFragmentById()やFragmentManager#findFragmentByTag()でFragmentを取得する
    • FragmentManager#popbackStack()でback stackからFragmentを取得する(Back keyで戻る行為と同じ)
    • FragmentManager#addOnBackStackChangedListener()でback stackのlistenerを登録する

Performing Fragment Transactions

    • 1回のcommitでやりとりされる変更をtransactionと呼ぶ
    • 1つのtransactionにFragmentに対する変更をFragmentTransaction#add(), FragmentTransaction#remove(), FragmentTransaction#replace()といったmethodでまとめる事が出来る
    • UserがBack keyで以前の状態に戻るにはFragmentTransaction#commit()をする前にFragmentTransaction#addToBackStack()を呼ぶ
//FragmentとFragmentTransactionを生成する
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

//fragment_container viewにあるFragmentを生成したFragmentで入れ替えて
//このreplace transactionをback stackに追加する
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// transactionをcommitする
transaction.commit();
    • いくつかの変更を追加したtransactionをcommitする前にback stackに追加するとBack keyで加えられた変更が一気に巻き戻される
    • Transactionに変更を加える順番は影響しない。ただし、ひとつの親viewに複数のFragmentが付加される場合はaddされた順番でview hierarchyに現れる
    • Fragmentをremoveするtransactionをcommitする前にback stackに登録しなければ、そのtransactionがcommitされると、そのFragmentはdestroyされる。一方、登録されたFragmentはstopされる
    • Transaction毎にFragmentTransaction#setTransition()でFragmentのAnimationをすることが出来る
    • Transactionは即座には実行されず、UI threadが実行可能になった際に実行される。即座に実行したい場合はFragmentManager#executePendingTransactions()を呼ぶ
    • commitはActivityがonSaveInstanceState()が呼ばれる前に実行されなければいけない。状態を残さずにcommitしても良い場合はFragmentTransaction#commitAllowingStateLoss()で実行する

Communicating with the Activity

FragmentはActivityから独立しているがActivityと直接のつながりがある

//現在つながりのあるActivityを取得するにはFragment#getActivity()を呼ぶ
View listView = getActivity().findViewById(R.id.list);
//逆にActivityからFragmentを取得するには
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

Creating event callbacks to the activity

Activityとeventを共有したい場合はcallback interfaceを定義しActivityに実装させる

1. Interfaceを宣言する

public static class FragmentA extends ListFragment {
    ...
    // Activityがこのinterfaceを実装する
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}

2. Fragment#onAttach()で渡されるActivityをListener登録する

public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...
}

3. Eventを取得したらListener登録されたActivityに通知する

public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        //EventをListener登録されたActivityに通知
        mListener.onArticleSelected(noteUri);
    }
    ...
}

Adding items to the Action Bar

FragmentはOptionMenu(結果的にはAction Bar)にMenu itemを追加する事が出来る

    1. Fragment#onCreate()でFragment#setHasOptionsMenu()を呼び、設定を行う
    2. Fragment#onCreateOptionsMenu()で実装を行う

Fragment内のViewに対してFragment#registerForContextMenu()でContext menuを提供する様出来る

*ただし、Menu itemに対するcallbackはActivityが始めに受け取り、Activityで処理を完結しなかった時のみFragmentに通知される



Fragment callbacks

Handling the Fragment Lifecycle

Fragmentのlife cycleはActivityのlife cycleと似ている

    • Resumed

Fragmentが実行中のActivity内で表示される時

    • Paused

他のActivityが全面に出ているが、FragmentをhostするActivityが見えている状態になった時

    • Stopped

HostのActivityがstopしたか、FragmentがActivityからback stackに登録されremoveされた時

また、Activityと同様にFragment#onSavedInstanceState()で状態をBundle objectに保存することが出来る

Coordinating with the activity lifecycle

基本的にはActivityのcallbackが呼ばれた際にはFragmentの同じ様なcallbackが呼ばれる。ただし、Fragmentには追加で下記のcallbackが用意されている

    • onAttach()

FragmentがActivityと結び付けられた時

    • onCreateView()

FragmentのView hierarchyを作る時

    • onActivityCreated()

Activity#onCreate()が終了した時

    • onDestroyView()

FragmentのView hierarchyが取り除かれる時

    • onDetach()

FragmentがActivityとの結び付けを解除された時



Fragmentに関連したcodeはここ

HashTag #Android, #Java, #Fragment, #FragmentManager, #FragmentTransaction

Fragmentを勉強する - part1

今回はAndroid 3.0で追加されたFragmentに関してです。
2回位に分けてここの要点をまとめたいと思います。

Fragment

    • 複数のFragmentを一つのActivity内で表示する事が出来る
    • 複数のActivityでFragmentを共有する事が出来る
    • FragmentのLifecycleはActivityのLifecycleに影響される
    • FragmentのTransactionはStackに保存されBack keyで戻ることが出来る
    • FragmentはActivityで使用されるViewGroupに組み込まれる
    • xmlで定義する際は要素として定義する
    • fragmentをUI上に表示する必要はない(Backgroundで作業をさせる)

Fragment Design Philosophy

複数のScreen sizeでそれぞれ適したUIを
Fragment example

Creating a Fragment

    1. Activityと同じようなLife cycle。少なくとも下記のcallback methodを実装する必要がある
      • onCreate()
      • onCreateView()
        • 初めてUIをdrawする際に呼ばれる。fragmentのrootとなるViewを返す必要がある。UIを持たない場合はViewを返す必要がない
      • onPause
    2. Fragmentのsub class
      • DiaglogFragment
      • ListFragment
      • PreferenceFragment

Life cycle

Adding a user interface

UIにFragmentを追加するにはonCreateView()でActivityのlayout(ViewGroup)に追加されるViewを返す

public static class ExampleFragment extends Fragment {
    //第2引数のViewGroupにreturnするViewが追加される
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 第3引数のbooleanは"container"にreturnするViewを追加するかどうか
    //trueにすると最終的なlayoutに再度、同じView groupが表示されてしまうのでfalseでOKらしい
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}

Adding a fragment to an Activity

ActivityにFragmentを追加する

1. Activityのlayout xmlに定義

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

FragmentにはSystemやProgrammerが識別する為のidもしくはtagが必要である

    • android:idで特定のIDを提供
    • android:tagで特定のstringを提供
    • もし、上記二つがどっちも定義されていなければSystemは親ViewのIDを使用する

2. Source内で追加

FragmentTransaction objectを取得

FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

FragmentTransaction#add()でfragmentをActivityのViewGroupに追加

//Fragmentをinstance化
ExampleFragment fragment = new ExampleFragment();
//FragmentTransaction#add()で第1引数のlayoutにfragmentを追加
fragmentTransaction.add(R.id.fragment_container, fragment);
//変更をcommit
fragmentTransaction.commit();

Adding a Fragment without a UI

    • FragmentTransaction#add(Fragment, String)でFragmentを追加
    • UIを持たないのでonCreateView()を実装する必要がない
    • FragmentManager#findFragmentByTag()でFragmentを取得する(tagを定義しないとUIを持たないFragmentを取得する方法がなくなる)

1回目はまずはここまで。

HashTag #Android, #Fragment, #FragmentManager, #FragmentTransaction, #Activity

MatrixとCanvas

久々のpostです。MatrixとCanvasの動作に関してです。ちょっとチンプンカンプンなところがあったので動作を確認しながらまとめてみました

今回やりたいこと

  1. Matrix(とHandler)を使用してIconを縦方向に落下するAnimationをさせる
  2. Canvasを操作し文字列とIconを縦方向に描画する

Matrixを操作しIconを回転させ、画面に沿って落下させるの図


Canvasを操作し文字列、Iconを縦に回転させるの図

MatrixとCanvasで気付いたこと

1. Matrix

    • Matrixにはpre-concat系、post-concat系、set系のMatrix操作系methodがある
    • 引数に指定するx、yは画面に対してのx、yなのでmatrixを90度回転してもx軸、y軸は変わらない

2. Canvas

    • Canvas経由のmatrix操作はpre-concatなので、codeの並び順とは逆順に実行される
    • Canvasmatrix操作系methodで引数として指定するx、yは画面に対してのx、yなのでmatrixを90度回転してもx軸、y軸は変わらない
    • Canvas描画系methodで引数として指定するx、yはCanvasに対してのx、yなのでmatrixを90度回転するとx軸、y軸も合わせて回転する

その他気付いたこと

    • Viewを入れ替える際はView.INVISIBLEでは駄目でView.GONEを指定する必要がある
    • Matrixを使用する際にはscaleType属性にmatrixを指定する必要あり
    • Canvas#drawText()で指定する座標位置はtextのbaselineの座標位置

それでは実装です

続きを読む

HTMLの基礎覚え書き - form

HTML基礎覚え書き最後にしたいと思います。今回はformに関してです。またまた、ここのサイトを参考にさせて頂いてます

form要素

    1. formはcontrolのまとまり
    2. 「なにを」「どこに」「どうやって」の「どこに」「どうやって」を指定してあげる
      • 「どこに」はaction属性で指定
        • action属性にはprogramの名前を
        • action属性にはURIを指定することも出来る(ex. mailto:)
      • 「どうやって」はmethod属性で指定
        • method属性には"post", "get"のmethodの指定を
      • 「なにを」はcontrolが担当

input要素(controlの一種)

    • name属性を指定することにより、dataを受信したプログラムが入力dataの項目を判別することが出来る
    • readonly属性を使用し、readonly="readonly"と指定することにより、読み取り専用のcontrolとなる
    • type属性を指定することにより、様々な入力形式に変化する

1. textタイプ

    • 文字の入力
    • size属性でtext boxの長さを指定することが出来る
    • value属性でhint textを表示することが出来る
<p>URL: <input type="text" name="url" value="http://" size="60" />

2. submitタイプ

    • submit buttonの表示
    • value属性でbuttonに表示する文字列を指定することが出来る
<input type=”submit" value="送信">

3. radioタイプ

    • radio buttonの表示
    • あらかじめchecked属性、checked="checked"を指定することにより初期選択ができる
    • 選択されたbuttonを判別するためにvalue属性が必要
<li><input type="radio" name="sex" value=”male” checked="checked" /> Male</li>
<li><input type="radio" name="sex" value=”female” /> Female</li>

4. checkboxタイプ

    • checkboxの表示
    • radioタイプと同様checked属性が指定できる
<li><input type="checkbox" name="hobby" value="Running" checked="checked" /> Running</li>
<li><input type="checkbox" name="hobby" value="Swimming" /> Swimming</li>

5. hiddenタイプ

    • HTML文書作成者が設定したdataを送るUserに知られることなく送れる
<!-- infoという名前とsecretというvalueを持ったdataが送られる -->
<input type="hidden" name="info" value="secret" />

6. fileタイプ

    • 選択されたfileがformのdataとして送信することが出来る
    • form要素のenctype属性をmultipart/form-data指定するとMIMEのマルチパートデータとしてファイルやその他の項目の内容を送信する

select要素(controlの一種)

    • option要素入れ子にすることによって、それらをアイテムとしたメニューリストを表示
    • option要素を初期選択状態にするにはselected属性を使用し、selected="selected"を指定する
    • size属性を指定することにより、そのリストアイテムの数を表示したスクロールフィールドを表示する
<select name="favourite_fruit">
    <option selected="selected">りんご</option>
    <option>みかん</option>
</select>

textarea要素

    • input要素textタイプでは一行dataしか入力出来ないので複数行に渡るdataを入力したい時に使用
    • readonly属性を使用し、readonly="readonly"と指定することにより、読み取り専用のcontrolとなる
    • 入力エリアの行数、列数を指定するにはrows属性、cols属性を指定する
    • input要素textタイプと異なり、文字をmarkupするとtext areaにあらかじめtextを表示する(Input要素textタイプではvalue属性に定義していた)
<textarea name="free_ans" rows="2" cols="40">答えを入力</textarea>

URLエンコード

    • method="get”を指定するとformのdataがプログラムのURLの後ろに「?」でつながれ、URLエンコードされて送信される
    • エンコードの仕方
      1. それぞれのデータ(文字列)の中で、スペース文字を"+"に変換
      2. さらに英数字と一部記号以外のものを"%"とその文字を表す2桁の16進数に変換
      3. 変数名(name)と内容(value)を"="で結ぶ
      4. 各項目のデータを "&" で連結する

label要素

    • controlと表示文字列を紐づける
    • ここを参照

XML宣言

    • HTML文書の先頭ではXML宣言を定義すべき
<?xml version="1.0" encoding="Shift_JIS"?>

HashTag #HTML