Blogを移転します。
今まではこのcocologを使っていたのですが、
以前から気になっていた、Bloggerに移転したいと思います。
基本的に新しい記事はBloggerの方に書いていきます。
基本的に技術的なネタを投稿するようにしたいと思っています。
| 固定リンク
| コメント (0)
| トラックバック (0)
今まではこのcocologを使っていたのですが、
以前から気になっていた、Bloggerに移転したいと思います。
基本的に新しい記事はBloggerの方に書いていきます。
基本的に技術的なネタを投稿するようにしたいと思っています。
| 固定リンク
| コメント (0)
| トラックバック (0)
最近、ButtonのOnClickListenerを実装するのが面倒なので、レイアウトXMLのonClickを利用しているのですが、Dialogでも同じように使おうとしたところ、
以下のメッセージと共に、java.lang.IllegalStateException例外が発生しました。
「Could not find a method buttonClick(View) in the activity」
その時はOnClickListenerを実装した方が早かったので、深く調べなかったのですが、
たまたま思い出したので調べてみました。
※今回はAndroid2.2のソースコードを追いかけました。1.6でも同様の現象に
ぶち当たるのではないかと思います。
実際、レイアウトXMLのOnClickが設定される場所は、Viewクラスにあります。
case R.styleable.View_onClick: if (context.isRestricted()) { throw new IllegalStateException("The android:onClick attribute cannot " + "be used within a restricted context"); } final String handlerName = a.getString(attr); if (handlerName != null) { setOnClickListener(new OnClickListener() { private Method mHandler; public void onClick(View v) { if (mHandler == null) { try { mHandler = getContext().getClass().getMethod(handlerName, View.class); } catch (NoSuchMethodException e) { int id = getId(); String idText = id == NO_ID ? "" : " with id '" + getContext().getResources().getResourceEntryName( id) + "'"; throw new IllegalStateException("Could not find a method " + handlerName + "(View) in the activity " + getContext().getClass() + " for onClick handler" + " on view " + View.this.getClass() + idText, e); } } try { mHandler.invoke(getContext(), View.this); } catch (IllegalAccessException e) { throw new IllegalStateException("Could not execute non " + "public method of the activity", e); } catch (InvocationTargetException e) { throw new IllegalStateException("Could not execute " + "method of the activity", e); } } }); } break;
handlerName変数には呼び出されるはずのメソッド名が設定されています。
ポイントは、以下のコードになります。
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
この部分で、クラス内にOnClickで設定したメソッドがあるかどうかを確認しています。
さて、今回の現象はActivityだとメソッドが発見できて、Dialogだと発見出来ないわけですから、getContext().getClass()で返されるクラスのインスタンスが違ってそうな気がします。
ということで、Dialog#onCreate(setContentView()を呼び出した直後)で
Log.d("TEST", "ClassName = " + getContext().getClass().getName());
なんてことをしてみました。
すると、出力されたログをみると、
ClassName = android.view.ContextThemeWrapper
と出力されました。
Activityだと同じ事ができないのですが、恐らく、getContext()がActivityのインスタンスを返すのだろうと思われます。
Activityのインスタンスであれば、自分で実装してあれば、メソッドが発見できますが、DialogでgetContext()するとContextThemeWrapperが返ってくるため、
OnClickのメソッドが発見出来ないわけです。
ちなみに、Dialog#getContext()が返す、Contextは、以下の通りです。
mContext = new ContextThemeWrapper( context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme); public final Context getContext() { return mContext; }
ということで、結論は、「DialogではレイアウトXMLのOnClickは使えない」と言うことがわかりました。
DialogではおとなしくOnClickListenerを実装しましょう。
| 固定リンク
| コメント (1)
| トラックバック (0)
今、専門学校の授業の一環で、私が担当するクラスの生徒たちが
ModxというPHPのCMSのソースコードを
読み、その結果から資料を作るという事をしています。
もうすぐ、Modxのカスタマイズもやるそうです。
4月から始まって、2か月半が経過しました。
聞こえてくる言葉は「ソースコードが汚い。」「何をしているかわからない」
と言った、マイナスな言葉が多く聞こえてきていますが、
私がたまに質問を受けて、ソースコードを見てみると、そうでもなく、
処理を追いかける事ができます。
(実際読んで頂ければわかりますが、汚いとは思えません。
プログラムの設計思想などを議論するつもりもないです。それは、
人それぞれだと思いますので。)
最初は、「そんなに汚いコードでもない」と思っていたのですが、
冷静に分析すると、これまでプログラムと格闘してきた経験の差と
言うことなのかもしれません。
ソースコードの読み方を教える事はできないかもしれませんが、
ソースコードを読むためのヒントは教える事ができるのかもしれないなと
思いました。
一般的(IT企業とか)にはどういう風に教えているのでしょうね。
| 固定リンク
| コメント (1)
| トラックバック (0)
先週末の事ですが、第7回中国GTUG勉強会@広島を開催しました。
今までは、岡山での開催ばかりで、以前から「広島開催」の希望が
ありました。
これまで、場所を確保することが問題となっていました。
(私が岡山在住であるので、広島で借りられる会議室がどこにあるのか。
会議室を県外の人が借りられるのかという問題があるため、
私が直接行動に移すことが難しかった)
しかし、3月の日本Androidの会中国支部勉強会で名刺交換をさせて
いただいた、広島国際学院大学の先生にメールでお願いをしてみたところ、
快諾していただきました。
ということで、開催にこぎつける事ができました。
今回は、ひとまず知っている人に講師をお願いしました。
キャンセルの想定をしていたので多めにお願いをした所、
お願いした全ての方にOKの回答を頂くことができました。
ということで、後は、当日参加していただいた方には
楽しんでいただいたような状況となりました。
第7回はスタッフ込みで40名弱の参加をしていただきました。
たくさんの希望を頂いたので、タイミングが合えばまた
開催をしたいと思いますのでよろしくお願いします。
広島で場所を確保してもらえるようにスタッフもそろそろ
お願いしようと思っています。(何人かの方には立候補していただいたので
その中から1人にお願いしようと思っています)
| 固定リンク
| コメント (0)
| トラックバック (0)
専門学校の授業中にXAMPP Ver1.7.4をインストールして、PHPとMySQLを使って
授業をしています。
そろそろPHPの授業でデータベース連携の内容に入ろうとした所で
事件が起こりました。
「MySQLに登録したデータ(日本語)がすべて文字化けする。」
ということで、調べてみました。XAMPP Ver1.7.4の時点ではMySQLの標準文字コードはlatin1のようです。(?)
PHPの方は文字コードをUTF-8に変更しているので、PHPMyAdminから
追加、更新すると文字化けした状態で登録されてしまいます。
(mysqlクライアントからも同様の結果になりました。
set names sjisしても文字化けが直りませんでした。。これだと無事更新できそうだけど…?)
結局、MySQLの設定ファイルmy.iniを修正して、デフォルトの文字コードを
変更すれば修正できそうだという情報を見つけたので、以下の記述を追加しました。
[XAMPPインストールフォルダ]¥mysql¥bin¥my.ini
[mysqld]
character-set-server = utf8
skip-character-set-client-handshake
[mysqldump]
default-character-set=utf8
[mysql]
default-character-set=utf8
character-set-serverの設定名は、
古いバージョンだと、default-character-setになるようです。
サーバを再起動すると、無事更新できるようになるかと思ったのですが、
文字コードを指定する前に作成したデータベースに関しては、文字コードが
設定されているようで、この設定では反映されませんでした。
なので、以下のクエリを実行して、デフォルトの文字コードを変更します。
ALTER DATABASE sampledb default character set=utf8;
これでも、すでに登録されたデータに関しては復活しないようなので、
テストデータに関しては諦めるしか無いのかもしれません。。。
| 固定リンク
| コメント (1)
| トラックバック (0)
今日、ある方がTwitter上で起動元のActivityを閉じるにはどうするか?
みたいな事をつぶやかれていたので、色々試したことを記述しておくことにする。
で、ドキュメント的にはActivity#finishActivity()を呼び出せば、呼び出し元の
Activityをfinish()する事ができるようだが、実際に1.6 on HT-03Aで動かしてみると
想定した動きにならなかった。
で、finishActivity()のソースコード(v1.6_r2)を見てみると、以下のソースコードだった。
/** * Force finish another activity that you had previously started with * {@link #startActivityForResult}. * * @param requestCode The request code of the activity that you had * given to startActivityForResult(). If there are multiple * activities started with this request code, they * will all be finished. */ public void finishActivity(int requestCode) { if (mParent == null) { try { ActivityManagerNative.getDefault() .finishSubActivity(mToken, mEmbeddedID, requestCode); } catch (RemoteException e) { // Empty } } else { mParent.finishActivityFromChild(this, requestCode); } }
mParentという変数は、呼び出し元Activityと思われるが、この変数に
Activityのインスタンスがセットされていれば、呼び出し元Activityが
無事finishできるようです。
しかし、mParentにインスタンスがセットされるような箇所が存在しませんでした。バグなんですかね…?
ついでに、ドキュメント上、呼び出せと言われているstartActivityForResult()の
ソースコードは以下です。
/** * Launch an activity for which you would like a result when it finished. * When this activity exits, your * onActivityResult() method will be called with the given requestCode. * Using a negative requestCode is the same as calling * {@link #startActivity} (the activity is not launched as a sub-activity). * *Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may * not get the result when you expect. For example, if the activity you * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * *
As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your * activity, then your window will not be displayed until a result is * returned back from the started activity. This is to avoid visible * flickering when redirecting to another activity. * *
This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } } else { mParent.startActivityFromChild(this, intent, requestCode); } }
すでにmParent変数を参照して動作を振り分けるようになっています。
しかも、mParent変数に値をセットしている場所もない…。
これはどういう事なんだろうか…。
最後にmParent変数へのsetterを見つけたので転載しておきます。
// ------------------ Internal API ------------------ final void setParent(Activity parent) { mParent = parent; }
どうやら、setterは非公開APIのようですので、普通にアプリケーションを
作成するためにはfinishActivity()を使って呼び出し元Activityを閉じるという
事はできなさそうです。
| 固定リンク
| コメント (0)
| トラックバック (0)
先週の土曜日のことを今書くのは遅いと思ったのですが、
これまでのオープンセミナーと違った役回りでの関わり方だったので
書いておこうと思います。
今年のオープンセミナー2011@岡山は、実行委員長だった昨年までと
違って、スタッフとしての参加でした。
私の時と違って、ミーティングも何回もこなし、
着々と準備を進めていきました。
私は今年は、会計係ということで、収支と現金の管理をしました。
昨年は金額が合わないなどいろいろと面倒になった経緯を踏まえ、
あくまでも「私の手元に来たお金」と「私が出したお金」のみを
管理することにしました。
ということで、受付時に受け取り忘れたり、お釣りを間違えたなどという
点については無視しました。
(人的ミスについてはどうすることもできないので)
で、お金の管理とサイン会、途中から受付などをやっていたら、
今年もほとんど話が聞けませんでした。
そして、参加者との挨拶もろくにできず、少し残念な感じがしました。
ただ、これは裏方スタッフとしての動きをして運営をサポートしていれば
仕方のないことだと思います。
来年は当日運営スタッフだけでなく、事前準備の運営スタッフへの
参加を期待します。
そして、年々スタッフが減っている(特に事前準備スタッフ)ので
もし協力していただけるなら協力していただけると助かります。
来年の実行委員長はきよくらさんが担当されるということで、
私、ひらさんと、また違ったオープンセミナー@岡山を企画して
いただけると思います。
最後に、今の私を作るきっかけになった「オープンセミナー@岡山の実行委員長」
という役目を若い人に担当していただきたい。
「岡山で最大のイベント」を企画し、運営をしたという実績は
色々な面で助けてくれる武器となると思います。
そして今年もまだ私が「実行委員長」というのもありましたので
早く、フェードアウトしたいと思っています。
(当然「元」実行委員長であることは間違いないのですが、
その年の「顔」は当然その年の実行委員長ですので
できる限り立ててあげたいと思います)
そろそろ、また一人の観客としてオープンセミナー@岡山に関わりたいかな?
| 固定リンク
| コメント (0)
| トラックバック (0)
SahanadroidでBasic認証を使って認証をしようとしているのですが、
AndroidからBasic認証を実行する事ができなくてハマっています。
Internet上の情報を探してみると大体の方が、
client.getCridentialProvider().setCridentials()を利用しているようですが、
tcpdumpコマンドでパケットをキャプチャしてみると、
Authorizationヘッダが付加されない現象に遭遇しています。
今回は、tcpdumpコマンドのメモと参考サイトを紹介しようと思います。
解析がとても楽になりました。
tcpdumpコマンド[ITPro]
http://goo.gl/OGDe9
コマンド例(for Mac)
sudo tcpdump -i en1 -X -vvv port 80 and host japan.sahanafoundation.org
| 固定リンク
| コメント (0)
| トラックバック (0)
GWあけてから、職業訓練校でAndroidの授業のチューターのバイトを
することになりました。
専門学校の授業もあるのと、給与面で折り合いがつかなかったので、
専任の講師としては関わらないことにしました。
そこで、今はAndroidの基本からスタートしているのですが、
私もまだまだ基礎ができていない部分があるなと痛感しました。
(実際には問題はタイプミスが多いのですが、そこに到るまでに
苦戦した回数が今日は多かった)
よく見る所は、タイプミスをすぐ発見できるのですが、
例えば、<FrameLayout xmlns:android="http://…
の所のタイプミスは授業時間内に発見できませんでした。
でも、コンパイルは通りますし、実行すると即落ち+
「Binary XML file line #18: You must supply a layout_width attribute」
という、layout_widthが設定出来ていないという意味の例外メッセージが
でるだけです。
この時に、android:layout_width="fill_parent"の記述が
正しい場合は何のエラーなのか???となりました。
ただし、android:layout_widthは必ず指定しなければいけないので
記述がない場合も同様に落ちます。
答えは、xmlns="http;//…"とスキーマの「:」が「;」に
なっていただけでした。
こういう時に原因がすぐに発見できなかったのは痛かったです。
(本当はIDEで自動生成するので本来はそんなに編集するような場所では
ないと思うのですが)
xmlnsの意味などもしっかり押さえないといけないなと思いました。
# 某Ustでantビルドでの周回遅れ勉強会が放送されていますが、
# ああいう所では上記のような状況が発生するのかな?
職業訓練校もバイトという立場での関わりとなりますが、
生徒達の成長を見守りたいと思います。
| 固定リンク
| コメント (0)
| トラックバック (0)
TextViewに下線を引く処理をアプリケーションに実装していたのですが、
AutoLink属性を使うことにしましたので、
処理が不要になりました。
しかし、そのまま消してしまうのももったいないので
ここに控えておくことにします。
(XMLからでも設定できたかな…?)
import android.text.Spannable;
import android.text.style.UnderlineSpan;Spannable t = Spannable.Factory.getInstance().newSpannable(strHandlingUrl);
UnderlineSpan us = new UnderlineSpan();
t.setSpan(us, 0, strHandlingUrl.length(), t.getSpanFlags(us));
txt.setText(t, TextView.BufferType.SPANNABLE);
| 固定リンク
| コメント (0)
| トラックバック (0)