2012/11/25
Android ActionBarCompatでAndroid 2.xでもタブ+Fragmentを使う時にアクションボタンが切り替わるようにする
ActionBarCompatRev
ActionBarを使ったスタイルはAndroid 3.0以降で利用できますが、
実際にアプリ開発をするとなると、まだまだAndroid 2.3などの下位バージョンを
考慮する必要があり、デザイン・仕様を共通化するために前述のActionBarCompatなどを
使う必要があります。
もちろん、既にActionBarSherlockのような非常に高機能なライブラリも出ていますが
高機能ゆえにサイズも大きい、もしバグ(もしくは期待しない挙動)があったときに手を入れるのが難しい、など採用しにくいケースもあると思います。
そこで、規模が小さく内容を把握しやすいActionBarCompatを使おうと思ったのですが、問題だったのが、Tabを使ったレイアウトだとAndroid 2.xで動かした時に、タブ(=Fragment)を切り替えてもアクションボタンが切り替わらないということです。
ActionBarCompatのソースコードを読んでいくと、Fragmentのメニュー(onCreateOptionsMenu())が呼び出されるのはActivityが切り替わったタイミングだということが分かります。
なので、タブを使う場合のように1つのActivityの中で複数のFragmentが切り替わっていくパターンではFragmentごとにメニューを読み込んでくれません。
冒頭に書いたライブラリは、ActionBarCompatのこの点を改良したものです。
ライブラリを使ったサンプルを付けていますので、同じような問題に遭遇した方はお試しいただければと思います。
使うには、まずこのライブラリをAndroid Library Projectとして組込みます。
2012/10/27
Android 端末情報を確認・共有するアプリ
アプリが使う機能にもよりますが、想像以上に機種間の差はあったりするので検証する端末の選定は重要です。
しかしながら、キャリアやメーカーから公開されている仕様だけでは不十分なことが多く、もっと多くの情報を収集したいものです。
端末の情報を表示するアプリは既に多数ありますが、これをサーバへ送信して皆が見られるようにするためのアプリを公開しました。
DeviceInfo
名前が普通過ぎるので、アプリ名で検索すると残念ながら多数ヒットするのですが…。
このアプリのメニューから「送信」とすると、サーバへ端末情報が送られます。
もちろん、個人を特定するような情報は送っていません。
ファイルへのエクスポートもできます。
サーバサイドのアプリは現時点で準備中ですが、下記のような一覧が見られる予定です。 あとは如何に多くの端末情報が集められるかが課題ですね。
Android Intentでテキストを共有する時のタイトル
IntentのExtraにテキストデータを入れて共有するとき、以下のようにすると思います。
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("text/*"); intent.putExtra(Intent.EXTRA_SUBJECT, "something");このとき、Intent#putExtra()の第1引数がIntent.EXTRA_TITLEだとEvernoteなどはタイトルとして認識してくれますが、Gmailなどは認識しません。
メール系のアプリでもタイトルとして扱われるようにするには、Intent.EXTRA_SUBJECTとする必要があるようです。 EvernoteはIntent.EXTRA_SUBJECTでもタイトルとして扱っており、こちらの方が適用範囲が広いかもしれません。
Heroku + Node.js + Express + Mongoose
{ "name": "hoge", "version": "0.0.1", "private": true, "dependencies": { "express": "3.0.0", "mongoose": "1.7.4", "jade": "*" }, "engines": { "npm": "1.1.41", "node": "0.6.13" } }
2012/10/18
Android keystoreの操作
keystoreの変更操作は、バックアップを取ってから実行した方が良いです。
■keystore内のエントリの確認方法
keytool -list -keystore keystoreファイル名 -storepass パスワード
■keystoreのキー(エントリ)のパスワード変更方法
keytool -keypasswd -alias エイリアス -keypass キーのパスワード -new キーの新しいパスワード -keystore keystoreファイル名 -storepass keystoreのパスワード
■keystore自体のパスワード変更方法
keytool -storepasswd -keystore keystoreファイル名 -storepass keystoreのパスワード -new keystoreの新しいパスワード
■keystore内のエントリの削除方法
くれぐれも、必要なエントリをうっかり削除しないように気をつけてください。
keytool -delete -keystore keystoreファイル名 -alias 削除対象エントリのエイリアス -storepass keystoreのパスワード
Android keystoreのエイリアス変更方法
keystoreのエイリアスを変更する方法です。
keystoreを作り直せば良い話ですが「もうこのkeystoreで署名したAPKは出回ってしまってるのでkeystoreを作り直すことはできない」という場合に使えそうです。
keytool -changealias -alias 現在のエイリアス -destalias 新しいエイリアス -keystore keystoreファイル名 -storepass パスワード
2012/09/09
Android adbコマンドで特定端末を簡単に指定
ADBS - github
これを使うと、シリアル番号の最初の1文字を入力するだけで実行できます。
$ adb devices
List of devices attached
304D19E0D41F543F device
275501700028393 device
となっているときに、304D19E0D41F543Fの端末に対してshellコマンドを実行するには
$ adbs -s 3 shell
shell@android:/ $
とするだけです。一覧を見てから実行したければ'-s'オプションを外して
$ adbs shell
List of devices attached
[3] 304D19E0D41F543F
[2] 275501700028393
1st character of the serial number you want to use: 2
shell@android:/ $
とできます。
もしシリアル番号の先頭文字が同じ端末があった場合、シリアル番号を前方一致で探しているので
$ adbs -s 30 shell
のように2文字目以降も指定すれば動くはずです。
2012/08/19
Android TextViewのURLをリンクにしつつURL以外もクリック可能にする
それに加えて、URL以外の場所をクリックした場合はそのイベントを拾いたかったのですが、なかなかその方法が見つからず苦労したので、ここに整理したものを公開します。
同じことをされたい方がいらっしゃいましたらどうぞご利用ください。(LinkUtils.java)
※もう一つのActivityは使用例です。
https://gist.github.com/3394338
String testStr = "URLの形式のみブラウザで開きます。http://www.yahoo.co.jp/とhttp://d.hatena.ne.jp/をリンク表示にしてクリック可能にしました。"; TextView textView = new TextView(this); textView.setText(testStr); LinkUtils.autoLink(textView, new LinkUtils.OnClickListener() { @Override public void onLinkClicked(final String link) { Log.i("SensibleUrlSpan", "リンククリック:" + link); } @Override public void onClicked() { Log.i("SensibleUrlSpan", "ビュークリック"); } }); setContentView(textView);
URLがクリックされたときと、その他の場所がクリックされたときをハンドリングする場合は、第2引数に専用のリスナーを設定します。
URLとして認識される文字列はLinkUtilsの中に正規表現で持っていますが、autoLink()の第3引数で変更可能です。
http://www.techmaru.net/wordpress/20101015/textviewlink/
2012/08/03
Android ViewPagerを使った円形のインジケータ
viewpagersample
既にライブラリとしてViewPagerIndicatorというすばらしいものがあります。が、別のAndroidプロジェクトをいくつも組み込むと環境構築手順やビルド手順も煩雑になりますし、単に円形タイプのインジケータを組み込みたいだけなのでこちらは使いたくない…という方がもしいらしたら、参考にしてみてください。
小さいクラスなので中身もすぐに理解できると思います。
2012/06/12
Android Theme.Lightでのダイアログの文字色
背景が白の明るい配色になり、文字色は黒系の色になります。
@android:style/Themeの場合は逆です。こちらの場合は問題ないのですが、 @android:style/Theme.Lightを使うときにダイアログを独自のレイアウトで組み立てると、 背景色は黒なのに、文字色も黒系(グレー)になってしまいます。
つまり、各TextViewに文字色を都度設定しなければならないようです。
これを避けるために、独自レイアウトの背景色がTheme.Lightと同じになるよう
テーマをカスタマイズしよう、という案を思いつきますが ダイアログの背景色を変えると、
今度は標準的なAlertDialogに影響が出ます。
AlertDialog.Builder#setView()でレイアウトを変えない普通のAlertDialogの場合、 Theme.Lightを適用していても文字色が白系のまま変わらないためです。
背景白・文字白系で非常に見にくくなります。
*AlertDialogの色を変えられるのは背景色のみのようです。
背景・文字色ともに変更ができるのは
レイアウトを指定しないAlertDialogではなく
レイアウトを指定したAlertDialogなので
レイアウトファイルの中で背景色と文字色両方を指定するのが正解なのだと思います。
ちなみに上記はAndroid 2.3.3とAndroid 4.0(エミュレータ)で確認しています。
2012/03/31
Android ListViewがクリックできない原因の一例
ListViewをカスタマイズして以下のような行のレイアウトを作成しましたが、
クリックできなくなってしまいました。
ListView#setOnItemClickListener()を使っても、クリックのイベントに反応しなくなったのです。
しかしなぜか ListView#setOnItemLongClickListener() は有効でした。
レイアウトは以下です。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="2dp"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:textSize="18sp" /> <TextView android:id="@+id/updated_at" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" /> <TextView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_below="@id/title" android:inputType="text" /> </RelativeLayout>
試行錯誤した挙げ句、原因は最後の TextView に指定している android:inputType だとわかりました。
これが設定されていると、この TextView が focusable になり、
ListViewではクリックイベントを拾えなくなるようです。
対策は、以下のように focusable="false" とすることです。
これで、ListView#setOnItemClickListener() が有効になります。
<TextView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_below="@id/title" android:inputType="text" android:focusable="false" />
2012/01/07
Android SonyTablet SをMacのadbで認識させる
SonyTablet Sを、Windowsでは接続できましたがMacで接続できず試行錯誤していましたが、
SONYのサイトに説明がありました。
http://www.sony.jp/support/tablet/products/info/sdk.html
単純に接続しただけでは以下のようになり、adbで認識されません。
% adb devices
List of devices attached
%
上記サイトの説明のようにすると、下記の通りadbでデバイスを認識するようになります。
% echo "0x54c" >> $HOME/.android/adb_usb.ini
% adb kill-server
% adb start-server
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
% adb devices
List of devices attached
4289142435fa597 device
%
2012/01/02
Android MapActivityをIntentで起動したときにNoClassDefFoundError発生
AndroidでGoogle Maps APIを使う場合に、次のようにIntentでMapActivityのサブクラスを起動するケースがあると思います。
Intent intent = new Intent().setClass(this, SampleMapActivity.class);
その際、別のプロジェクトからコピーしてきた場合などで、ある記述が抜けていると NoClassDefFoundErrorが発生してしまいます。 他の情報が全くなく、はまってしまったので対処方法を記録します。
解決策は下記の通りなのですが、uses-libraryでGoogle Maps APIを使っていることをAndroidManifest.xmlに明記する必要があります。
Cannot resolve MapActivity class on Android
具体的には以下のようにapplicationタグの子としてuses-libraryを書きます。
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme" > <uses-library android:name="com.google.android.maps" />
uses-libraryがなくてもコンパイルは成功するので、注意が必要です。