2010-12-29

mediaplayerを作ってみる(14)

ファイルを忍者に置いておきます。

http://sattva.asasvata.net/Entry/28/

前回の遺産がなくなったので、なかなか進みません。
まあ、それだけでもないんですが。

プリファレンスを追加しました。思ったより簡単でした。
というか、簡単なのにしました。

onStop()で、書き込み。


@Override
public void onStop() {
super.onStop();
musicPlayer.stop();

SharedPreferences pref = getSharedPreferences("SDMP", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();

editor.putString("directory_name", musicDirList.get(musicPlayer.getDirNum()));

editor.putString("file_name",
musicFileList.get(musicPlayer.getMusicNum()));

editor.commit();
}

onStart()で、読み込み。

@Override
public void onStart() {
super.onStart();
SharedPreferences pref = getSharedPreferences("SDMP", MODE_PRIVATE);
String dirName = pref.getString("directory_name", "");
String fileName = pref.getString("file_name", "");
int dirNum = 0;
int fileNum = 0;
if (musicDirList.contains(dirName)) {
mflm.musicFileListMaker(dirName, musicFileList);    
addNumList();
if (musicFileList.contains(fileName)) {
dirNum = musicDirList.indexOf(dirName);
fileNum = musicFileList.indexOf(fileName);
}
}
spinner.setSelection(dirNum);
mflm.musicFileListMaker(musicDirList.get(dirNum), fileListForListView);
mflm.musicFileListMaker(musicDirList.get(dirNum), musicFileList);
addNumList();

musicPlayer.setDirNum(dirNum);
musicPlayer.setCount(fileNum);
//listViewの変更と通知
listView.setAdapter(listAdapter);
musicPlayer.setListView(listView);
listView.clearChoices();
listView.setItemChecked(fileNum, true);
if (fileNum == 0) listView.setSelection(fileNum);
else listView.setSelection(fileNum - 1);
}

流れでonItemSelectedとかも変わってますが、
実行するタイミングが変わっただけで、やってることは同じ。

intではなくStringで書き込んだのは、その方がいいかなーと。
ディレクトリやファイルの場所は、追加、削除で変わるので。

まあ、場所が変わると読み込まないので、無かったことになります。
その辺が、簡単の限界。おまけ程度です。

次は、まあ、そのうち。

2010-12-24

mediaplayerを作ってみる(13)-2

とりあえず置いときます。あまり変わってませんが。

http://sattva.asasvata.net/Entry/25/

本当は、allMusicListに全曲の情報を詰めて
それを使って、randomをしようと思ったんですが、
なんか、色々考えると面倒くさいのでもういいかと。

変更は、menuで演奏履歴をクリアするようにしただけ。


    //オプションメニューの生成
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
     MenuInflater inflater = getMenuInflater();
     inflater.inflate(R.menu.options_menu, menu);
     return true;
    }
  
    //menuが選択されたときの処理
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
     switch (item.getItemId()) {
     case R.id.randomReset:
         allMusicList.clear();//clearしときます
         Toast.makeText(this, "reset", Toast.LENGTH_SHORT).show();
         break;
     }
    
     return super.onOptionsItemSelected(item);
    }


メニューを使いたかっただけです。
本当はvolume調整をメニューでしようと思ったんですが、
本体の横についてるんでいらないかと。

一応前に作ったのを利用して、main.xmlに


<TextView
    android:id="@+id/volText"
    android:layout_width="fill_parent"
    android:layout_height="30dp"
    android:textSize="16sp"
    android:background="@color/violet"
android:textColor="@color/green"
android:gravity="center">
</TextView>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:max="15"
android:progressDrawable="@color/green">
</SeekBar>


を追加して、onCreateの中に、

//seekBarの取得と初期値の設定
SeekBar seekBar = (SeekBar)findViewById(R.id.seekBar);
seekBar.setProgress(5);//とりあえず、5。

//volTextの取得と表示する文字列のセット
final TextView volText = (TextView)findViewById(R.id.volText);
volText.setText("Vol:" + seekBar.getProgress());

//volume調整のための準備
final AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//int maxVolume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC, 5, 0);

//seekBarが動かされたときの処理
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//volumeのセット
am.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
//volTextに文字列をセット
volText.setText("Vol:" + progress);
}
//@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO 自動生成されたメソッド・スタブ
}

//@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO 自動生成されたメソッド・スタブ
}
});


んな感じのを書いとくと、
こんな感じ↓に

















なったりして。

これも置いときます。
忍者に。



2010-12-18

ubuntuとis01とgalaxy

結構簡単につながります。ubuntuには。

参考サイト


Ubuntu 上に IS01 の開発環境構築



そのままです。一個目のを先にやってたので、
そのファイルに追記するだけ。

一個目のは、とりあえずファイルを作ってから
mvで移動させました。

今回は、クリックしたらファイルが開いて
そのまま追記できました。

SUBSYSTEM=="usb", SYSFS{idVendor}=="04dd", MODE="0666"
SUBSYSTEM=="usb", SYSFS{idVendor}=="04e8", MODE="0666"

↑の2行です。
ということは、番号さえ分かればいくらでもいける。かも。
やってないので分かりませんが。

ちなみに、usbマウントをしてsdに書き込もうとすると、
is01の方は、普通に記憶デバイスとして認識されますが、

galaxyは、mediaplayerとして認識されます。
しかも、sdだけじゃなく、本体の方も同じように認識されます。

