さとやn Blog

試合はRuby,勝負はC#!

Android逆引辞書

C# で Android - MonoDroid でHelloMonoDroidしてみた


MonoDevelop版が出るまでは触らないでおこうと思ったMonoDroidですが、すでにパブリックベータが公開されているようなので、とりあえずHello Worldあらため、 Hello MonoDroid をやってみました。

因みに環境は
Windows7
Visual Studio2010
です。

http://monodroid.net/Installation
上記のページの説明にしたがってJDK, Android SDK, MonoDroidプラグインをインストール。

VisualStudioを起動。新規作成で MonoDroidApplicationを選んでOK。
md01


デフォルトでこんなコードが書かれているようです。
ボタンをクリックするとそのカウントが表示されるサンプルのようです。
md02


とりあえず、書きなおす。
tv.setText("Hello MonoDroid!!");  // 今時 setXXX なんて嫌ですよねー
じゃなくて、
tv.Text = "Hello Monodroid!!"; 
です!
md03


とりあえず CRTL+F5 で実行すると、エミュレータを選択する画面が出てきますが、エミュレータはまだ起動してないので、 
Start emulator image
リンクをクリックして、事前に作成しておいたエミュレータを選択してOK。
md04
md05

エミュレータが起動 〜 アプリのパッケージング 〜 インストール 〜 起動
までVisualStudioがやってくれます。
md07
md08


無事起動。
md09

はやくMonoDevelop版出ないかな、、、。

Android自習メモ - ドロップダウンリスト

Androidでドロップダウンリストを使用する場合は、Spinnerクラスを使うようです。

Spinner is a widget similar to a drop-down list for selecting items.

とのこと。
 
Spinnerに限らず、Androidでは、リスト系のコントロールを使う場合は、
ArrayAdapterを使ってコントロールとデータをバインドして使うのが正しいやり方のようで、下の例は、res/values/strings.xml に書いた名前の一覧を単にリストで表示してみました。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    Spinner sp = (Spinner)this.findViewById(R.id.spinner1);
    
    ArrayAdapter<CharSequence> ad = ArrayAdapter.createFromResource(this,
            R.array.members, android.R.layout.simple_spinner_dropdown_item);
    
    sp.setAdapter(ad);
    
    sp.setOnItemSelectedListener(new OnItemSelectedListener() {

        public void onItemSelected(AdapterView<?> parent, View view,
                int pos, long id) {
            TextView tv = (TextView)findViewById(R.id.textView1);
            tv.setText(parent.getItemAtPosition(pos).toString());
        }

        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub
        }
    });
}

25)

Android自習メモ - データベース − データ取得

Androidは標準でSQLiteとそのライブラリが用意されているので、それを使用します。
queryというメソッドが用意されていて、select, where, order, group by, having, limit, distinct をパラメータで指定できます。
感想としては、直接SQL書かせたほうが早いような気がします。ちゃんとそれも用意されていますが。そっちは、
rawQuery という名前のメソッドで、クエリ文字とパラメータ配列を指定するもので、どう考えてもこっちの方が使いやすいと思います。

SQLiteDatabase
db = openDatabase(); // DBオープンは別項で Cursor c = db.query("テーブル名", new String[]{"name", "email", "city"}, "city=?", new String[]{"松戸"}, null, // groupby なければnull null, // having なければnull "name ASC"); ArrayList<Member> members = new ArrayList<Member>(); while(c.moveToNext()){ members.add(new Member("name", "email")); } db.close(); //オーバーロードで limit を指定できるものと、さらに distinctを指定できるバージョンが有ります。 //query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) //query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) //ちなみに生のSQLを書きたい場合は raqQuery というメソッドが使えます。
db.rawQuery( "select name, email, city from members where city=?", new String[]{"松戸"});

Android自習メモ - アラートダイアログを表示する

Androidでダイアログ(アラート、日付選択等)を表示する場合は、
Activity.showDialog(int id)
Activity.onCreateDialog(int id)
を使用する方法が推奨されているようです。
個人的にはちょっと面倒なイメージがありますが。

ボタンをクリックすると、Hello AlertDialog というアラートメッセージを表示するサンプル。
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.hello_dialog_activity);
    final Button b = (Button)this.findViewById(R.id.button1);
    b.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            showDialog(0); //このメソッドを呼び出すと onCreateDialogメソッドがコールバックとして呼び出される。引数0はとりあえず。
        }
    });
}

@Override
protected Dialog onCreateDialog(int id) {
    switch(id) {
    case 0:
        return new AlertDialog.Builder(this).setMessage("Hello AlertDialog").create();
    }
    return null;
}

id は任意の値を指定して、それに応じて、AlertDialogや、DatePickerDialogだったりを生成します。ここではcaseはいらないのですが、とりあえず。

でも、単にアラート出すだけなら
new AlertDialog.Builder.new(this).setMessage("hello alertDialog").show();
でも目的は達せられます。
違いはダイアログが呼び出し元のAcitivityにアタッチされるかされないかの違い、だそうです。
詳しくは、
http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
 

Android自習メモ - 日付フォーマット

日付(Date)を 文字列にする場合は、
DateFormatを使えば良いのですが、androidでは

java.text.DateFormat.getDateInstance()
android.text.format.DateFormat.getDateFormat(context)

どちらも java.text.DateFormat型のインスタンスを返すのですが、2つあってどちらを使えばいいのかな、どっちも同じになるのかな? 

