2014/07/14

Android携帯の着信音とアラーム音楽を変えよう

もはや、Androidの携帯で音楽を聞くときは、GooglePlayMusicを使うので
携帯に音楽をコピーしなくてもよくなったけど。
着信音とかめざましのアラーム音楽とかを変えたい!という方のために
簡単に説明しようと思います。

MP3を編集する?

まず、音楽をイケてる出だしにしたいよね。
mp3cutというサイトで、とても直感的に、編集できます。
http://mp3cut.net/
どうぞ。

パソコンの音楽を携帯に入れるというところからです。

まずパソコンと携帯をUSBでつなぎます

USB(´・ω・`)?
こんなやつです。


繋ぐと、ピコ!と音がする(かバイブかなにか)ので、
携帯を見ると、「メディアデバイスで接続」か何かのお知らせが出ています。


携帯側で接続を許可すると、パソコンは、携帯を認識します。
[フォルダを開いてファイルを表示]を選択します。
この画面が出てこない場合は、[マイコンピュータ]から携帯が接続されている
ドライブ(ディスク)を選択して表示します。

Android側にフォルダを作る

続いて、フォルダーを開いて音楽を入れる場所をつくります。
私は、『コンピューター\Nexus 5\内部ストレージ\media\audio\ringtones』に入れてます。


ここで、
着信音が『ringtones』で、
めざましが『alarms』です。

べつに、場所(階層)はどこでもいいのですが、フォルダ名が重要です。
フォルダは、右クリックメニュー『新規フォルダー』で作って名前をとにかくRingtonesとAlarms

PCからAndroidにコピペ

続いて、パソコンの音楽が入っている場所を開きます。
左がAndroidに作ったRingtonesフォルダで、右がパソコンの音楽が入っているフォルダです。
















携帯で着信音・めざましアラームを今コピーした音楽に変えよう

携帯を見ます。
まず、着信音から
[設定]>[音]>[着信音]ですかね?機種によって違うんですよね。



次にアラーム


ワーイできた!

ちなみに、携帯にすでに音楽いっぱい入ってるし(´・ω・`)っていうひとは、
いけてるファイルエクスプローラ(ESファイルエクスプローラとか?)あれば、
音を設定するときに、起動してくれるから、直接指定できるね(´・ω・`)




JavaFXでグラフ描くよ

CSSでグラフの色が設定できるのはいいですね。
あとから、簡単に変えれる!
StackedChartをやるつもりでしたがひとまず、1系列で。
#追記:ソースがうまく貼れないので、githubにあげてみた

まず、画面が

<BorderPane id="_root" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxsample2.ChartController">
    <stylesheets>   
        <URL value="@chart.css" />
    </stylesheets>
    <top>
            <MenuBar id="menuBer" layoutY="2.0">
                    <menus>
                            <Menu mnemonicParsing="false" text="メニュー" />
                    </menus>
            </MenuBar>
    </top>
    <center>
        <VBox>
        <StackedBarChart fx:id="chartApp" BorderPane.alignment="CENTER">
            <xAxis>
                    <CategoryAxis fx:id="xAxis1" side="BOTTOM" />
            </xAxis>
            <yAxis>
                    <NumberAxis fx:id="yAxis1" side="LEFT" />
            </yAxis>
    </StackedBarChart>
        <StackedBarChart fx:id="chartApp2" BorderPane.alignment="CENTER">
            <xAxis>
                    <CategoryAxis fx:id="xAxis2" side="BOTTOM" />
            </xAxis>
            <yAxis>
                    <NumberAxis fx:id="yAxis2" side="LEFT" />
            </yAxis>
    </StackedBarChart>
        </VBox>
    </center>
</BorderPane>

コントローラが
public class ChartController extends BaseController  implements Initializable{
    @FXML private NumberAxis yAxis1;
    @FXML private NumberAxis yAxis2;
    @FXML private CategoryAxis xAxis1;
    @FXML private CategoryAxis xAxis2;
    @FXML private StackedBarChart chartApp;
    @FXML private StackedBarChart chartApp2;
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        
        XYChart.Series series1 = new XYChart.Series();
        XYChart.Series series2 = new XYChart.Series();

        xAxis1.setLabel("Time");
        xAxis2.setLabel("Time");
        Calendar cal1 = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");//"hh:mm:ss SSS"
        cal1.set(2016, 6, 30);
        Random rnd = new Random();
        ArrayList datelist = new ArrayList();
        for(int i=0; i< 20; i++){
         cal1.add(Calendar.SECOND, 1);
         String label = sdf.format(cal1.getTime());
         datelist.add(label);
        }
        xAxis1.setCategories(FXCollections.observableArrayList(datelist));
        xAxis2.setCategories(FXCollections.observableArrayList(datelist));
        
        yAxis1.setLabel("M bps");
        yAxis2.setLabel("なんか単位");
        series1.setName("なんとかチャート");
        series2.setName("なんかのグラフ");
        for(int i=0; i< 20; i++){
            float val = rnd.nextInt(100); 
            series1.getData().add(new XYChart.Data(datelist.get(i), val));
            series2.getData().add(new XYChart.Data(datelist.get(i), val%20));
        }
        chartApp.getData().addAll(series1);
        chartApp2.getData().addAll(series2);
    }
}



でCSSがこんな感じ
.chart {
    -fx-category-gap:0.0px;
    -fx-background-color: -fx-box-border, #f5f5f5;
    -fx-background-insets: 0, 1;
}
#chartApp .default-color0.chart-bar{
    -fx-stroke-width: 0;
    -fx-background-radius: 0;
    -fx-background-color: rgba(50,180,230,0.6);
    -fx-background-position: left center;
}
#chartApp2 .default-color0.chart-bar{
    -fx-stroke-width: 0;
    -fx-background-radius: 0;
    -fx-background-color: rgba(180,230,50,0.6);
    -fx-background-position: left center;
}



JavaFXやってみた

JavaFXやってみるよ。

環境は、CentOS6.5です。

JavaFXとは
Java Platform Standard Edition 7 Documentation
http://docs.oracle.com/javase/7/docs/

JDKに内包されているからそのまま使えるのだ。
swingの上にかぶさっている感じで、swingはコンポーネントとして利用できるのだ。
その他さまざまなコンポーネントがあって便利。
CSSでスキンを設定できるし。

JavaFXのリファレンス

JDKをインストール後、バージョンを確認しよう

/usr/java/jdk1.7.0_60/jre/lib/javafx.properties
↑これにjavaFXのバージョンが書いてあるよ

$ java -version
java version "1.7.0_60"
$ cat $JAVA_HOME/jre/lib/javafx.properties
javafx.runtime.version=2.2.60

ちなみにこの記事によると、「The JavaFX 2.2 SDK for Linux is installed as part of JDK 7 update 6 for Linux.」らしいので、yumで入れれるJDKには入ってなかった。
なので update 6を

$ sudo rpm -ihv jdk-7u60-linux-i586.rpm

とかで入れたよ。

JavaFX Scene Builder

JavaFXでMVC的にViewにあたる.fxml形式の画面を作成するためのツールです。
ポチポチ、コンポーネントを配置して画面を作りたい場合は、使います。
全部javaで描きますっていう場合は、要らないかも。
紹介してもらった@skrbさんのサイトに詳しく書いてあるから参考に↓

開発環境(eclipse編)

java系では、IDEはNetBeansとやらが主流なのかもしれないけども。
eclipseでやってみよう(と最初は思った)。

eclipseのアドイン e(fx)clipse

eclipseでjavaFXのプロジェクトを作成する為に「e(fx)clipse」アドインを入れる
http://www.efxclipse.org/p2-repos/releases/latest/
e(fx)clipse - install
e(fx)clipse - tooling
この2つをいれるよ

開発環境(NetBeansIDE編)

はじめ、eclipseでやっていたのですが、圧倒的にNetBeansが使いやすいので切り替えました。
つまり、さまざまのウィザードが充実しているし、ファイル新規作成時にある程度、道筋があるので、FlashBuilderのように使える。
eclipseに慣れていない場合は、NetBeansでいいのでは?と思いました。
https://netbeans.org/index_ja.html

JavaFX Scene Builderのパス設定

[ツール]>[オプション]>[Java]>[JavaFX]でパスを設定します(NetBeans再起動)。
設定すると、.fxmlを編集するときScene Builderが起動するようになります。

導入用サンプル

http://docs.oracle.com/javafx/2/get_started/jfxpub-get_started.htm


いちおうどちらでも開発できるようになってよかった

2014/05/06

UNIX時刻⇔DateTime文字列 変換

UNIX時刻⇔DateTime文字列の変換をガジェットっぽくしてみた。
ついでにGPSの閏秒計算するようにしてみた。
なんというか、検算用にツールにしとこうかなと思いまして。

GPS時刻は、GPS衛星の時計が打ち上がったとき(1980-01-06)の時計らしく
閏秒の補正が途中からされてない状態らしい。
# 閏秒についてちょっと難しくて実はよくわかってないのですけど。
# なんしか、原子時計とUTCはずれてくるから
# いままで合計25回(2015/06/30入れて26回)、6月末か12月末に23:59:60という時間を挿入して調整しているらしい。

挿入した閏秒
1972 0630235960
1972 1231235960
1973 1231235960
1974 1231235960
1975 1231235960
1976 1231235960
1977 1231235960
1978 1231235960
1979 1231235960
----ここからGPS時計スタート----
1981 0630235960
1982 0630235960
1983 0630235960
1985 0630235960
1987 1231235960
1989 1231235960
1990 1231235960
1992 0630235960
1993 0630235960
1994 0630235960
1995 1231235960
1997 0630235960
1998 1231235960
2005 1231235960
2008 1231235960
2012 0630235960
2015 0630235960 add

GPSの時計は、1980-01-06から始まっているから、
今(2014-05)まで打ち上がってから16回調整してない状態になっているんだね。
今は、UTC時刻+16秒=GPS時刻ということ。16秒進んでる。
いちおう過去の時刻も大丈夫、例えば1990-01-01なら6秒とか。

ソースはここにあります。

<できること>

  • 入力したUNIXEpoch[s]をDateTime文字列に変換します
  • 入力したDateTime文字列をUNIXEpoch[s]に変換します(format固定で(^^;))
  • 入力した時間についてGPS時刻で表示します

それでガジェットっぽく貼ってみた。右サイド→
[レイアウト]>[ガジェットを追加]>[HTML/JavaScript]に埋め込んでるだけ。


  • Leap seconds:
    • 入力した時刻のGPS閏秒つまり1980-01-06から調整した閏秒の総和
  • GPS Time:
    • DateTime+Leap seconds
  • Week Number(1980/1/6からの何番目の週か)
    • wn=Math.floor((epogps - 315964800) / 86400 / 7)
  • Time of week(日曜日の0時からの秒)
    • tow=(epogps - 315964800) - (wn * 7 * 86400)
epogpsは入力した時刻+Leap secondsです。
ちなみに、Week Numberは、1024までで表すから、カッコ内は、mod 1024です。

こんなイメージなのですが。
あと、いまから未来に閏秒調整があったら、リスト修正しないとダメですm(_ _)m。

参考したサイト
http://www.enri.go.jp/~sakai/pro.htm

2014/05/05

mongodbで新しいドキュメント取得

やりたいこと
あるコレクションから、
まだ取得していなくて、
新しく追加されたドキュメントを取得したい


例えば、oidが、あるOIDまで取得している状態で、
db.test.find({_id:{$gt:ObjectId(OID)}}).sort({_id:-1});
db.test.find({_id:{$gt:ObjectId(OID)}}).sort({$natural:-1});
などが思い当たりますよね。

ここでOIDは、4つに分けて
536700f5 80bedc 359f 275bc9
the seconds since the Unix epochとmachine identifierとprocess idとcounter
http://docs.mongodb.org/manual/reference/object-id/
らしいから、

これだと秒まで同じドキュメントが複数あって、それらが違うmachine idの場合に対応できないよね。

oidの2つ目のmachine idって

mongo localhost/test1 insert.js
536700f5 80bedc 359f 275bc9

mongo 127.0.0.1/test2 insert.js
536701af dc8c4c 3ebe 80a615

mongoシェルからやったら
53670229 daa151 cae9 41c342

みたいに
同じマシンでもinsertの仕方によっても違うし。

つまり、oidでsortしてもね。

ということで、1秒以内に書き込まれることを考慮したら、
.find({_id:{$gt:ObjectId(OID)}}).sort({_id:-1})では最新を取得できないよね?と思うのですよ。

ということでやっぱり自前のミリ秒くらいまでの時刻フィールド{ts : new Date()}を追加してそれで、
.find({ts:{$gt:timestamp}}).sort({ts:-1})
かつ取ってきたドキュメントでまた持ってないOIDだけに制限して使うことにするわ。


もっといいやり方ないんかね。

2012/07/05

Flex4.6にて
ViewNavigatorApplicationにおいてdestructionPolicy="never"でView遷移するときの動作についてです。
普通は、↓のようにして、pushView/popViewで遷移して、HomeViewのみインスタンスは1つだけ
という動作になります。(NextViewは毎回インスタンスが生成されます。)

これで、HomeViewにNEXTボタン、NextViewにBACKボタンを定義して
それぞれpushView/popViewで遷移するようにして、
add/creationComplete/viewActivate/viewDeactivateのイベントを定義すると
次のような順番に処理が行われます。


HomeView addHandler
HomeView creationCompleteHandler
HomeView viewActivateHandler
--push NEXT button--
NextView addHandler
NextView creationCompleteHandler
HomeView viewDeactivateHandler
NextView viewActivateHandler
--push BACK button--
HomeView addHandler
NextView viewDeactivateHandler
HomeView viewActivateHandler     createしていない
--push NEXT button--
NextView addHandler
NextView creationCompleteHandler
HomeView viewDeactivateHandler
NextView viewActivateHandler

NextViewからHomeViewに戻るときにcreateしていないことがわかります。


ここで問題。


私が作りたいアプリは、HomeViewではなくNextViewのインスタンスを1つにして、
NextViewのcreateを1回だけにしたかったのです。
いろいろ悩んた結果、次のようにしました。


NEXTボタン
 1回目HomeViewからNextViewに遷移するときは、replaceViewにして、
 2回目からは、popViewで遷移します。
BACKボタン
 NextViewからHomeViewはpushViewで遷移します。


そうすると、次のような順番で処理が行われ、
HomeViewではなく、NextViewのインスタンスを1つに保つことができました。



HomeView addHandler
HomeView creationCompleteHandler
HomeView viewActivateHandler
--push NEXT button--
HomeView [navigator.replaceView(NextView)]
NextView addHandler
NextView creationCompleteHandler
HomeView viewDeactivateHandler
NextView viewActivateHandler
--push BACK button--
NextView [navigator.pushView(HomeView, "pop")]
HomeView addHandler
HomeView creationCompleteHandler
NextView viewDeactivateHandler
HomeView viewActivateHandler
--push NEXT button--
data=pop
HomeView [navigator.popView()]
NextView addHandler
HomeView viewDeactivateHandler
NextView viewActivateHandler     createしていない


dataを用いて、1回目と2回目を区別するようにする場合、こんな感じです。

// HomeViewのNextボタン押下時
protected function btnNext_clickHandler(event:MouseEvent):void
{
 if(data == null){
  trace("HomeView [navigator.replaceView(NextView)]");
  navigator.replaceView(NextView);
 } else {
  trace("data=" + data);
  trace("HomeView [navigator.popView(slideLeftTran)]");
  navigator.popView(slideLeftTran);
 }
}
でもちょっとむりくり感があります。
もっと簡単にインスタンスを1つにする方法はないのでしょうかね。