まあ、それだけで普通に書き込めますが。

2010-12-17

mediaplayerを作ってみる(13)

また忍者ブログに置いときます。

random。ディレクトリを越えて。

SDMP13_1 http://sattva.asasvata.net/Entry/20/

SDMP13_2 http://sattva.asasvata.net/Entry/21/

SDMP13_3 http://sattva.asasvata.net/Entry/22/

12/18追加 SDMP13_4 http://sattva.asasvata.net/Entry/23/

色々さまよった結果、3つ目のに落ち着きました。

12/18 ↑はずでしたが、たぶんもうちょっと変更します。

主な変更点

MusicDirListMakerの引数にArrayListを追加。合計3つ。
で、追加したやつに音楽ファイルをとりあえず詰め込む。
あと、地味にsortもしてます。

ほいで、Activityで、音楽ファイルの総数を確保してから
とりあえず、clear。

で、randomボタンと言うかCheckBox。


public void onClickRandom(View view) {

allMusicList.clear();//clearしときます
addNumList();//sortしときます。

Resources res = getResources();//なんとなく、使ってみる。

if (randomFlag) {

repeatButton.setClickable(true);
shuffleButton.setClickable(true);

     repeatButton.setTextColor(res.getColor(R.color.red));
     shuffleButton.setTextColor(res.getColor(R.color.red));
    
randomFlag = !randomFlag;
} else {

     repeatButton.setChecked(false);
     shuffleButton.setChecked(false);
    
     repeatButton.setClickable(false);
     shuffleButton.setClickable(false);
    
     repeatButton.setTextColor(res.getColor(R.color.dark_red));
     shuffleButton.setTextColor(res.getColor(R.color.dark_red));
    
     randomFlag = !randomFlag;
}
}

repeatButtonとshuffleButtonを、無効にしてテキストの色を暗く。
押す度に、allMusicList.clear();をしてますが、まあ、お好みで。

で、MusicPlayer。

plauMusic内

//Stringに変換
str = "" + dirNum + musicNum;
//全体の80%を越えたらクリアー。なんとなく。
if (allMusicList.size() > (totalMusicCount * 8 / 10)) allMusicList.clear();
//allMusicListに含まれてなければ
if (!allMusicList.contains(str)) allMusicList.add(str);

randomButton.isChecked()が、無いのはなんとなく。
というか、randomButtonを押す度にclearしてなかった時の名残りです。
まあ、いいかと。

で、onCompletion内

while(true) {
//ランダムにディレクトリを変更
dirNum = (int)(Math.random() * dirList.size());
//リストの詰め替え
sdmp.getMflm().musicFileListMaker(dirList.get(dirNum), musicList);
//カウントもランダムに変更
count = (int)(Math.random() * musicList.size());
//Stringに変換
str = "" + dirNum + count;
//allMusicListに含まれていなければ、つまりrandom開始後再生されていなければ
if (!allMusicList.contains(str)) break;
}

一応これで、再生済みの曲をはじけます。
が、なにぶんMath.random()を使っているので
残りが少なくなる(再生済みの曲が増える)と、
当たりを引くまで時間がかかりそう。

なので、playMusicのほうで、80%ぐらいでclearするようにしたんですが、
まあ、お好みで。

あと、読み込むファイルがmp3とwmaに変わってます。

ーーこれ以下、与太話。ーー

なんかねー。基金訓練にいく前に(16時すぎに始まるんですわ)
携帯ショップをのぞいたらgalaxyが在庫有りになってて
思わず機種変更してしまいまして。

で、そこに貼ってあったスペック表に、mp3/wma再生可能
なんてかいてあったんで。まあ、ついでに。

時間が無かったんで登録だけしといて受け取りは、翌日。(つまり今日)
まあ、結局遅刻したんで、遅れついでに受け取っとけば良かったんですが。

結構ちょこちょこ入荷してるらしいです。予約分は、はけたんですかね。
まあ、気にしてもしょうがないですが。

こんなことなら、is01いらなかった。
まあ、(普通の)TVなし生活中なので、is01のワンセグは有難いんですが。

何かここんとこ出費が多い。あぶく銭が入ったんで。
定職についてないんだから、貯金するべきなんだろうけど。

カバンとか、防風ジーンズとか。そんで、galaxy。

防風ジーンズ。ユニクロの。結構いいです。
そんな寒いとこじゃないんですが、バイクを常用しているので。
寒くないとは言わないが、かなりマシ。
普通に歩いてるだけなら、これだけで充分。パッチいらず。
(パッチ・・・股引。ここではヒートテック含む。)

カバンは、撥水の。ポリウレタン?何かそんなやつ。
まあ、バイク用。少々の雨なら大丈夫。カバンは。本人は大丈夫じゃないけど。

で、galaxy。衝動的に。・・・。

まあ、受け取ったらとりあえずこれを入れてみます。
エミュレーターだと2.3でも動いてるけど、2.2の実機でどうなるか。

ちょっと楽しみ。結構不安。まあ、結果はまた。

2010-12-15

StopWatchっぽい物を作ってみた

作ってみました。参考はこちら。というか、まあ、なんというか。

アクティビティ


package net.asasvata.stopwatchex;

import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.Chronometer;

public class StopWatchExActivity extends Activity {
    private Chronometer chronometer;
    private boolean pauseFlag;
    private boolean stopFlag;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
      