実際やってみました。
public class Main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        DateFormat _jf = DateFormat.getDateInstance();
        DateFormat _af = android.text.format.DateFormat.getDateFormat(this);
        
        Date d = new Date();
        
        TextView tv1 = (TextView)this.findViewById(R.id.date1);
        TextView tv2 = (TextView)this.findViewById(R.id.date2);
        
        tv1.setText(_jf.format(d));
        tv2.setText(_af.format(d));
        
        Log.i("timezone",_jf.getTimeZone().getDisplayName());
        Log.i("timezone",_af.getTimeZone().getDisplayName());
    }
}

52)


何故こうなるのか、Javaとか詳しい人教えてくれると嬉しいのですが。
因みに DateFormat.getDateInstance(Locale.Japan) でロケールを指定しても同じでした。
Androidの方の言語設定を日本語にしてるんだから同じことだとは思ったのですが、、、。

Androidプロジェクトではなく、普通にEclipseでJavaプロジェクトを作成して試してみたところ、 java.text.DateFormat.getDateInstance()で取得したDateFormatオブジェクトでも意図したとおりに yyyy/MM/dd で整形されました。

まあ、わざわざ android.text.format.DateFormat 用意しているんだからこっち使えよってことなんでしょうけど、、、。ドキュメントにその辺のこと書いてあったかなぁ。

Android自習メモ - UIテスト runOnUiThreadでハマる

Androidのテストアプリ(テスト自体もいわゆるAndroidアプリなのです)から、テスト対象アプリのUIを制御する場合は、対象アプリと同じスレッドで実行する必要があるため、

Activity.runOnUiThread(Runnable action)

を使用します。

Button1にフォーカスをセットして、エンター。

public void testButton1() {
    Activity a = this.getActivity();
    final Button b = (Button) a.findViewById(対象アプリパッケージ.R.id.button1);
    
    a.runOnUiThread(new Runnable() {
        public void run() {
            b.requestFocus();
        }
    });
    this.sendKeys(KeyEvent.KEYCODE_ENTER);

}

@UiThreadTest は必要ありません!

テストクラスがinstrumentation-based classes 
実際には
ActivityInstrumentationTestCase2<T>
になるのですが、その場合は@UiThreadTestは必要がないどころか、指定してしまうと、UIスレッド以外から呼び出しが全くできなくなってしまいます。
sendKeysとかが呼び出せなくなるので、実質テストが出来ません。

じゃあ、なんで最初はエラーになったのかー、と思いよくよく見てみると、
runOnUiThread呼出の後に何の処理も記述されてないと、UIスレッドで実行されるrunメソッド内部の処理が実行される前に、テストの方のスレッドが終了しちゃってるからか? 

sendKeysとかの処理を追加したら、何ら問題なくテストできました。

詳しくは、
http://developer.android.com/guide/topics/testing/testing_android.html#UITesting
 

Android自習メモ - SMSメッセージ受信エミュレート

起動中のエミュレータにSMSメッセージを送る場合は、
telnet localhost ポート番号
で接続して、

sms send 090xxxxxxxx(適当な電話番号)送信文字

で送ることが出来ます。

ポート番号はデフォルトでは 5554ですが、複数起動している場合は、
adb devices

で起動中のエミュレータ一覧が表示され、一緒にポート番号も表示されます。 
51)


telnet接続して SMS送信
 名称未設定
 
画面上部にメッセージが表示されます。
名称未設定2
 

Android自習メモ - リソースファイルを読み込む

生リソースファイル ( res/raw ディレクトリ下にあるファイル)を読み込む場合は、
Resourceオブジェクトを取得して、openRawResource(リソースID) でストリームを取得できます。

res/raw/file1.txt というテキストファイルを用意して、そのファイルを読み込んで内容をアラートダイアログで表示する。

Resources res = this.getResources();
InputStream st = null;
try {
    st = res.openRawResource(R.raw.file1);
    byte[] buffer = new byte[st.available()];
    while((st.read(buffer)) != -1) {}
    String s = new String(buffer);
    new AlertDialog.Builder(this).setMessage(s).show();
} catch (IOException e) {
} finally{
    try{
        st.close();
    }catch(IOException e2)
    }
}



Android自習メモ - ファイルを読み込む

アプリケーションで作成したファイルを読み込む場合は、

openFileInput(ファイル名)

でストリームを取得できます。

ファイルは実際には、 /data/data/パッケージ名/files/ 下に作成されます。

FileInputStream fs = null;
try{
    fs = this.oepnFileInput("myfile.txt");
    byte[] buffer = new bytes[fs.available()];
    while((fs.read(buffer)) != -1){}
    String s = new String(buffer); 
    Log.i("mysoft", s);
}catch(IOException ioe){
    // handle exception
}finally{
    if(fs != null){
        try{
            fs.close();
        }catch(IOException ioe2){
            //handle exception
        }
    }
}


Android-ファイルに書き込む

Androidで自分のアプリ領域内で任意のファイルにデータを書き込む場合は、
openFileOutputメソッドで書き込み用のストリームを取得できます。
アクセス権限については、Contextクラスで定義されているMODE_xxxを参照。

myfileという名前のファイルに文字列 "hello world" を書き込んで保存する場合。

FileOutputStream
fs = null; try{ fs = this.oepnFileOutput("myfile", Context.MODE_PRIVATE); String data = "hello world"; fs.write(data.getBytes()); }catch(IOException ioe){ // handle exception }finally{ if(fs != null){ try{ fs.close(); }catch(IOException ioe2){ //handle exception } } }

この場合、実際には、/data/data/パッケージ名/files/

という場所にmyfileという名前のファイルが作成されます。



livedoor プロフィール
QRコード
QRコード
  • ライブドアブログ