mojavy.com

細かすぎて伝わらないAndroid開発のはまりどころまとめ その1

November 07, 2012 at 12:00 PM | categories: android, tips |

android

これまでandroidアプリを開発しててはまったことがたまってきたのでまとめておきます。順不同です。 その2はまたねたがたまってきたらたぶんそのうち。

目次

onAnimationEndでviewの階層を操作するとNullPointerExceptionでおちる

Viewをフェードアウトして親Viewからremoveする、というような動作をしたい場合に、普通にonAnimationEndの中でremoveViewとかするとNullPointerExceptionでおちます。onAnimationEndの中でViewの階層構造を操作するような処理をしてはだめらしいです。回避するには、Handlerをつかってタイミングをずらしてやるとよいです。

Animationが動かない

AnimationさせるViewには親Viewが存在している必要があります。WindowManagerはViewではないので、WindowManagerにaddViewしたViewをアニメーションさせたい場合は空のRelativeLayoutとかにaddViewしてから、RelativeLayoutのほうをWindowManagerにaddViewしてやる必要があります。

WindowManagerにaddViewしたときの挙動

WindowManagerにもaddViewできますが、通常のViewとは挙動が違います。

  • 背景透過はWindowManager.LayoutParam.format に TRANSLUCENT をセットすればよいです。
  • dimでフェードインできますが、その際のdurationを変更する方法は分かりませんでした。
  • BACKボタンはきかなくなります。自分でKeyEventを処理してやる必要があります。android.widget.PopupWindowのdispathKeyEventのソースが参考になります。

Activityが横向きでスタートした場合と縦向きでスタートしたときで表示倍率が違う

onCreateが何回もよばれる

回転やキーボード表示のタイミングでもonCreateがよばれます。AndroidManifest.xmlでconfigChangesを設定することで回避できます。

popupWindowのsetWidth, setHeightは次回以降の表示サイズしか変えられません。既に表示しているポップアップウィンドウのサイズはそのままです。invalidateしても無駄です。

HttpURLConnectionが 0byteのresponseを返す

コネクションプールとkeepaliveがらみで問題が発生する場合があるみたいです。SDKのバージョンとウェブサーバ側の設定も影響します。 System.setProperty("http.keepAlive", "false") で回避はできるようです。これに遭遇したときは、org.apache.http.impl.client.DefaultHttpClientの方を使うことにしたので詳細は追ってません。

org.apache.http.impl.client.DefaultHttpClientがすごく遅い

httpsでリクエストを投げると、ウェブサーバ側の負荷が高いわけでもネットワークが細いわけでもないのに、返ってくるまでなぜか数秒かかる場合があります。こちらもkeepaliveがらみの問題っぽいです。これもウェブサーバ側の設定が影響します。 試した限りでは以下のような状況でした。

  • setHeader("Connection", "close") しても効果なし
  • setKeepAliveStrategyでdurationを 0とか1にしても効果なし
  • Connection closeしないウェブサーバならすぐレスポンスが返ってくる
  • httpならすぐレスポンスが返ってくる