      chronometer = (Chronometer)findViewById(R.id.chronometer);
      pauseFlag = false;
      stopFlag = true;
    }
  
    public void onClickStart(View view) {
     if (stopFlag) {
     chronometer.setBase(SystemClock.elapsedRealtime());
     chronometer.start();
     stopFlag = false;
     }
     if (pauseFlag) {
     chronometer.start();
     pauseFlag = false;
     }
 
    }
  
    public void onClickStop(View view) {
     chronometer.stop();
     stopFlag = true;
     pauseFlag = false;
    }
  
    public void onClickPause(View view) {
     chronometer.stop();
     pauseFlag = true;
    }
  
    public void onClickRestart(View view) {
     if (stopFlag || pauseFlag) {
    //一時停止していた時間を取得
int stoppedMilliseconds = 0;
String chronoText = chronometer.getText().toString();
String array[] = chronoText.split(":");
if (array.length == 2) {
stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 1000
+ Integer.parseInt(array[1]) * 1000;
} else if (array.length == 3) {
stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 60 * 1000
+ Integer.parseInt(array[1]) * 60 * 1000
+ Integer.parseInt(array[2]) * 1000;
}

chronometer.setBase(SystemClock.elapsedRealtime() - stoppedMilliseconds);
chronometer.start();
stopFlag = false;
pauseFlag = false;
     }
    }
}

レイアウト


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Chronometer
     android:id="@+id/chronometer"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:textSize="20px">
    </Chronometer>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content">
     <Button
     android:id="@+id/startButton"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:text="@string/start_button"
     android:onClick="onClickStart">
     </Button>
     <Button
     android:id="@+id/stopButton"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:text="@string/stop_button"
     android:onClick="onClickStop">
     </Button>
     <Button
     android:id="@+id/pauseButton"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:text="@string/pause_button"
     android:onClick="onClickPause">
     </Button>
     <Button
     android:id="@+id/restartButton"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:text="@string/restart_button"
     android:onClick="onClickRestart">
     </Button>
    </LinearLayout>
</LinearLayout>

string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, StopWatchExActivity!</string>
    <string name="app_name">StopWatchEx</string>
    <string name="start_button">start</string>
    <string name="stop_button">stop</string>
    <string name="pause_button">pause</string>
    <string name="restart_button">restart</string>
</resources>

Hello World消すのわすれてますが、まあ、まあ。
resetbuttonつけてないのも、まあ、まあ。
大体で。

startとrestart、stopとpauseの違い。

chronometerは、stopしただけだと裏で動きつづけます。
で、
pause→startだと、resetしないで裏で動いてたとこから、続けます。
stop→startだと、resetして0から始めます。
ほいで、
pause or stop→restartで、裏で動いてた時間をひいて、
つまり、表示されてるとこから、続けます。

そんだけ。秒単位の表示が、なんかねー。
handlerとか使うべきかも。
まあ、気が向いたら挑戦します。

mediaplayerを作ってみる(12)

時間表示をつけました。とりあえず。
また置いときます。

http://sattva.asasvata.net/Entry/18/

一応修正版
http://sattva.asasvata.net/Entry/19/

下記の内容は修正前の物です。
修正後は、handlerは、Activityと同じファイルに移動してます。
やってることは同じです。まあ、さまよってるのも何かの参考になれば。


今回の主な追加はhandlerです。


package net.asasvata.sdmediaplayer;

import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class TickHandler extends Handler {
private boolean playFlag;
private MediaPlayer mp;

private TextView textView;

public TickHandler(MediaPlayer mp, TextView textView) {
super();
this.mp = mp;
this.textView = textView;
}

public void setPlayFlag(boolean flag) {
playFlag = flag;
}

@Override
public void handleMessage(Message msg) {
if (playFlag) {
int duration = mp.getDuration();
int currentPosition = mp.getCurrentPosition();

String durationTime = timeText(duration);
String currentTime = timeText(currentPosition);
textView.setText(currentTime + "/" + durationTime);
} else {
textView.setText("00:00/00:00");
}
if (this != null) this.sleep(100);

}

public void sleep(long delayMills) {
removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMills);
}

private String timeText(int time) {
int m = (int)(time / 60000);
     int s = (int)(time % 60000 / 1000);

String str = "00:00";
     if (m > 10 && s > 10) str = "" + m + ":" + s;
     else if (m < 10 && s >= 10) str = "0" + m + ":" + s;
     else if (m >= 10 && s < 10) str = "" + m + ":" + "0" + s;
     else if (m < 10 && s < 10) str = "0" + m + ":" + "0" + s;
    
     return str;
}
}

まあ、本に乗ってたのを少し変えただけですが。
timeTextは、durationとかがミリ秒で、かえされるので
(例 3分なら180000)それを、修正してます。

ただstopしたときに、なんかぴくぴくするので、
ちょっと修正が必要かも。
エミュレーターだと大丈夫なんですが、is01はぴくぴく。
まあ、ぼちぼち。

前のでは、chronometerを使ってごまかしたんですが、
handlerも、使ってみるかと。
どうやってごまかしたかは、書きませんが。

その時のを元にstopwatchっぽいものを、作ったので
次に載せときます。

秒単位でしか表示されない、ぽいだけのですが。


修正後のhandlerを、さらに下記のものに変更すると、
忙しい感じになります。


public class TickHandler extends Handler {

@Override
public void handleMessage(Message msg) {
if (musicPlayer.isPlaying() || pauseFlag) {
int duration = musicPlayer.getDuration();
int currentPosition = musicPlayer.getCurrentPosition();

String durationTime = timeText(duration);
String currentTime = timeCountDown(duration, currentPosition);
timeText.setText(currentTime + "/" + durationTime);
} else {
timeText.setText(timeCountDown(0, 0) + "/" + timeCountDown(0, 0));
}
if (this != null) this.sleep(10);

}

public void sleep(long delayMills) {
removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMills);
}

private String timeText(int time) {
int m = (int)(time / 60000);
     int s = (int)(time % 60000 / 1000);

String str = "";
     if (m > 10 && s > 10) str = "" + m + ":" + s;
     else if (m < 10 && s >= 10) str = "0" + m + ":" + s;
     else if (m >= 10 && s < 10) str = "" + m + ":" + "0" + s;
     else if (m < 10 && s < 10) str = "0" + m + ":" + "0" + s;
    
     return str;
}

private String timeCountDown(int duration, int currentPosition) {
int time = duration - currentPosition;

int m = (int)(time / 60000);
     int s = (int)(time % 60000 / 1000);
     int cs = (int)((time - m*60000 - s*1000) / 10);

String str = "";
     if (m >= 10 && s >= 10 && cs >= 10) str = "" + m + ":" + s + ":" + cs;
     else if (m < 10 && s >= 10 && cs >= 10) str = "0" + m + ":" + s + ":" + cs;
     else if (m >= 10 && s < 10 && cs >= 10) str = "" + m + ":" + "0" + s + ":" + cs;
     else if (m < 10 && s < 10 && cs >= 10) str = "0" + m + ":" + "0" + s + ":" + cs;
     else if (m >= 10 && s >= 10 && cs < 10) str = "" + m + ":" + s + ":" + "0" + cs;
     else if (m < 10 && s >= 10 && cs < 10) str = "0" + m + ":" + s + ":" + "0" + cs;
     else if (m >= 10 && s < 10 && cs < 10) str = "" + m + ":" + "0" + s + ":" + "0" + cs;
     else if (m < 10 && s < 10 && cs < 10) str = "0" + m + ":" + "0" + s + ":" + "0" + cs;
     return str;
}
}

stopwatchに使えそう。普通に表示させたら。

2010-12-13

mediaplayerを作ってみる(11)-2

shuffleつけました。変更は・・・。
多すぎるので、また忍者ブログに置いときます。
http://sattva.asasvata.net/Entry/17/

12/14↑ちょっと修正しました。まあ、ね。

まあ、要点だけ。


//シャッフル。特定の番号をlistの先頭にする
private void shuffleMusicNumList(int num) {

//一番後ろに追加
musicNumList.add(musicNumList.get(num));

//元からあるのを削除
musicNumList.remove(num);

//1回は済んでるので、size()-2から始める。
for (int i = musicNumList.size()-2; i >= 0; i--) {

//詰め替えてないのからランダムに選択
int n = (int)(Math.random()*(i+1));

//追加と削除
musicNumList.add(musicNumList.get(n));
musicNumList.remove(n);
}
}

なんか、すごく見にくい。まあ、それはそれとして。

普通にCollections.shuffleを使わなかったのは、
shuffleButtonにonClickをつけたので、
shuffleButtonを押したときにかかってる曲をlistの先頭に
持っていっとこうかと。

そうでもしないと、同じ曲がすぐにかかったすることがあるので。
まあ、listViewで選択した時もshuffleしなおすので、
直前の曲がすぐにかかることは、避けられてないですが。

あと、Collections.sortを使ってないのは、まあ、なんとなく。
addNumListで、いけるので。せっかく作ったし。

あと、参考までにjavaのソースを。
0から9の入ったArrayListの5番目の要素(indexは4)を
先頭に持っていきます。その他はまあ、適当に。

import java.util.*;

public class RandomTest2 {
public static void main(String[] args) {
ArrayList<Integer> array1 = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
array1.add(i);
}
array1.add(array1.get(4));
array1.remove(4);
for (int i = array1.size()-2; i >= 0; i--) {
int n = (int)(Math.random()*(i+1));
array1.add(array1.get(n));
array1.remove(n);
}
System.out.println(array1);
}
}

まあ、一緒です。これを元にしたんで。

あと、↑にもありましたが、ArrayListをもう一本使うのも。
なんかおかしいですが、まあ、適当に作ったんで。

import java.util.*;

public class RandomTest {
public static void main(String[] args) {
ArrayList<Integer> array1 = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
array1.add(i);
for (int j = 0; j < array1.size(); j++) {
ArrayList<Integer> array2 = new ArrayList<Integer>();
array2.add(array1.size()-1);
//array1.remove(array1.size()-1);
Collections.shuffle(array1);
for (Integer n : array1) {
array2.add(n);
}
//array1.clear();
System.out.println(array2);
}
}
}
}

意図したのとは違う動きをするのが、残念な感じ。
Collections.shuffleしたのを、新しいlistに追加。
無駄が多い。様な気がするので、不採用。

それと、onClickBackとonClickNextのとこは、
(1)なら、(1)だけコメントアウトを解除して
(2),(3)は、コメントアウトにしておくと、処理が変わります。
たぶん。まあ、あまり確認してませんが。3つとも。