ここ( http://hc.apache.org/httpclient-3.x/sslguide.html ) のKnown limitations and problemsをみるとそれっぽい既知の問題があるようですが、根が深そうだったので詳細は追ってません。

eclipseのAndroid pluginが動かなくなった

なぜかeclipseでAndroid pluginが動かなくなるときがありました。詳細をメモるのを忘れてしまいましたが、以下の手順で直ったような気がします。

  1. Android Support Libraryをアンインストール
  2. eclipse再起動
  3. 新しいAndroidプロジェクトを作るとダイアログでライブラリのインストールを促されるのでそれに従う
  4. android プラグインをアップデート

WebViewで表示されるコンテンツが小さすぎる

通常ビューのスケールとWebViewのスケールは別です。setScaleで調整する必要があります。 これはたぶんiOSでも同様かと。

java.lang.RuntimeException: Stub!

android.jar内のコードはdalvikvmの外で実行することはできません。問答無用でタイトルの例外が飛びます。 エラーメッセージはもうちょいなんとかならなかったのか。

参考

jarとして配布するandroidライブラリ内にリソースを埋め込むことはできない

リソースIDを列挙しているRパッケージはjarにそのまま入れることはできますが、そのリソースIDは不正なものとなります。 ライブラリにリソースを含めたい場合は、ソースも含めたプロジェクトをまるごと配布するしかないようです。

ごく小さなアイコン画像だけとかであればバイナリデータをソース中に埋め込んでしまう、というのも手です。 iOSならBundleという仕組みがあります。

android-maven-plugin から mvn eclipse:eclipse でeclipse用にエクスポートすることはできない

androidでもmavenは使えますが、androidのmavenプロジェクトは通常の方法(mvn eclipse:eclipse)ではeclipseにインポートできません。 以下のファイルを手動でつくってみたらとりあえずいけました。

  • .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
        <classpathentry kind="src" path="src/main/java"/>
        <classpathentry kind="src" path="gen"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry kind="output" path="bin/classes"/>
</classpath>
  • .project
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        <name>project-name</name>
        <comment></comment>
        <projects>
        </projects>
        <buildSpec>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>org.eclipse.jdt.core.javabuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
                <buildCommand>
                        <name>com.android.ide.eclipse.adt.ApkBuilder</name>
                        <arguments>
                        </arguments>
                </buildCommand>
        </buildSpec>
        <natures>
                <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
                <nature>org.eclipse.jdt.core.javanature</nature>
        </natures>
</projectDescription>
  • project.properties
# Project target.
target=android-10

# if it is a library
# android.library=true

まあ、なんというか、Androidはいろいろ残念ですね。

iOSはこういう仕様なのかバグなのかよくわからないようなものが少ないし、OSバージョンの入れ換わりが早くて対応バージョンも少なくて済む分、個人的な体感ではandroidアプリの工数はiOSの3割増しという感じ。



UbuntuでPDFの日本語フォントが表示できないときの対処メモ

November 02, 2012 at 12:00 PM | categories: pdf, tips, ubuntu |

ubuntu

Ubuntu 12.04 で日本語フォントのはいったpdfを開くと、日本語の部分が空白になって以下のようなエラーログが表示されてしまっていた。

Error (13373): No font in show/space
Error (13412): No font in show/space
Error (13497): No font in show/space
Error (13515): No font in show
Error (13555): No font in show/space
Error (13572): No font in show
Error (13607): No font in show/space
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Missing language pack for 'Adobe-Japan1' mapping
Error: Unknown font tag 'C0_0'
Error (231): No font in show
Error: Unknown font tag 'C0_1'

pdfビューワはDocument Viewerでもokularでも同様だった。

そこで、このあたりを参考に、

sudo apt-get install poppler-data

としたらちゃんと表示されるようになった。



Quick links

October 31, 2012 at 11:30 PM | categories: quicklinks |

jack

もう11月ですね。前回に引き続き今後のネタのメモとか。

Impara

GoogleのDremelに触発されてつくったものとのこと。MapReduce以外の選択肢が増えてくると、pigみたいな高級言語の重要度があがってくるかもしれないですね。

米Yahoo!、IE10のDo Not Trackを無視

ちょっと前に、ApacheがIE10のDNTを無視するパッチをだしてましたが、これも影響してるのだろうか。 ちなみにこのパッチをコミットしたのはこの人らしい。

supersonic

名前からしてすごそうですね。これをうまく使えれば、下手にhadoop使うより大量にメモリ積んだマシン1台でがんばれるシチュエーションが増えそう。

List::FrontCode

積読状態だったWEB+DB PRESS総集編のバックナンバーをまじめに消化してたら、Vol.42のアルゴリズム&データ構造の記事がおもしろかった。naoya氏を見習って自分で実装してみたいと思います。

ipad miniとかkindleとかwindows surfaceとか

kindleのpaperwhite予約しました。



Common Lisp練習 - CodeChef : TSORT

October 24, 2012 at 06:00 PM | categories: programming, common lisp |

codechef

Common Lispの練習にCodeChefの↓の練習問題をやってみた。

http://www.codechef.com/problems/TSORT

問題自体は全然難しくないけど、Common Lispで解こうとしたらTime Limit Exceededでおちてしまった。

最初は以下のように書いて、

(let ((_n (parse-integer (read-line)))
      (lis ()))
  (dotimes (i _n)
    (push (parse-integer (read-line)) lis))
  (setf lis (sort lis #'(lambda (x y) (< x y))))
  (dolist (x lis) (format t "~a~%" x)))

以下の用にして時間を測ったところ

$ time ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}' | sbcl --script turbosort.cl > /dev/null
ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}'  1.19s user 0.01s system 91% cpu 1.311 total
sbcl --script turbosort.cl > /dev/null  3.42s user 0.43s system 97% cpu 3.938 total

ローカルだと3.42s程度だった。codechef上での制限は5secなのでセーフかと思ったけどTime Limit Exceededだった。

そこで、vectorを使うように改良

(let* ((_n (parse-integer (read-line)))
       (lis (make-array _n :fill-pointer 0)))
  (dotimes (i _n)
    (vector-push (parse-integer (read-line)) lis))
  (setf lis (sort lis #'(lambda (x y) (< x y))))
  (loop for i across lis do (format t "~a~%" i)))
$ time ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}' | sbcl --script turbosort.cl > /dev/null
ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}'  1.21s user 0.01s system 94% cpu 1.289 total
sbcl --script turbosort.cl > /dev/null  2.64s user 0.44s system 98% cpu 3.137 total

若干改善されたが、まだTime Limit Exceededだった。

read-sequenceで読み込んだほうが早いかと思って以下のように書いてみた。

(defun parse-input (str)
  (loop
     for i = 0 then (+ 1 j)
     as j = (position #\Newline str :start i)
     as k = (parse-integer (subseq str i j) :junk-allowed t)
     if (not (null k))
     collect k
     while j))

(let* ((_n (parse-integer (read-line)))
       (lis (make-array (* _n 20) :element-type 'character))
       (nums ())
       )
  (read-sequence lis *standard-input*)
  (setf nums (sort (parse-input lis) #'(lambda (x y) (< x y))))
  (loop for i in nums do (format t "~a~%" i)))
$ time ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}' | sbcl --script turbosort.cl > /dev/null
ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}'  1.13s user 0.01s system 97% cpu 1.159 total
sbcl --script turbosort.cl > /dev/null  3.67s user 0.48s system 96% cpu 4.297 total

残念ながら逆に遅くなってしまった。parse-inputの部分で60%くらい時間がかかっていた。 あと、#'(lambda (x y) (< x y))の部分を #'<にするとなぜか遅くなる。

まだ誰もlispではパスしてない模様。こういうのをもっと高速に書く方法あるのだろうか。

ちなみにCだと余裕。ローカルだと0.2秒くらいだけどリモートでは3秒くらいかかってた。そもそもCodeChefの実行環境がしょぼすぎる疑惑が。。

#include <stdio.h>
#include <stdlib.h>

int f(const void *i, const void *j) {
    return *((int*)i) > *((int*)j);
}

int main(void) {
    char buf[256];
    int num = atoi(fgets(buf, 256, stdin));

    int lis[num];
    for (int i = 0; i < num; ++i) {
        lis[i] = atoi(fgets(buf, 256, stdin));
    }
    qsort(lis, num, sizeof(int), f);
    for (int i = 0; i < num; ++i) {
        printf("%d\n", lis[i]);
    }
$ time ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}' | ./a.out > /dev/null
ruby -e 'n=1000000;puts n; n.times{puts (rand * 10000000).to_i}'  0.99s user 0.01s system 99% cpu 1.006 total
./a.out > /dev/null  0.18s user 0.01s system 17% cpu 1.116 total


twitter apiで404: {"errors":[{"message":"Sorry, that page does not exist","code":34}]}

October 18, 2012 at 10:00 PM | categories: web, twitter |

twitter

最近twitter apiをつかっているサービスで以下のようなエラーがでた。

{"errors":[{"message":"Sorry, that page does not exist","code":34}]}

twitterのデベロッパフォーラムによると、先週くらいにバージョンがついてないエンドポイントは /oauth を除いて廃止されたらしい。また、ドメインもapi.twitter.comに統一されたらしい。

つまり、api.twitter.com/account/verify_credentials.json とか twitter.com/1/account/verify_credentials.json とか twitter.com/account/verify_credentials.json ではだめで、api.twitter.com/1/account/verify_credentials.json を使えということ。

ログイン直後にverify_credentialsをつかってるアプリは多いと思われるが、その場合ログインに失敗したように見えるので認証まわりをライブラリ任せにしてると原因がわかりにくいかも。

とりあえずtwitterの開発ブログまめにチェックしたほうがよさそう。

参考



About Me

pic
mojavy

Recent posts






Categories



Badges