後、なんとなくでもなく見た目の変更。
隙間を開けとかないとボタンが押しにくいので。
こんな↓感じ。

















checkboxは、前に作ったのに変更。
せっかく作ったし。

次は、まあ、いろいろと。適当に。

2010-12-10

mediaplayerを作ってみる(11)-1

ファイルを、忍者ブログに置いときました。

http://sattva.asasvata.net/Entry/15/

書かなくてもいいような気もしますが一応。
shuffleへの下準備を。MusicPlayerから。
フィールドに

private ArrayList<Integer> numList; 追加。
private int count; 追加。

コンストラクタに

count = 0; 追加。

public ArrayList<Integer> getNumList() {
return numList;
}

public void setNumList(ArrayList<Integer> array) {
numList = array;
}

public int getCount() {
return count;
}

public void setCount(int n) {
count = n;
musicNum = numList.get(count);//これは、いらないかも
}

追加。要らないのもあるかも。
ほいで、playMusic

musicNum = numList.get(count); 追加。

setTitle()の上に。
次は、onCompletion

++musicNum を ++count に変更。
musicNum = 0 を count = 0 に変更。

sdmp.getMflm().musicFileListMaker(dirList.get(dirNum), musicList);
の下に、

addNum(); 追加。2ヶ所とも。それから、

public void addNum() {
numList.clear();
for (int i = 0; i < musicList.size(); i++) {
numList.add(i);
}
}

追加。Activityは、フィールドに

private ArrayList<Integer> musicNumList; 追加。

onCreate内

musicFileList = new ArrayList<String>(); 追加。
musicNumList = new ArrayList<Integer>(); 追加。

onItemSelected内

if (musicFileList == null) {
musicFileList = new ArrayList<String>();
     mflm.musicFileListMaker(musicDirList.get(position), musicFileList);
}
を、

if (!startFlag) {
     mflm.musicFileListMaker(musicDirList.get(position), musicFileList);    
     addNumList();
}

に変更。それと、

musicPlayer.setNumList(musicNumList); 追加。

で、onClickBack内

int n = musicPlayer.getCount() - 1; に変更。

if (repeatButton.isChecked())のとこ

n = musicPlayer.getNumList().size() - 1;
musicPlayer.setCount(n);

に変更。それから、

musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);

を、

changeMusicList(num); に変更。


その下を

n = musicPlayer.getNumList().size() - 1;
musicPlayer.setCount(n);

に変更。2ヶ所とも。あと、一番下の} else {のとこ

musicPlayer.setCount(n); に変更。

そいで、onClickNext

int n = musicPlayer.getCount() + 1; 変更。

if (n < musicPlayer.getNumList().size()) {
musicPlayer.setCount(n); 

に変更。ほいで、n = 0;の下

musicPlayer.setCount(n); 変更。

そいから、

musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
を、

changeMusicList(num);

に変更。2ヶ所とも。それと、setAndPlayMusicを、

private void setAndPlayMusic() {

if (spinnerPosition != musicPlayer.getDirNum()) {
changeMusicList(spinnerPosition);
}

     musicPlayer.setCount(listPosition);
musicPlayer.playMusic();
changeMusicFlag = false;    
}

に変更。あとは、

private void addNumList() {
musicNumList.clear();
for (int i = 0; i < musicFileList.size(); i++) {
musicNumList.add(i);
}
}

private void changeMusicList(int num) {
musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
addNumList();
}

を追加。たぶんこんだけ。

ちょっとした思いつきなんですが、うまくいくか・・・。
まあ、大体で。

ファイルは、一応ダウロードできることを確認。
が、自分だからかも。まあ、大体で。

2010-12-08

sdk新しいのを入れてみた。

12/10タイトル変更
なんか、前のタイトルが検索で引っかかって見にくる方が多いようで。
たぶん、期待に答えてないと思うので。
手遅れかもしれませんが。変更しときます。

SDK2.3がリリースされたので入れてみました。
おかしなことになりました。

Ubuntuの方は、eclipseのヘルプ→更新の確認で
ADT8.0.0にアップデートできまして、SDKのインストールも
できましたが、adbの場所が変わってるのに気づかず
えらいさまよいました。

platfrom-tools。こんなとこにあるとは。
で、何とかなったと思ったんですが・・・。

DDMSは、右クリック→リセットで元通り。
が、AVDマネージャーが立ち上がらない。

結局、eclipseを入れ替えました。なんとなく、heliosに。
何とか元通り。と思います。思いたいです。

何が悪かったのか。まあ、そんだけです。

ちなみに、eclipseで更新できないときは、
android-sdk→tools→androidで、sdkをインストール。
(winはsdkmanager.exe?なんかそんなの)
eclipseは、androidのプラグインをアンインストールして
入れ直すのがよろしいかと。
まあ、これもダメだったんですが。一応。

12/9追記

端末使って、

eclipseのフォルダにあるeclipse(起動する奴)のpath -clean

で、どうやら問題解消のようです。AVDマネジャーが動きました。

http://d.hatena.ne.jp/kristallna/20101207/1291697229

こちらから辿りました。

後、一つ小ネタを。ubuntuで、eclipse.iniの-vmargsの上辺りに

-vm
/usr/lib/jvm/java-6-sun-1.6.0.22/jre/bin/java

なんてのを追加すると、eclipseの起動画面が変わります。
そんだけ。pathは、まあ、状況で変えてください。



12/13 追記 

ADTが、8.0.1になってる。
入れ替えてみたけど、win7のほうの元からあるeclipseは、
AVDマネージャー起動せず。なぜ?ubuntuはいけたのに。

2010-12-07

mediaplayerを作ってみる(10)-2

結構変更。いろんなとこを。まずは、selector。checkboxの。
この間、色々拾ってきたんで。元のcheckboxがいやだったし。
参考サイト Android Wiki* の

ボタンの画像変更(CheckBox,RadioButton)

checkbox_selector.xml


<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:state_pressed="true"
android:drawable="@drawable/free2you5" />
<item
android:state_checked="true"
android:drawable="@drawable/free2you1" />
<item
android:state_checked="false"
android:state_pressed="true"
android:drawable="@drawable/free2you5" />
<item
android:state_checked="false"
android:drawable="@drawable/free2you6" />
</selector>

上から

チェックされてて、押された状態
チェックされてる状態
チェックされてなくて、押された状態
チェックされていない状態

それぞれの状態のbutton(icon)を設定。
色々試した結果、32x32とxmlをdrawable-mdpiに。まあ、お好みで。
上から1番目と3番目(押された状態)は、同じ画像を使ってます。まあ、お好みで。
ほいで、style。res/valuesに。

checkbox_style.xml


<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="custom_checkbox" parent="android:Widget.CompoundButton.CheckBox">
<item name="android:button">@drawable/checkbox_selector</item>
</style>
</resources>

で、main.xml。skipボタンの列に。skipボタンもまとめて。


<LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:gravity="center_horizontal">
     <CheckBox
     android:id="@+id/repeatButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textSize="16sp"
     android:text="@string/repeat_button"
     android:textColor="@color/green"
     android:layout_marginLeft="10dp"
     style="@style/custom_checkbox">
     </CheckBox>
     <CheckBox
     android:id="@+id/shuffleButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textSize="16sp"
     android:text="@string/shuffle_button"
     android:textColor="@color/green"
     android:layout_marginLeft="10dp"
     style="@style/custom_checkbox">
     </CheckBox>
<Button
android:id="@+id/skipButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/skip_button"
android:onClick="onClickSkip"
android:layout_marginLeft="10dp">
</Button>
</LinearLayout>

shuffle用もまとめて追加。どうせつけるんで。
表示する文字は、まあ、お好みで。
で、こんな↓感じ。

















eclipseで、画面キャプチャ出来るとは。知りませんでした。
一応メモ。DDMS→Devices→スクリーンのキャプチャー
便利だ。それはそれとして、次はMusicDirListMaker。作り変えました。

package net.asasvata.listmaker;

import java.io.File;
import java.util.ArrayList;

public class MusicDirListMaker {
private final String FILE_SEP = File.separator;

public void musicDirListMaker(ArrayList<String> list1, ArrayList<String> list2) {

int m = 0; int n = 0;
        while (list1.size() > m) {
         File subDir = new File(list1.get(m));
         try {
        String[] subFileName = subDir.list();
        n = 0;
        while (subFileName.length > n) {
        File subFile = new File(subDir.getPath() +
FILE_SEP + subFileName[n]);
        if (subFile.isDirectory()) {
        list1.add(subDir.getPath() + FILE_SEP + subFileName[n]);
        } else if (subFile.isFile() &&
        (subFile.getName().endsWith("mp3") ||
        subFile.getName().endsWith("wav"))) {
       
        if (!list2.contains(list1.get(m))) {
        list2.add(list1.get(m));
        }
        }
        n++;
        }
         } catch (NullPointerException e) {
         }
         m++;
        }
    }
}

Exceptionは、dirListMakerと同じ理由でほったらかし。いいのだろうか。
endWith()で拡張子をみてるので、追加、削除はまあ、お好みで。
あと、voidになってます。なんとなく。MusicFileListMakerもつくりました。

package net.asasvata.listmaker;

import java.io.File;
import java.util.ArrayList;

public class MusicFileListMaker {
private final String FILE_SEP = File.separator;
public void musicFileListMaker(String name, ArrayList<String> list) {
list.clear();
     File musicFile = new File(name);
     String[] musicFileList = musicFile.list();
     for (String fileName : musicFileList) {
     File file = new File(name + FILE_SEP + fileName);
     if (file.isFile() && (fileName.endsWith("mp3") || 
            fileName.endsWith("wav"))) {
     list.add(fileName);
     }
     }
}
}

"mp3"って書くのが、面倒なんで。wavはなんとなく。要らないような気も。
あと、何気なく list.clear()。 そのうちまた変わるかも。まあ、適当に。
次は、MusicPlayer。フィールドに

private SDMediaPlayerActivity sdmp; 
private CheckBox repeatButton;

2個追加。で、コンストラクタの引数に

SDMediaPlayerActivity sdmp 追加。1つ目に。

コンストラクタの中に、

this.sdmp = sdmp; 追加。

そいで、

public void setRepeatButton(CheckBox cb) {
repeatButton = cb;
}

public void onCompletion(MediaPlayer mp) {
if (++musicNum < musicList.size()) {
playMusic();
} else {
musicNum = 0;
if (repeatButton.isChecked()) {
playMusic();
} else {
if (++dirNum < dirList.size()) {
if (dirNum - 1 == sdmp.getSpinnerPosition()) {
setSpinnerAndListView();
}
sdmp.getMflm().musicFileListMaker(dirList.get(dirNum), musicList);
playMusic();
} else {
if (dirNum - 1 == sdmp.getSpinnerPosition()) {
dirNum = 0;
setSpinnerAndListView();
}
dirNum = 0;
sdmp.getMflm().musicFileListMaker(dirList.get(dirNum), musicList);
playMusic();
}
}
}
}

//spinner表示変更
public void setSpinnerAndListView() {
sdmp.getSpinner().setSelection(dirNum);
sdmp.getMflm().musicFileListMaker(dirList.get(dirNum), sdmp.getFlfv());
listView.setAdapter(sdmp.getAdapter());
}

こんだけ追加と、変更。ほいから、Activity。
フィールド

private FileListMaker flm; 削除。
private MusicFileListMaker mflm; 追加。
private int spinnerPosition; 変更。(static削除)
private String musicDirName; 削除。
private CheckBox repeatButton; 追加。

onCreate内、

musicDirList = new ArrayList<String>(); ↓の上に追加。
mdlm.musicDirListMaker(dirList, musicDirList); 変更。(引数追加)

↓は、この位置関係で。ちょっとおかしいかもしれませんが。

//CheckBoxの取得
repeatButton = (CheckBox)findViewById(R.id.repeatButton); 追加。

//musicPlayerの生成とmusicNumの取得
musicPlayer = new MusicPlayer(this,titleView); 引数変更。
musicPlayer.setRepeatButton(repeatButton); 追加。

これも忘れず。

flm = new FileListMaker(); 削除。
mflm = new MusicFileListMaker(); 追加。

次、onItemSelected内、

musicDirName = musicDirList.get(position); 削除。

fileListForListView.clear(); 削除。

flm.fileListMaker(musicDirName, "mp3", fileListForListView); 削除。

mflm.musicFileListMaker(musicDirList.get(position), 
    fileListForListView); 追加。


if (musicFileList == null) {
     musicFileList = new ArrayList<String>();
     mflm.musicFileListMaker(musicDirList.get(position), musicFileList);
}

↑変更。そいで、結構な変更。

//戻る
public void onClickBack(View view) {
int n = musicPlayer.getMusicNum() - 1;//とりあえず減らす
if (n < 0) {
if (repeatButton.isChecked()) {
     n = musicPlayer.getMusicList().size() - 1;//最後の曲を指定
     musicPlayer.setMusicNum(n);
     if (musicPlayer.isPlaying()) musicPlayer.playMusic();
        else setTitle();
} else {
int num = musicPlayer.getDirNum() - 1;
if (num < 0) {
if (num + 1 == spinnerPosition) {
num = musicDirList.size() - 1;
setSpinnerAndListView(num);
}
num = musicDirList.size() - 1;
musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
    n = musicPlayer.getMusicList().size() - 1;//最後の曲を指定
    musicPlayer.setMusicNum(n);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
    else setTitle();
} else {
if (num + 1 == spinnerPosition) {
setSpinnerAndListView(num);
}
musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
    n = musicPlayer.getMusicList().size() - 1;//最後の曲を指定
    musicPlayer.setMusicNum(n);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
    else setTitle();
}
}
} else {
musicPlayer.setMusicNum(n);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
else setTitle();
}
}
//進む
public void onClickNext(View view) {
int n = musicPlayer.getMusicNum() + 1;//とりあえず増やす。
if (n < musicPlayer.getMusicList().size()) {
musicPlayer.setMusicNum(n);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
   else setTitle();
} else {
n = 0;//1曲目を指定
musicPlayer.setMusicNum(n);
if (repeatButton.isChecked()){
     if (musicPlayer.isPlaying()) musicPlayer.playMusic();
     else setTitle();
} else {
int num = musicPlayer.getDirNum() + 1;
if (num < musicDirList.size()) {
if (num - 1 == spinnerPosition) {
setSpinnerAndListView(num);
}
musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
    else setTitle();
} else {
if (num - 1 == spinnerPosition) {
num = 0;
setSpinnerAndListView(num);
}
num = 0;
musicPlayer.setDirNum(num);
mflm.musicFileListMaker(musicDirList.get(num), musicFileList);
if (musicPlayer.isPlaying()) musicPlayer.playMusic();
    else setTitle();
}
}
}
}

次は、地味に変更。

public int getSpinnerPosition() {
    return spinnerPosition;
}

staticを外しただけ。も一つ地味に。setAndPlayMusic内、

if (spinnerPosition != musicPlayer.getDirNum()) {
mflm.musicFileListMaker(musicDirList.get(spinnerPosition), musicFileList);
musicPlayer.setDirNum(spinnerPosition);
}

最後に、

private void setSpinnerAndListView(int num) {
spinner.setSelection(num);
mflm.musicFileListMaker(musicDirList.get(num), fileListForListView);
listView.setAdapter(listAdapter);
}

追加。たぶん、これだけ。
次は、shuffle。ボタンもつけたし。

2010-12-05

mediaplayerを作ってみる(10)-1

今回は、見た目の変更と前から気になってたのを追加。
参考は、
rTAKI's android ブログ

SDカードの中身を ListView を使って表示&選択 (拡張子フィルター付)


Tech Booster

Android Wiki*

後は、free icon。参考まで。


とりあえず気になっていた分から。
ActivityのonCreate内、setContentViewの次に

  String SDstatus = Environment.getExternalStorageState();

        // SDカードがセットされているか確認
        if (SDstatus.equals(Environment.MEDIA_MOUNTED) == false) {

          AlertDialog.Builder builder = 
      new AlertDialog.Builder(SDMediaPlayerActivity.this);

          builder.setTitle("警告");
          builder.setMessage("SDカードがセットされていません。");
          builder.setPositiveButton("OK", new DialogInterface.OnClickListener () {

            //@Override
            public void onClick(DialogInterface dialog, int which) {
             SDMediaPlayerActivity.this.finish();
            }
          });
          builder.show();
        }

まんまです。相変わらず。一応あった方がいいかなーと。

で、見た目はspinnerのdropdownlist。radiobuttonを変えるだけ。
まずは、button(icon)の用意。さっきのサイトでもいいですし、作るのもあり。
僕は、残念な感じのしか作れなかったので・・・。

で、用意したbuttonをres/drawableに。3つある理由はここを参考に。
ちょっと試した結果、is01だと、32x32をdrawable-hdpiに置いとくと
なんかいい感じなので、そのように致しました。まあ、お好みで。

で、まずはselector。res/drawableに配置。とりあえず同じとこに。

radiobutton_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item
  android:state_checked="true"
  android:drawable="@drawable/button_purple" />
</selector>


checkされてるとこしかbuttonを表示しない。まあ、お好みで。
button_purple は、用意したbuttonの名前に変えてください。
次は、style。res/valuesに配置。

radiobutton_style.xml

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <style name="custom_radiobutton" parent="android:Widget.DropDownItem">
        <item name="android:checkMark">@drawable/radiobutton_selector</item>
    </style>
</resources>

ほいから、layout。res/layoutに配置。

dropdownlist.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@android:id/text1"
  style="@style/custom_radiobutton"
  android:layout_height="?android:attr/listPreferredItemHeight"
  android:layout_width="fill_parent"
  android:singleLine="true"
  android:textSize="16sp"
  android:ellipsize="marquee">
</CheckedTextView>

最後に、ActivityのonCreate内の

spinnerAdapter.setDropDownViewResource(
    android.R.layout.simple_spinner_dropdown_item); を、

spinnerAdapter.setDropDownViewResource(R.layout.dropdownlist);

に変更。こんな↓感じ。










Tech Boosterさんのボタンいいなー、何て思ってたら見つけちゃったので。
ほんとは、色も変えたかったんですが枠の色の変え方がわからないので。保留。

次は、やっとフォルダをまたいでの連続再生。今度はほんと。現在進行中。
まあ、ぼちぼち。

2010-12-04

mediaplayerを作ってみる(9)-2

また、地味に変更。思いつきでAndroid2.2のエミュレーターで動かしたら
強制終了。ほっといても良かったんですが。is01は1.6なので。
なんか引っかかって。こちら↓を参考に

Android 1.xと2.2の互換性について



dirListMakerを


public ArrayList<String> dirListMaker(ArrayList<String> list, String ext) {
//ArrayListの生成
ArrayList<String> array = new ArrayList<String>();

int m = 0; int n = 0;
        while (list.size() > m) {
        
         File subDir = new File(list.get(m));
         try {
         String[] subFileName = subDir.list();
        n = 0;
        while (subFileName.length > n) {
        File subFile = new File(subDir.getPath() + FILE_SEP + subFileName[n]);
       
        if (subFile.isDirectory()) {
        list.add(subDir.getPath() + FILE_SEP + subFileName[n]);
       
        } else if (subFile.isFile() && subFile.getName().endsWith(ext)) {
       
        if (!array.contains(list.get(m))) {
        array.add(list.get(m));
        }
        }
        n++;
        }
         } catch (NullPointerException e) {
         /*Android2.2ではString[] subFileName = subDir.list();において
         * ディレクトリが空の場合nullを返します。
         * そのExceptionを回避するためのtry-catchなので
         処理をしません。*/
         }
         m++;
        }
        return array;
}

try-catchで括っただけ。これで、いけました。エミュレーターでは。
もう一つの方も変更しときました。使ってませんが。
後もう一ヶ所変更。特につながりはありませんが。
javaの道の文字列-6.文字列の分割を参考に。

ActivityのonCreate内でspinnerAdaperにaddしてるとこ↓を


        int n = 0;
        for(String name : musicDirList) {
         ++n;
         spinnerAdapter.add(n + ":" + name);
        }

この様に↓

        //ちょっとした準備
        ArrayList<String[]> dirNameList = new ArrayList<String[]>();
        for (String fileName : musicDirList) {
         String[] strArray = fileName.split(File.separator);
         dirNameList.add(strArray);
        }
        
        //ディレクトリ2階層分だけ表示。SD直下にある時は1階層だけ。
        int n = 0;
        for(String[] nameList : dirNameList) {
         int size = nameList.length;
         if (size < 3) {
         spinnerAdapter.add((n + 1) + ":" + "/" + nameList[size - 1]);
         } else {
         spinnerAdapter.add((n + 1) + ":" + "/" + nameList[size - 2] + "/" + nameList[size - 1]);
         }
         n++;
        }

階層が深くなったときに表示しきれなくなってたので。
もっと他にやりようがあるような気もしますが。
layoutを作るとか、adapterを作るとか。

次は、いや次も、なんか適当に。たぶん。